@react-navigation/routers 8.0.0-alpha.2 → 8.0.0-alpha.21

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 (42) hide show
  1. package/lib/module/BaseRouter.js +64 -61
  2. package/lib/module/BaseRouter.js.map +1 -1
  3. package/lib/module/CommonActions.js +9 -21
  4. package/lib/module/CommonActions.js.map +1 -1
  5. package/lib/module/DrawerRouter.js +15 -14
  6. package/lib/module/DrawerRouter.js.map +1 -1
  7. package/lib/module/StackRouter.js +287 -166
  8. package/lib/module/StackRouter.js.map +1 -1
  9. package/lib/module/SwitchRouter.js +426 -0
  10. package/lib/module/SwitchRouter.js.map +1 -0
  11. package/lib/module/TabRouter.js +14 -290
  12. package/lib/module/TabRouter.js.map +1 -1
  13. package/lib/typescript/src/BaseRouter.d.ts +10 -8
  14. package/lib/typescript/src/BaseRouter.d.ts.map +1 -1
  15. package/lib/typescript/src/CommonActions.d.ts +42 -39
  16. package/lib/typescript/src/CommonActions.d.ts.map +1 -1
  17. package/lib/typescript/src/DrawerRouter.d.ts +6 -5
  18. package/lib/typescript/src/DrawerRouter.d.ts.map +1 -1
  19. package/lib/typescript/src/StackRouter.d.ts +70 -24
  20. package/lib/typescript/src/StackRouter.d.ts.map +1 -1
  21. package/lib/typescript/src/SwitchRouter.d.ts +69 -0
  22. package/lib/typescript/src/SwitchRouter.d.ts.map +1 -0
  23. package/lib/typescript/src/TabRouter.d.ts +4 -24
  24. package/lib/typescript/src/TabRouter.d.ts.map +1 -1
  25. package/lib/typescript/src/createParamsFromAction.d.ts +2 -2
  26. package/lib/typescript/src/createParamsFromAction.d.ts.map +1 -1
  27. package/lib/typescript/src/createRouteFromAction.d.ts +2 -2
  28. package/lib/typescript/src/createRouteFromAction.d.ts.map +1 -1
  29. package/lib/typescript/src/index.d.ts +9 -9
  30. package/lib/typescript/src/index.d.ts.map +1 -1
  31. package/lib/typescript/src/types.d.ts +20 -30
  32. package/lib/typescript/src/types.d.ts.map +1 -1
  33. package/package.json +8 -8
  34. package/src/BaseRouter.tsx +93 -80
  35. package/src/CommonActions.tsx +44 -66
  36. package/src/DrawerRouter.tsx +28 -22
  37. package/src/StackRouter.tsx +551 -238
  38. package/src/SwitchRouter.tsx +724 -0
  39. package/src/TabRouter.tsx +24 -463
  40. package/src/createParamsFromAction.tsx +1 -1
  41. package/src/createRouteFromAction.tsx +1 -1
  42. package/src/types.tsx +39 -41
@@ -6,105 +6,118 @@ import type {
6
6
  PartialState,
7
7
  } from './types';
8
8
 
9
- /**
10
- * Base router object that can be used when writing custom routers.
11
- * This provides few helper methods to handle common actions such as `RESET`.
12
- */
13
- export const BaseRouter = {
14
- getStateForAction<State extends NavigationState>(
15
- state: State,
16
- action: CommonNavigationAction
17
- ): State | PartialState<State> | null {
18
- switch (action.type) {
19
- case 'SET_PARAMS':
20
- case 'REPLACE_PARAMS': {
21
- const index = action.source
9
+ function getStateForAction<State extends NavigationState>(
10
+ state: State,
11
+ action: CommonNavigationAction
12
+ ): State | PartialState<State> | null;
13
+ function getStateForAction(
14
+ state: NavigationState,
15
+ action: CommonNavigationAction
16
+ ) {
17
+ switch (action.type) {
18
+ case 'SET_PARAMS':
19
+ case 'REPLACE_PARAMS': {
20
+ const index =
21
+ action.source !== undefined
22
22
  ? state.routes.findIndex((r) => r.key === action.source)
23
23
  : state.index;
24
24
 
25
- if (index === -1) {
26
- return null;
27
- }
28
-
29
- return {
30
- ...state,
31
- routes: state.routes.map((r, i) =>
32
- i === index
33
- ? {
34
- ...r,
35
- params:
36
- action.type === 'REPLACE_PARAMS'
37
- ? action.payload.params
38
- : { ...r.params, ...action.payload.params },
39
- }
40
- : r
41
- ),
42
- };
25
+ if (index === -1) {
26
+ return null;
43
27
  }
44
28
 
45
- case 'PUSH_PARAMS': {
46
- const index = action.source
29
+ return {
30
+ ...state,
31
+ routes: state.routes.map((r, i) =>
32
+ i === index
33
+ ? {
34
+ ...r,
35
+ params:
36
+ action.type === 'REPLACE_PARAMS'
37
+ ? action.payload.params
38
+ : { ...r.params, ...action.payload.params },
39
+ }
40
+ : r
41
+ ),
42
+ };
43
+ }
44
+
45
+ case 'PUSH_PARAMS': {
46
+ const index =
47
+ action.source !== undefined
47
48
  ? state.routes.findIndex((r) => r.key === action.source)
48
49
  : state.index;
49
50
 
50
- if (index === -1) {
51
- return null;
52
- }
53
-
54
- return {
55
- ...state,
56
- routes: state.routes.map((r, i) =>
57
- i === index
58
- ? {
59
- ...r,
60
- params: action.payload.params,
61
- history: [
62
- ...(r.history ?? []),
63
- { type: 'params', params: r.params },
64
- ],
65
- }
66
- : r
67
- ),
68
- };
51
+ if (index === -1) {
52
+ return null;
69
53
  }
70
54
 
71
- case 'RESET': {
72
- const nextState = action.payload as State | PartialState<State>;
55
+ return {
56
+ ...state,
57
+ routes: state.routes.map((r, i) =>
58
+ i === index
59
+ ? {
60
+ ...r,
61
+ params: action.payload.params,
62
+ history: [
63
+ ...(r.history ?? []),
64
+ { type: 'params', params: r.params },
65
+ ],
66
+ }
67
+ : r
68
+ ),
69
+ };
70
+ }
71
+
72
+ case 'RESET': {
73
+ const nextState = action.payload;
74
+
75
+ const routeNamesSet = new Set(state.routeNames);
76
+
77
+ if (
78
+ nextState.routes.length === 0 ||
79
+ nextState.routes.some(
80
+ (route: { name: string }) => !routeNamesSet.has(route.name)
81
+ )
82
+ ) {
83
+ return null;
84
+ }
73
85
 
86
+ if (nextState.stale === false) {
74
87
  if (
75
- nextState.routes.length === 0 ||
76
- nextState.routes.some(
77
- (route: { name: string }) => !state.routeNames.includes(route.name)
78
- )
88
+ state.routeNames.length !== nextState.routeNames.length ||
89
+ nextState.routeNames.some((name) => !routeNamesSet.has(name)) ||
90
+ !Number.isInteger(nextState.index) ||
91
+ nextState.index < 0 ||
92
+ nextState.index >= nextState.routes.length
79
93
  ) {
80
94
  return null;
81
95
  }
82
96
 
83
- if (nextState.stale === false) {
84
- if (
85
- state.routeNames.length !== nextState.routeNames.length ||
86
- nextState.routeNames.some(
87
- (name) => !state.routeNames.includes(name)
88
- )
89
- ) {
90
- return null;
91
- }
92
-
93
- return {
94
- ...nextState,
95
- routes: nextState.routes.map((route) =>
96
- route.key ? route : { ...route, key: `${route.name}-${nanoid()}` }
97
- ),
98
- };
99
- }
100
-
101
- return nextState;
97
+ return {
98
+ ...nextState,
99
+ routes: nextState.routes.map((route) =>
100
+ 'key' in route && route.key
101
+ ? route
102
+ : { ...route, key: `${route.name}-${nanoid()}` }
103
+ ),
104
+ };
102
105
  }
103
106
 
104
- default:
105
- return null;
107
+ return nextState;
106
108
  }
107
- },
109
+
110
+ default:
111
+ return null;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Base router object that can be used when writing custom routers.
117
+ * This provides few helper methods to handle common actions such as `RESET`.
118
+ */
119
+ export const BaseRouter = {
120
+ getStateForAction,
108
121
 
109
122
  shouldActionChangeFocus(action: CommonNavigationAction) {
110
123
  return action.type === 'NAVIGATE';
@@ -9,59 +9,59 @@ type ResetState =
9
9
 
10
10
  type GoBackAction = {
11
11
  type: 'GO_BACK';
12
- source?: string;
13
- target?: string;
12
+ source?: string | undefined;
13
+ target?: string | undefined;
14
14
  };
15
15
 
16
16
  type NavigateAction = {
17
17
  type: 'NAVIGATE';
18
18
  payload: {
19
19
  name: string;
20
- params?: object;
21
- path?: string;
22
- merge?: boolean;
23
- pop?: boolean;
20
+ params?: object | undefined;
21
+ path?: string | undefined;
22
+ merge?: boolean | undefined;
23
+ pop?: boolean | undefined;
24
24
  };
25
- source?: string;
26
- target?: string;
25
+ source?: string | undefined;
26
+ target?: string | undefined;
27
27
  };
28
28
 
29
29
  type ResetAction = {
30
30
  type: 'RESET';
31
- payload: ResetState | undefined;
32
- source?: string;
33
- target?: string;
31
+ payload: ResetState;
32
+ source?: string | undefined;
33
+ target?: string | undefined;
34
34
  };
35
35
 
36
36
  type SetParamsAction = {
37
37
  type: 'SET_PARAMS';
38
- payload: { params?: object };
39
- source?: string;
40
- target?: string;
38
+ payload: { params?: object | undefined };
39
+ source?: string | undefined;
40
+ target?: string | undefined;
41
41
  };
42
42
 
43
43
  type ReplaceParamsAction = {
44
44
  type: 'REPLACE_PARAMS';
45
- payload: { params?: object };
46
- source?: string;
47
- target?: string;
45
+ payload: { params?: object | undefined };
46
+ source?: string | undefined;
47
+ target?: string | undefined;
48
48
  };
49
49
 
50
50
  type PushParamsAction = {
51
51
  type: 'PUSH_PARAMS';
52
- payload: { params?: object };
53
- source?: string;
54
- target?: string;
52
+ payload: { params?: object | undefined };
53
+ source?: string | undefined;
54
+ target?: string | undefined;
55
55
  };
56
56
 
57
57
  type PreloadAction = {
58
58
  type: 'PRELOAD';
59
59
  payload: {
60
60
  name: string;
61
- params?: object;
61
+ params?: object | undefined;
62
62
  };
63
- source?: string;
64
- target?: string;
63
+ source?: string | undefined;
64
+ target?: string | undefined;
65
65
  };
66
66
 
67
67
  export type Action =
@@ -73,54 +73,32 @@ export type Action =
73
73
  | PushParamsAction
74
74
  | PreloadAction;
75
75
 
76
- export function goBack(): Action {
77
- return { type: 'GO_BACK' };
76
+ export function goBack() {
77
+ return { type: 'GO_BACK' } as const satisfies GoBackAction;
78
78
  }
79
79
 
80
80
  export function navigate(
81
81
  name: string,
82
- params?: object,
83
- options?: {
84
- merge?: boolean;
85
- pop?: boolean;
86
- }
87
- ): Action;
88
-
89
- export function navigate(options: {
90
- name: string;
91
- params?: object;
92
- path?: string;
93
- merge?: boolean;
94
- pop?: boolean;
95
- }): Action;
96
-
97
- export function navigate(...args: any): Action {
98
- if (typeof args[0] === 'string') {
99
- const [name, params, options] = args;
100
-
101
- return {
102
- type: 'NAVIGATE',
103
- payload: {
104
- name,
105
- params,
106
- merge: options?.merge,
107
- pop: options?.pop,
108
- },
109
- };
110
- } else {
111
- const payload = args[0] || {};
112
-
113
- if (!('name' in payload)) {
114
- throw new Error(
115
- 'You need to specify a name when calling navigate with an object as the argument. See https://reactnavigation.org/docs/navigation-actions#navigate for usage.'
116
- );
117
- }
118
-
119
- return { type: 'NAVIGATE', payload };
120
- }
82
+ params?: object | undefined,
83
+ options?:
84
+ | {
85
+ merge?: boolean | undefined;
86
+ pop?: boolean | undefined;
87
+ }
88
+ | undefined
89
+ ) {
90
+ return {
91
+ type: 'NAVIGATE',
92
+ payload: {
93
+ name,
94
+ params,
95
+ merge: options?.merge,
96
+ pop: options?.pop,
97
+ },
98
+ } as const satisfies NavigateAction;
121
99
  }
122
100
 
123
- export function reset(state: ResetState | undefined) {
101
+ export function reset(state: ResetState) {
124
102
  return { type: 'RESET', payload: state } as const satisfies ResetAction;
125
103
  }
126
104
 
@@ -145,7 +123,7 @@ export function pushParams(params: object) {
145
123
  } as const satisfies PushParamsAction;
146
124
  }
147
125
 
148
- export function preload(name: string, params?: object) {
126
+ export function preload(name: string, params?: object | undefined) {
149
127
  return {
150
128
  type: 'PRELOAD',
151
129
  payload: { name, params },
@@ -1,11 +1,11 @@
1
1
  import { nanoid } from 'nanoid/non-secure';
2
2
 
3
+ import { SwitchRouter } from './SwitchRouter';
3
4
  import {
4
5
  type TabActionHelpers,
5
6
  TabActions,
6
7
  type TabActionType,
7
8
  type TabNavigationState,
8
- TabRouter,
9
9
  type TabRouterOptions,
10
10
  } from './TabRouter';
11
11
  import type {
@@ -14,18 +14,19 @@ import type {
14
14
  PartialState,
15
15
  Router,
16
16
  } from './types';
17
+
17
18
  export type DrawerStatus = 'open' | 'closed';
18
19
 
19
20
  export type DrawerActionType =
20
21
  | TabActionType
21
22
  | {
22
23
  type: 'OPEN_DRAWER' | 'CLOSE_DRAWER' | 'TOGGLE_DRAWER';
23
- source?: string;
24
- target?: string;
24
+ source?: string | undefined;
25
+ target?: string | undefined;
25
26
  };
26
27
 
27
28
  export type DrawerRouterOptions = TabRouterOptions & {
28
- defaultStatus?: DrawerStatus;
29
+ defaultStatus?: DrawerStatus | undefined;
29
30
  };
30
31
 
31
32
  export type DrawerNavigationState<ParamList extends ParamListBase> = Omit<
@@ -44,7 +45,11 @@ export type DrawerNavigationState<ParamList extends ParamListBase> = Omit<
44
45
  * List of previously visited route keys and drawer open status.
45
46
  */
46
47
  history: (
47
- | { type: 'route'; key: string }
48
+ | {
49
+ type: 'route';
50
+ key: string;
51
+ params?: object | undefined;
52
+ }
48
53
  | { type: 'drawer'; status: DrawerStatus }
49
54
  )[];
50
55
  };
@@ -87,10 +92,7 @@ export function DrawerRouter({
87
92
  DrawerNavigationState<ParamListBase>,
88
93
  DrawerActionType | CommonNavigationAction
89
94
  > {
90
- const router = TabRouter(rest) as unknown as Router<
91
- DrawerNavigationState<ParamListBase>,
92
- TabActionType | CommonNavigationAction
93
- >;
95
+ const router = SwitchRouter<'drawer'>(rest);
94
96
 
95
97
  const isDrawerInHistory = (
96
98
  state:
@@ -179,11 +181,16 @@ export function DrawerRouter({
179
181
  return partialState;
180
182
  }
181
183
 
182
- let state = router.getRehydratedState(partialState, {
183
- routeNames,
184
- routeParamList,
185
- routeGetIdList,
186
- });
184
+ let state: DrawerNavigationState<ParamListBase> = {
185
+ ...router.getRehydratedState(partialState, {
186
+ routeNames,
187
+ routeParamList,
188
+ routeGetIdList,
189
+ }),
190
+ default: defaultStatus,
191
+ type: 'drawer',
192
+ key: `drawer-${nanoid()}`,
193
+ };
187
194
 
188
195
  if (isDrawerInHistory(partialState)) {
189
196
  // Re-sync the drawer entry in history to correct it if it was wrong
@@ -191,12 +198,7 @@ export function DrawerRouter({
191
198
  state = addDrawerToHistory(state);
192
199
  }
193
200
 
194
- return {
195
- ...state,
196
- default: defaultStatus,
197
- type: 'drawer',
198
- key: `drawer-${nanoid()}`,
199
- };
201
+ return state;
200
202
  },
201
203
 
202
204
  getStateForRouteFocus(state, key) {
@@ -224,8 +226,12 @@ export function DrawerRouter({
224
226
  case 'NAVIGATE': {
225
227
  const result = router.getStateForAction(state, action, options);
226
228
 
227
- if (result != null && result.index !== state.index) {
228
- return closeDrawer(result as DrawerNavigationState<ParamListBase>);
229
+ if (
230
+ result != null &&
231
+ result.stale === false &&
232
+ result.index !== state.index
233
+ ) {
234
+ return closeDrawer(result);
229
235
  }
230
236
 
231
237
  return result;