@react-navigation/routers 6.1.5 → 7.0.0-alpha.0

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/BaseRouter.js +11 -18
  3. package/lib/commonjs/BaseRouter.js.map +1 -1
  4. package/lib/commonjs/CommonActions.js +23 -8
  5. package/lib/commonjs/CommonActions.js.map +1 -1
  6. package/lib/commonjs/DrawerRouter.js +13 -45
  7. package/lib/commonjs/DrawerRouter.js.map +1 -1
  8. package/lib/commonjs/StackRouter.js +155 -97
  9. package/lib/commonjs/StackRouter.js.map +1 -1
  10. package/lib/commonjs/TabRouter.js +28 -69
  11. package/lib/commonjs/TabRouter.js.map +1 -1
  12. package/lib/commonjs/index.js +0 -11
  13. package/lib/commonjs/index.js.map +1 -1
  14. package/lib/commonjs/types.js.map +1 -1
  15. package/lib/module/BaseRouter.js +11 -17
  16. package/lib/module/BaseRouter.js.map +1 -1
  17. package/lib/module/CommonActions.js +22 -4
  18. package/lib/module/CommonActions.js.map +1 -1
  19. package/lib/module/DrawerRouter.js +13 -39
  20. package/lib/module/DrawerRouter.js.map +1 -1
  21. package/lib/module/StackRouter.js +155 -92
  22. package/lib/module/StackRouter.js.map +1 -1
  23. package/lib/module/TabRouter.js +28 -65
  24. package/lib/module/TabRouter.js.map +1 -1
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/module/types.js.map +1 -1
  27. package/lib/typescript/src/BaseRouter.d.ts +1 -0
  28. package/lib/typescript/src/BaseRouter.d.ts.map +1 -0
  29. package/lib/typescript/src/CommonActions.d.ts +14 -13
  30. package/lib/typescript/src/CommonActions.d.ts.map +1 -0
  31. package/lib/typescript/src/DrawerRouter.d.ts +6 -5
  32. package/lib/typescript/src/DrawerRouter.d.ts.map +1 -0
  33. package/lib/typescript/src/StackRouter.d.ts +24 -5
  34. package/lib/typescript/src/StackRouter.d.ts.map +1 -0
  35. package/lib/typescript/src/TabRouter.d.ts +6 -5
  36. package/lib/typescript/src/TabRouter.d.ts.map +1 -0
  37. package/lib/typescript/src/index.d.ts +1 -0
  38. package/lib/typescript/src/index.d.ts.map +1 -0
  39. package/lib/typescript/src/types.d.ts +15 -14
  40. package/lib/typescript/src/types.d.ts.map +1 -0
  41. package/package.json +5 -5
  42. package/src/BaseRouter.tsx +1 -1
  43. package/src/CommonActions.tsx +48 -28
  44. package/src/DrawerRouter.tsx +2 -1
  45. package/src/StackRouter.tsx +270 -147
  46. package/src/TabRouter.tsx +10 -17
@@ -13,7 +13,7 @@ import type {
13
13
  export type StackActionType =
14
14
  | {
15
15
  type: 'REPLACE';
16
- payload: { name: string; key?: string | undefined; params?: object };
16
+ payload: { name: string; params?: object };
17
17
  source?: string;
18
18
  target?: string;
19
19
  }
@@ -33,6 +33,16 @@ export type StackActionType =
33
33
  type: 'POP_TO_TOP';
34
34
  source?: string;
35
35
  target?: string;
36
+ }
37
+ | {
38
+ type: 'POP_TO';
39
+ payload: {
40
+ name: string;
41
+ params?: object;
42
+ merge?: boolean;
43
+ };
44
+ source?: string;
45
+ target?: string;
36
46
  };
37
47
 
38
48
  export type StackRouterOptions = DefaultRouterOptions;
@@ -79,6 +89,30 @@ export type StackActionHelpers<ParamList extends ParamListBase> = {
79
89
  * Pop to the first route in the stack, dismissing all other screens.
80
90
  */
81
91
  popToTop(): void;
92
+
93
+ /**
94
+ * Pop any screens to go back to the specified screen.
95
+ * If the specified screen doesn't exist, it'll be added to the stack.
96
+ *
97
+ * @param name Name of the route to navigate to.
98
+ * @param [params] Params object for the route.
99
+ * @param [merge] Whether to merge the params onto the route.
100
+ */
101
+ popTo<RouteName extends keyof ParamList>(
102
+ ...args: // This condition allows us to iterate over a union type, similar to navigate
103
+ RouteName extends unknown
104
+ ? // This condition checks if the params are optional,
105
+ // which means it's either undefined or a union with undefined
106
+ undefined extends ParamList[RouteName]
107
+ ?
108
+ | [screen: RouteName]
109
+ | [screen: RouteName, params: ParamList[RouteName]]
110
+ | [screen: RouteName, params: ParamList[RouteName], merge: boolean]
111
+ :
112
+ | [screen: RouteName, params: ParamList[RouteName]]
113
+ | [screen: RouteName, params: ParamList[RouteName], merge: boolean]
114
+ : never
115
+ ): void;
82
116
  };
83
117
 
84
118
  export const StackActions = {
@@ -94,6 +128,9 @@ export const StackActions = {
94
128
  popToTop(): StackActionType {
95
129
  return { type: 'POP_TO_TOP' };
96
130
  },
131
+ popTo(name: string, params?: object, merge?: boolean): StackActionType {
132
+ return { type: 'POP_TO', payload: { name, params, merge } };
133
+ },
97
134
  };
98
135
 
99
136
  export default function StackRouter(options: StackRouterOptions) {
@@ -235,7 +272,7 @@ export default function StackRouter(options: StackRouterOptions) {
235
272
  return null;
236
273
  }
237
274
 
238
- const { name, key, params } = action.payload;
275
+ const { name, params } = action.payload;
239
276
 
240
277
  if (!state.routeNames.includes(name)) {
241
278
  return null;
@@ -246,7 +283,7 @@ export default function StackRouter(options: StackRouterOptions) {
246
283
  routes: state.routes.map((route, i) =>
247
284
  i === index
248
285
  ? {
249
- key: key !== undefined ? key : `${name}-${nanoid()}`,
286
+ key: `${name}-${nanoid()}`,
250
287
  name,
251
288
  params:
252
289
  routeParamList[name] !== undefined
@@ -262,24 +299,124 @@ export default function StackRouter(options: StackRouterOptions) {
262
299
  }
263
300
 
264
301
  case 'PUSH':
265
- if (state.routeNames.includes(action.payload.name)) {
266
- const getId = options.routeGetIdList[action.payload.name];
267
- const id = getId?.({ params: action.payload.params });
268
-
269
- const route = id
270
- ? state.routes.find(
271
- (route) =>
272
- route.name === action.payload.name &&
273
- id === getId?.({ params: route.params })
274
- )
275
- : undefined;
276
-
277
- let routes: Route<string>[];
278
-
279
- if (route) {
280
- routes = state.routes.filter((r) => r.key !== route.key);
281
- routes.push({
282
- ...route,
302
+ case 'NAVIGATE': {
303
+ if (!state.routeNames.includes(action.payload.name)) {
304
+ return null;
305
+ }
306
+
307
+ const getId = options.routeGetIdList[action.payload.name];
308
+ const id = getId?.({ params: action.payload.params });
309
+
310
+ let route: Route<string> | undefined;
311
+
312
+ if (id !== undefined) {
313
+ route = state.routes.find(
314
+ (route) =>
315
+ route.name === action.payload.name &&
316
+ id === getId?.({ params: route.params })
317
+ );
318
+ } else {
319
+ const currentRoute = state.routes[state.index];
320
+
321
+ // If the route matches the current one, then navigate to it
322
+ if (
323
+ action.type === 'NAVIGATE' &&
324
+ action.payload.name === currentRoute.name
325
+ ) {
326
+ route = currentRoute;
327
+ }
328
+ }
329
+
330
+ let params;
331
+
332
+ if (action.type === 'NAVIGATE' && action.payload.merge && route) {
333
+ params =
334
+ action.payload.params !== undefined ||
335
+ routeParamList[action.payload.name] !== undefined
336
+ ? {
337
+ ...routeParamList[action.payload.name],
338
+ ...route.params,
339
+ ...action.payload.params,
340
+ }
341
+ : route.params;
342
+ } else {
343
+ params =
344
+ routeParamList[action.payload.name] !== undefined
345
+ ? {
346
+ ...routeParamList[action.payload.name],
347
+ ...action.payload.params,
348
+ }
349
+ : action.payload.params;
350
+ }
351
+
352
+ let routes: Route<string>[];
353
+
354
+ if (route) {
355
+ const routeKey = route.key;
356
+
357
+ routes = state.routes.filter((r) => r.key !== routeKey);
358
+ routes.push({
359
+ ...route,
360
+ path:
361
+ action.type === 'NAVIGATE' && action.payload.path !== undefined
362
+ ? action.payload.path
363
+ : route.path,
364
+ params,
365
+ });
366
+ } else {
367
+ routes = [
368
+ ...state.routes,
369
+ {
370
+ key: `${action.payload.name}-${nanoid()}`,
371
+ name: action.payload.name,
372
+ path:
373
+ action.type === 'NAVIGATE' ? action.payload.path : undefined,
374
+ params,
375
+ },
376
+ ];
377
+ }
378
+
379
+ return {
380
+ ...state,
381
+ index: routes.length - 1,
382
+ routes,
383
+ };
384
+ }
385
+
386
+ case 'NAVIGATE_DEPRECATED': {
387
+ if (!state.routeNames.includes(action.payload.name)) {
388
+ return null;
389
+ }
390
+
391
+ // If the route already exists, navigate to that
392
+ let index = -1;
393
+
394
+ const getId = options.routeGetIdList[action.payload.name];
395
+ const id = getId?.({ params: action.payload.params });
396
+
397
+ if (id) {
398
+ index = state.routes.findIndex(
399
+ (route) =>
400
+ route.name === action.payload.name &&
401
+ id === getId?.({ params: route.params })
402
+ );
403
+ } else if (state.routes[state.index].name === action.payload.name) {
404
+ index = state.index;
405
+ } else {
406
+ for (let i = state.routes.length - 1; i >= 0; i--) {
407
+ if (state.routes[i].name === action.payload.name) {
408
+ index = i;
409
+ break;
410
+ }
411
+ }
412
+ }
413
+
414
+ if (index === -1) {
415
+ const routes = [
416
+ ...state.routes,
417
+ {
418
+ key: `${action.payload.name}-${nanoid()}`,
419
+ name: action.payload.name,
283
420
  params:
284
421
  routeParamList[action.payload.name] !== undefined
285
422
  ? {
@@ -287,32 +424,51 @@ export default function StackRouter(options: StackRouterOptions) {
287
424
  ...action.payload.params,
288
425
  }
289
426
  : action.payload.params,
290
- });
291
- } else {
292
- routes = [
293
- ...state.routes,
294
- {
295
- key: `${action.payload.name}-${nanoid()}`,
296
- name: action.payload.name,
297
- params:
298
- routeParamList[action.payload.name] !== undefined
299
- ? {
300
- ...routeParamList[action.payload.name],
301
- ...action.payload.params,
302
- }
303
- : action.payload.params,
304
- },
305
- ];
306
- }
427
+ },
428
+ ];
307
429
 
308
430
  return {
309
431
  ...state,
310
- index: routes.length - 1,
311
432
  routes,
433
+ index: routes.length - 1,
312
434
  };
313
435
  }
314
436
 
315
- return null;
437
+ const route = state.routes[index];
438
+
439
+ let params;
440
+
441
+ if (action.payload.merge) {
442
+ params =
443
+ action.payload.params !== undefined ||
444
+ routeParamList[route.name] !== undefined
445
+ ? {
446
+ ...routeParamList[route.name],
447
+ ...route.params,
448
+ ...action.payload.params,
449
+ }
450
+ : route.params;
451
+ } else {
452
+ params =
453
+ routeParamList[route.name] !== undefined
454
+ ? {
455
+ ...routeParamList[route.name],
456
+ ...action.payload.params,
457
+ }
458
+ : action.payload.params;
459
+ }
460
+
461
+ return {
462
+ ...state,
463
+ index,
464
+ routes: [
465
+ ...state.routes.slice(0, index),
466
+ params !== route.params
467
+ ? { ...route, params }
468
+ : state.routes[index],
469
+ ],
470
+ };
471
+ }
316
472
 
317
473
  case 'POP': {
318
474
  const index =
@@ -346,126 +502,93 @@ export default function StackRouter(options: StackRouterOptions) {
346
502
  options
347
503
  );
348
504
 
349
- case 'NAVIGATE':
350
- if (
351
- action.payload.name !== undefined &&
352
- !state.routeNames.includes(action.payload.name)
353
- ) {
505
+ case 'POP_TO': {
506
+ if (!state.routeNames.includes(action.payload.name)) {
354
507
  return null;
355
508
  }
356
509
 
357
- if (action.payload.key || action.payload.name) {
358
- // If the route already exists, navigate to that
359
- let index = -1;
360
-
361
- const getId =
362
- // `getId` and `key` can't be used together
363
- action.payload.key === undefined &&
364
- action.payload.name !== undefined
365
- ? options.routeGetIdList[action.payload.name]
366
- : undefined;
367
- const id = getId?.({ params: action.payload.params });
368
-
369
- if (id) {
370
- index = state.routes.findIndex(
371
- (route) =>
372
- route.name === action.payload.name &&
373
- id === getId?.({ params: route.params })
374
- );
375
- } else if (
376
- (state.routes[state.index].name === action.payload.name &&
377
- action.payload.key === undefined) ||
378
- state.routes[state.index].key === action.payload.key
379
- ) {
380
- index = state.index;
381
- } else {
382
- for (let i = state.routes.length - 1; i >= 0; i--) {
383
- if (
384
- (state.routes[i].name === action.payload.name &&
385
- action.payload.key === undefined) ||
386
- state.routes[i].key === action.payload.key
387
- ) {
388
- index = i;
389
- break;
390
- }
391
- }
392
- }
510
+ // If the route already exists, navigate to that
511
+ let index = -1;
393
512
 
394
- if (
395
- index === -1 &&
396
- action.payload.key &&
397
- action.payload.name === undefined
398
- ) {
399
- return null;
400
- }
513
+ const getId = options.routeGetIdList[action.payload.name];
514
+ const id = getId?.({ params: action.payload.params });
401
515
 
402
- if (index === -1 && action.payload.name !== undefined) {
403
- const routes = [
404
- ...state.routes,
405
- {
406
- key:
407
- action.payload.key ?? `${action.payload.name}-${nanoid()}`,
408
- name: action.payload.name,
409
- path: action.payload.path,
410
- params:
411
- routeParamList[action.payload.name] !== undefined
412
- ? {
413
- ...routeParamList[action.payload.name],
414
- ...action.payload.params,
415
- }
416
- : action.payload.params,
417
- },
418
- ];
419
-
420
- return {
421
- ...state,
422
- routes,
423
- index: routes.length - 1,
424
- };
516
+ if (id) {
517
+ index = state.routes.findIndex(
518
+ (route) =>
519
+ route.name === action.payload.name &&
520
+ id === getId?.({ params: route.params })
521
+ );
522
+ } else if (state.routes[state.index].name === action.payload.name) {
523
+ index = state.index;
524
+ } else {
525
+ for (let i = state.routes.length - 1; i >= 0; i--) {
526
+ if (state.routes[i].name === action.payload.name) {
527
+ index = i;
528
+ break;
529
+ }
425
530
  }
531
+ }
426
532
 
427
- const route = state.routes[index];
428
-
429
- let params;
430
-
431
- if (action.payload.merge) {
432
- params =
433
- action.payload.params !== undefined ||
434
- routeParamList[route.name] !== undefined
435
- ? {
436
- ...routeParamList[route.name],
437
- ...route.params,
438
- ...action.payload.params,
439
- }
440
- : route.params;
441
- } else {
442
- params =
443
- routeParamList[route.name] !== undefined
444
- ? {
445
- ...routeParamList[route.name],
446
- ...action.payload.params,
447
- }
448
- : action.payload.params;
449
- }
533
+ // If the route doesn't exist, remove the current route and add the new one
534
+ if (index === -1) {
535
+ const routes = [
536
+ ...state.routes.slice(0, -1),
537
+ {
538
+ key: `${action.payload.name}-${nanoid()}`,
539
+ name: action.payload.name,
540
+ params:
541
+ routeParamList[action.payload.name] !== undefined
542
+ ? {
543
+ ...routeParamList[action.payload.name],
544
+ ...action.payload.params,
545
+ }
546
+ : action.payload.params,
547
+ },
548
+ ];
450
549
 
451
550
  return {
452
551
  ...state,
453
- index,
454
- routes: [
455
- ...state.routes.slice(0, index),
456
- params !== route.params ||
457
- (action.payload.path && action.payload.path !== route.path)
458
- ? {
459
- ...route,
460
- path: action.payload.path ?? route.path,
461
- params,
462
- }
463
- : state.routes[index],
464
- ],
552
+ routes,
553
+ index: routes.length - 1,
465
554
  };
466
555
  }
467
556
 
468
- return null;
557
+ const route = state.routes[index];
558
+
559
+ let params;
560
+
561
+ if (action.payload.merge) {
562
+ params =
563
+ action.payload.params !== undefined ||
564
+ routeParamList[route.name] !== undefined
565
+ ? {
566
+ ...routeParamList[route.name],
567
+ ...route.params,
568
+ ...action.payload.params,
569
+ }
570
+ : route.params;
571
+ } else {
572
+ params =
573
+ routeParamList[route.name] !== undefined
574
+ ? {
575
+ ...routeParamList[route.name],
576
+ ...action.payload.params,
577
+ }
578
+ : action.payload.params;
579
+ }
580
+
581
+ return {
582
+ ...state,
583
+ index,
584
+ routes: [
585
+ ...state.routes.slice(0, index),
586
+ params !== route.params
587
+ ? { ...route, params }
588
+ : state.routes[index],
589
+ ],
590
+ };
591
+ }
469
592
 
470
593
  case 'GO_BACK':
471
594
  if (state.index > 0) {
package/src/TabRouter.tsx CHANGED
@@ -293,18 +293,11 @@ export default function TabRouter({
293
293
  getStateForAction(state, action, { routeParamList }) {
294
294
  switch (action.type) {
295
295
  case 'JUMP_TO':
296
- case 'NAVIGATE': {
297
- let index = -1;
298
-
299
- if (action.type === 'NAVIGATE' && action.payload.key) {
300
- index = state.routes.findIndex(
301
- (route) => route.key === action.payload.key
302
- );
303
- } else {
304
- index = state.routes.findIndex(
305
- (route) => route.name === action.payload.name
306
- );
307
- }
296
+ case 'NAVIGATE':
297
+ case 'NAVIGATE_DEPRECATED': {
298
+ const index = state.routes.findIndex(
299
+ (route) => route.name === action.payload.name
300
+ );
308
301
 
309
302
  if (index === -1) {
310
303
  return null;
@@ -320,7 +313,11 @@ export default function TabRouter({
320
313
 
321
314
  let params;
322
315
 
323
- if (action.type === 'NAVIGATE' && action.payload.merge) {
316
+ if (
317
+ (action.type === 'NAVIGATE' ||
318
+ action.type === 'NAVIGATE_DEPRECATED') &&
319
+ action.payload.merge
320
+ ) {
324
321
  params =
325
322
  action.payload.params !== undefined ||
326
323
  routeParamList[route.name] !== undefined
@@ -382,10 +379,6 @@ export default function TabRouter({
382
379
  }
383
380
  },
384
381
 
385
- shouldActionChangeFocus(action) {
386
- return action.type === 'NAVIGATE';
387
- },
388
-
389
382
  actionCreators: TabActions,
390
383
  };
391
384