@react-navigation/routers 6.1.8 → 7.0.0-alpha.1

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 +3 -4
  3. package/lib/commonjs/BaseRouter.js.map +1 -1
  4. package/lib/commonjs/CommonActions.js +23 -2
  5. package/lib/commonjs/CommonActions.js.map +1 -1
  6. package/lib/commonjs/DrawerRouter.js +4 -5
  7. package/lib/commonjs/DrawerRouter.js.map +1 -1
  8. package/lib/commonjs/StackRouter.js +129 -39
  9. package/lib/commonjs/StackRouter.js.map +1 -1
  10. package/lib/commonjs/TabRouter.js +9 -17
  11. package/lib/commonjs/TabRouter.js.map +1 -1
  12. package/lib/commonjs/index.js +8 -9
  13. package/lib/commonjs/index.js.map +1 -1
  14. package/lib/module/BaseRouter.js +2 -3
  15. package/lib/module/BaseRouter.js.map +1 -1
  16. package/lib/module/CommonActions.js +22 -2
  17. package/lib/module/CommonActions.js.map +1 -1
  18. package/lib/module/DrawerRouter.js +3 -2
  19. package/lib/module/DrawerRouter.js.map +1 -1
  20. package/lib/module/StackRouter.js +127 -36
  21. package/lib/module/StackRouter.js.map +1 -1
  22. package/lib/module/TabRouter.js +7 -14
  23. package/lib/module/TabRouter.js.map +1 -1
  24. package/lib/module/index.js +4 -4
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/typescript/src/BaseRouter.d.ts +1 -2
  27. package/lib/typescript/src/BaseRouter.d.ts.map +1 -1
  28. package/lib/typescript/src/CommonActions.d.ts +13 -13
  29. package/lib/typescript/src/CommonActions.d.ts.map +1 -1
  30. package/lib/typescript/src/DrawerRouter.d.ts +6 -6
  31. package/lib/typescript/src/DrawerRouter.d.ts.map +1 -1
  32. package/lib/typescript/src/StackRouter.d.ts +24 -6
  33. package/lib/typescript/src/StackRouter.d.ts.map +1 -1
  34. package/lib/typescript/src/TabRouter.d.ts +6 -6
  35. package/lib/typescript/src/TabRouter.d.ts.map +1 -1
  36. package/lib/typescript/src/index.d.ts +4 -4
  37. package/lib/typescript/src/index.d.ts.map +1 -1
  38. package/lib/typescript/src/types.d.ts +14 -14
  39. package/lib/typescript/src/types.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/src/BaseRouter.tsx +2 -4
  42. package/src/CommonActions.tsx +48 -28
  43. package/src/DrawerRouter.tsx +5 -3
  44. package/src/StackRouter.tsx +272 -149
  45. package/src/TabRouter.tsx +11 -21
  46. package/src/index.tsx +4 -4
@@ -1,6 +1,6 @@
1
1
  import { nanoid } from 'nanoid/non-secure';
2
2
 
3
- import BaseRouter from './BaseRouter';
3
+ import { BaseRouter } from './BaseRouter';
4
4
  import type {
5
5
  CommonNavigationAction,
6
6
  DefaultRouterOptions,
@@ -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,9 +128,12 @@ 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
- export default function StackRouter(options: StackRouterOptions) {
136
+ export function StackRouter(options: StackRouterOptions) {
100
137
  const router: Router<
101
138
  StackNavigationState<ParamListBase>,
102
139
  CommonNavigationAction | StackActionType
@@ -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
@@ -1,6 +1,6 @@
1
1
  import { nanoid } from 'nanoid/non-secure';
2
2
 
3
- import BaseRouter from './BaseRouter';
3
+ import { BaseRouter } from './BaseRouter';
4
4
  import type {
5
5
  CommonNavigationAction,
6
6
  DefaultRouterOptions,
@@ -139,7 +139,7 @@ const changeIndex = (
139
139
  };
140
140
  };
141
141
 
142
- export default function TabRouter({
142
+ export function TabRouter({
143
143
  initialRouteName,
144
144
  backBehavior = 'firstRoute',
145
145
  }: TabRouterOptions) {
@@ -293,18 +293,11 @@ export default function TabRouter({
293
293
  getStateForAction(state, action, { routeParamList, routeGetIdList }) {
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;
@@ -313,8 +306,8 @@ export default function TabRouter({
313
306
  return changeIndex(
314
307
  {
315
308
  ...state,
316
- routes: state.routes.map((route, i) => {
317
- if (i !== index) {
309
+ routes: state.routes.map((route) => {
310
+ if (route.name !== action.payload.name) {
318
311
  return route;
319
312
  }
320
313
 
@@ -331,7 +324,8 @@ export default function TabRouter({
331
324
  let params;
332
325
 
333
326
  if (
334
- action.type === 'NAVIGATE' &&
327
+ (action.type === 'NAVIGATE' ||
328
+ action.type === 'NAVIGATE_DEPRECATED') &&
335
329
  action.payload.merge &&
336
330
  currentId === nextId
337
331
  ) {
@@ -396,10 +390,6 @@ export default function TabRouter({
396
390
  }
397
391
  },
398
392
 
399
- shouldActionChangeFocus(action) {
400
- return action.type === 'NAVIGATE';
401
- },
402
-
403
393
  actionCreators: TabActions,
404
394
  };
405
395
 
package/src/index.tsx CHANGED
@@ -2,7 +2,7 @@ import * as CommonActions from './CommonActions';
2
2
 
3
3
  export { CommonActions };
4
4
 
5
- export { default as BaseRouter } from './BaseRouter';
5
+ export { BaseRouter } from './BaseRouter';
6
6
  export type {
7
7
  DrawerActionHelpers,
8
8
  DrawerActionType,
@@ -10,19 +10,19 @@ export type {
10
10
  DrawerRouterOptions,
11
11
  DrawerStatus,
12
12
  } from './DrawerRouter';
13
- export { DrawerActions, default as DrawerRouter } from './DrawerRouter';
13
+ export { DrawerActions, DrawerRouter } from './DrawerRouter';
14
14
  export type {
15
15
  StackActionHelpers,
16
16
  StackActionType,
17
17
  StackNavigationState,
18
18
  StackRouterOptions,
19
19
  } from './StackRouter';
20
- export { StackActions, default as StackRouter } from './StackRouter';
20
+ export { StackActions, StackRouter } from './StackRouter';
21
21
  export type {
22
22
  TabActionHelpers,
23
23
  TabActionType,
24
24
  TabNavigationState,
25
25
  TabRouterOptions,
26
26
  } from './TabRouter';
27
- export { TabActions, default as TabRouter } from './TabRouter';
27
+ export { TabActions, TabRouter } from './TabRouter';
28
28
  export * from './types';