@amazon-devices/react-navigation__routers 2.0.1758683737

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 (60) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +17 -0
  3. package/SystemBundles/b690027feea4132f8720e462805cba84c12cd0e25f99e321a1a2c8b794832a91.bundle +3515 -0
  4. package/SystemBundles/b690027feea4132f8720e462805cba84c12cd0e25f99e321a1a2c8b794832a91.map +1 -0
  5. package/SystemModules/amzn__react-navigation__routers-2.modules.txt +21 -0
  6. package/SystemModules/amzn__react-navigation__routers-2.private.modules.txt +13 -0
  7. package/SystemModules/keplerscript-system-bundle-config.json +7 -0
  8. package/THIRD_PARTY_NOTICES.txt +24 -0
  9. package/kepler-compatibility.json +8 -0
  10. package/kepler-transformed-package-info.json +3 -0
  11. package/lib/commonjs/BaseRouter.js +61 -0
  12. package/lib/commonjs/BaseRouter.js.map +1 -0
  13. package/lib/commonjs/CommonActions.js +53 -0
  14. package/lib/commonjs/CommonActions.js.map +1 -0
  15. package/lib/commonjs/DrawerRouter.js +154 -0
  16. package/lib/commonjs/DrawerRouter.js.map +1 -0
  17. package/lib/commonjs/StackRouter.js +310 -0
  18. package/lib/commonjs/StackRouter.js.map +1 -0
  19. package/lib/commonjs/TabRouter.js +253 -0
  20. package/lib/commonjs/TabRouter.js.map +1 -0
  21. package/lib/commonjs/index.js +80 -0
  22. package/lib/commonjs/index.js.map +1 -0
  23. package/lib/commonjs/types.js +6 -0
  24. package/lib/commonjs/types.js.map +1 -0
  25. package/lib/module/BaseRouter.js +55 -0
  26. package/lib/module/BaseRouter.js.map +1 -0
  27. package/lib/module/CommonActions.js +44 -0
  28. package/lib/module/CommonActions.js.map +1 -0
  29. package/lib/module/DrawerRouter.js +145 -0
  30. package/lib/module/DrawerRouter.js.map +1 -0
  31. package/lib/module/StackRouter.js +302 -0
  32. package/lib/module/StackRouter.js.map +1 -0
  33. package/lib/module/TabRouter.js +245 -0
  34. package/lib/module/TabRouter.js.map +1 -0
  35. package/lib/module/index.js +8 -0
  36. package/lib/module/index.js.map +1 -0
  37. package/lib/module/types.js +2 -0
  38. package/lib/module/types.js.map +1 -0
  39. package/lib/typescript/src/BaseRouter.d.ts +27 -0
  40. package/lib/typescript/src/BaseRouter.d.ts.map +1 -0
  41. package/lib/typescript/src/CommonActions.d.ts +56 -0
  42. package/lib/typescript/src/CommonActions.d.ts.map +1 -0
  43. package/lib/typescript/src/DrawerRouter.d.ts +53 -0
  44. package/lib/typescript/src/DrawerRouter.d.ts.map +1 -0
  45. package/lib/typescript/src/StackRouter.d.ts +69 -0
  46. package/lib/typescript/src/StackRouter.d.ts.map +1 -0
  47. package/lib/typescript/src/TabRouter.d.ts +41 -0
  48. package/lib/typescript/src/TabRouter.d.ts.map +1 -0
  49. package/lib/typescript/src/index.d.ts +11 -0
  50. package/lib/typescript/src/index.d.ts.map +1 -0
  51. package/lib/typescript/src/types.d.ts +177 -0
  52. package/lib/typescript/src/types.d.ts.map +1 -0
  53. package/package.json +1 -0
  54. package/src/BaseRouter.tsx +81 -0
  55. package/src/CommonActions.tsx +89 -0
  56. package/src/DrawerRouter.tsx +247 -0
  57. package/src/StackRouter.tsx +495 -0
  58. package/src/TabRouter.tsx +407 -0
  59. package/src/index.tsx +28 -0
  60. package/src/types.tsx +228 -0
@@ -0,0 +1,407 @@
1
+ import { nanoid } from 'nanoid/non-secure';
2
+
3
+ import BaseRouter from './BaseRouter';
4
+ import type {
5
+ CommonNavigationAction,
6
+ DefaultRouterOptions,
7
+ NavigationState,
8
+ ParamListBase,
9
+ PartialState,
10
+ Route,
11
+ Router,
12
+ } from './types';
13
+
14
+ export type TabActionType = {
15
+ type: 'JUMP_TO';
16
+ payload: { name: string; params?: object };
17
+ source?: string;
18
+ target?: string;
19
+ };
20
+
21
+ export type BackBehavior =
22
+ | 'initialRoute'
23
+ | 'firstRoute'
24
+ | 'history'
25
+ | 'order'
26
+ | 'none';
27
+
28
+ export type TabRouterOptions = DefaultRouterOptions & {
29
+ backBehavior?: BackBehavior;
30
+ };
31
+
32
+ export type TabNavigationState<ParamList extends ParamListBase> = Omit<
33
+ NavigationState<ParamList>,
34
+ 'history'
35
+ > & {
36
+ /**
37
+ * Type of the router, in this case, it's tab.
38
+ */
39
+ type: 'tab';
40
+ /**
41
+ * List of previously visited route keys.
42
+ */
43
+ history: { type: 'route'; key: string }[];
44
+ };
45
+
46
+ export type TabActionHelpers<ParamList extends ParamListBase> = {
47
+ /**
48
+ * Jump to an existing tab.
49
+ *
50
+ * @param name Name of the route for the tab.
51
+ * @param [params] Params object for the route.
52
+ */
53
+ jumpTo<RouteName extends Extract<keyof ParamList, string>>(
54
+ ...args: undefined extends ParamList[RouteName]
55
+ ? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
56
+ : [screen: RouteName, params: ParamList[RouteName]]
57
+ ): void;
58
+ };
59
+
60
+ const TYPE_ROUTE = 'route' as const;
61
+
62
+ export const TabActions = {
63
+ jumpTo(name: string, params?: object): TabActionType {
64
+ return { type: 'JUMP_TO', payload: { name, params } };
65
+ },
66
+ };
67
+
68
+ const getRouteHistory = (
69
+ routes: Route<string>[],
70
+ index: number,
71
+ backBehavior: BackBehavior,
72
+ initialRouteName: string | undefined
73
+ ) => {
74
+ const history = [{ type: TYPE_ROUTE, key: routes[index].key }];
75
+ let initialRouteIndex;
76
+
77
+ switch (backBehavior) {
78
+ case 'order':
79
+ for (let i = index; i > 0; i--) {
80
+ history.unshift({ type: TYPE_ROUTE, key: routes[i - 1].key });
81
+ }
82
+ break;
83
+ case 'firstRoute':
84
+ if (index !== 0) {
85
+ history.unshift({
86
+ type: TYPE_ROUTE,
87
+ key: routes[0].key,
88
+ });
89
+ }
90
+ break;
91
+ case 'initialRoute':
92
+ initialRouteIndex = routes.findIndex(
93
+ (route) => route.name === initialRouteName
94
+ );
95
+ initialRouteIndex = initialRouteIndex === -1 ? 0 : initialRouteIndex;
96
+
97
+ if (index !== initialRouteIndex) {
98
+ history.unshift({
99
+ type: TYPE_ROUTE,
100
+ key: routes[initialRouteIndex].key,
101
+ });
102
+ }
103
+ break;
104
+ case 'history':
105
+ // The history will fill up on navigation
106
+ break;
107
+ }
108
+
109
+ return history;
110
+ };
111
+
112
+ const changeIndex = (
113
+ state: TabNavigationState<ParamListBase>,
114
+ index: number,
115
+ backBehavior: BackBehavior,
116
+ initialRouteName: string | undefined
117
+ ) => {
118
+ let history;
119
+
120
+ if (backBehavior === 'history') {
121
+ const currentKey = state.routes[index].key;
122
+
123
+ history = state.history
124
+ .filter((it) => (it.type === 'route' ? it.key !== currentKey : false))
125
+ .concat({ type: TYPE_ROUTE, key: currentKey });
126
+ } else {
127
+ history = getRouteHistory(
128
+ state.routes,
129
+ index,
130
+ backBehavior,
131
+ initialRouteName
132
+ );
133
+ }
134
+
135
+ return {
136
+ ...state,
137
+ index,
138
+ history,
139
+ };
140
+ };
141
+
142
+ export default function TabRouter({
143
+ initialRouteName,
144
+ backBehavior = 'firstRoute',
145
+ }: TabRouterOptions) {
146
+ const router: Router<
147
+ TabNavigationState<ParamListBase>,
148
+ TabActionType | CommonNavigationAction
149
+ > = {
150
+ ...BaseRouter,
151
+
152
+ type: 'tab',
153
+
154
+ getInitialState({ routeNames, routeParamList }) {
155
+ const index =
156
+ initialRouteName !== undefined && routeNames.includes(initialRouteName)
157
+ ? routeNames.indexOf(initialRouteName)
158
+ : 0;
159
+
160
+ const routes = routeNames.map((name) => ({
161
+ name,
162
+ key: `${name}-${nanoid()}`,
163
+ params: routeParamList[name],
164
+ }));
165
+
166
+ const history = getRouteHistory(
167
+ routes,
168
+ index,
169
+ backBehavior,
170
+ initialRouteName
171
+ );
172
+
173
+ return {
174
+ stale: false,
175
+ type: 'tab',
176
+ key: `tab-${nanoid()}`,
177
+ index,
178
+ routeNames,
179
+ history,
180
+ routes,
181
+ };
182
+ },
183
+
184
+ getRehydratedState(partialState, { routeNames, routeParamList }) {
185
+ let state = partialState;
186
+
187
+ if (state.stale === false) {
188
+ return state;
189
+ }
190
+
191
+ const routes = routeNames.map((name) => {
192
+ const route = (
193
+ state as PartialState<TabNavigationState<ParamListBase>>
194
+ ).routes.find((r) => r.name === name);
195
+
196
+ return {
197
+ ...route,
198
+ name,
199
+ key:
200
+ route && route.name === name && route.key
201
+ ? route.key
202
+ : `${name}-${nanoid()}`,
203
+ params:
204
+ routeParamList[name] !== undefined
205
+ ? {
206
+ ...routeParamList[name],
207
+ ...(route ? route.params : undefined),
208
+ }
209
+ : route
210
+ ? route.params
211
+ : undefined,
212
+ } as Route<string>;
213
+ });
214
+
215
+ const index = Math.min(
216
+ Math.max(routeNames.indexOf(state.routes[state?.index ?? 0]?.name), 0),
217
+ routes.length - 1
218
+ );
219
+
220
+ const history =
221
+ state.history?.filter((it) => routes.find((r) => r.key === it.key)) ??
222
+ [];
223
+
224
+ return changeIndex(
225
+ {
226
+ stale: false,
227
+ type: 'tab',
228
+ key: `tab-${nanoid()}`,
229
+ index,
230
+ routeNames,
231
+ history,
232
+ routes,
233
+ },
234
+ index,
235
+ backBehavior,
236
+ initialRouteName
237
+ );
238
+ },
239
+
240
+ getStateForRouteNamesChange(
241
+ state,
242
+ { routeNames, routeParamList, routeKeyChanges }
243
+ ) {
244
+ const routes = routeNames.map(
245
+ (name) =>
246
+ state.routes.find(
247
+ (r) => r.name === name && !routeKeyChanges.includes(r.name)
248
+ ) || {
249
+ name,
250
+ key: `${name}-${nanoid()}`,
251
+ params: routeParamList[name],
252
+ }
253
+ );
254
+
255
+ const index = Math.max(
256
+ 0,
257
+ routeNames.indexOf(state.routes[state.index].name)
258
+ );
259
+
260
+ let history = state.history.filter(
261
+ // Type will always be 'route' for tabs, but could be different in a router extending this (e.g. drawer)
262
+ (it) => it.type !== 'route' || routes.find((r) => r.key === it.key)
263
+ );
264
+
265
+ if (!history.length) {
266
+ history = getRouteHistory(
267
+ routes,
268
+ index,
269
+ backBehavior,
270
+ initialRouteName
271
+ );
272
+ }
273
+
274
+ return {
275
+ ...state,
276
+ history,
277
+ routeNames,
278
+ routes,
279
+ index,
280
+ };
281
+ },
282
+
283
+ getStateForRouteFocus(state, key) {
284
+ const index = state.routes.findIndex((r) => r.key === key);
285
+
286
+ if (index === -1 || index === state.index) {
287
+ return state;
288
+ }
289
+
290
+ return changeIndex(state, index, backBehavior, initialRouteName);
291
+ },
292
+
293
+ getStateForAction(state, action, { routeParamList, routeGetIdList }) {
294
+ switch (action.type) {
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
+ }
308
+
309
+ if (index === -1) {
310
+ return null;
311
+ }
312
+
313
+ return changeIndex(
314
+ {
315
+ ...state,
316
+ routes: state.routes.map((route, i) => {
317
+ if (i !== index) {
318
+ return route;
319
+ }
320
+
321
+ const getId = routeGetIdList[route.name];
322
+
323
+ const currentId = getId?.({ params: route.params });
324
+ const nextId = getId?.({ params: action.payload.params });
325
+
326
+ const key =
327
+ currentId === nextId
328
+ ? route.key
329
+ : `${route.name}-${nanoid()}`;
330
+
331
+ let params;
332
+
333
+ if (
334
+ action.type === 'NAVIGATE' &&
335
+ action.payload.merge &&
336
+ currentId === nextId
337
+ ) {
338
+ params =
339
+ action.payload.params !== undefined ||
340
+ routeParamList[route.name] !== undefined
341
+ ? {
342
+ ...routeParamList[route.name],
343
+ ...route.params,
344
+ ...action.payload.params,
345
+ }
346
+ : route.params;
347
+ } else {
348
+ params =
349
+ routeParamList[route.name] !== undefined
350
+ ? {
351
+ ...routeParamList[route.name],
352
+ ...action.payload.params,
353
+ }
354
+ : action.payload.params;
355
+ }
356
+
357
+ const path =
358
+ action.type === 'NAVIGATE' && action.payload.path != null
359
+ ? action.payload.path
360
+ : route.path;
361
+
362
+ return params !== route.params || path !== route.path
363
+ ? { ...route, key, path, params }
364
+ : route;
365
+ }),
366
+ },
367
+ index,
368
+ backBehavior,
369
+ initialRouteName
370
+ );
371
+ }
372
+
373
+ case 'GO_BACK': {
374
+ if (state.history.length === 1) {
375
+ return null;
376
+ }
377
+
378
+ const previousKey = state.history[state.history.length - 2].key;
379
+ const index = state.routes.findIndex(
380
+ (route) => route.key === previousKey
381
+ );
382
+
383
+ if (index === -1) {
384
+ return null;
385
+ }
386
+
387
+ return {
388
+ ...state,
389
+ history: state.history.slice(0, -1),
390
+ index,
391
+ };
392
+ }
393
+
394
+ default:
395
+ return BaseRouter.getStateForAction(state, action);
396
+ }
397
+ },
398
+
399
+ shouldActionChangeFocus(action) {
400
+ return action.type === 'NAVIGATE';
401
+ },
402
+
403
+ actionCreators: TabActions,
404
+ };
405
+
406
+ return router;
407
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,28 @@
1
+ import * as CommonActions from './CommonActions';
2
+
3
+ export { CommonActions };
4
+
5
+ export { default as BaseRouter } from './BaseRouter';
6
+ export type {
7
+ DrawerActionHelpers,
8
+ DrawerActionType,
9
+ DrawerNavigationState,
10
+ DrawerRouterOptions,
11
+ DrawerStatus,
12
+ } from './DrawerRouter';
13
+ export { DrawerActions, default as DrawerRouter } from './DrawerRouter';
14
+ export type {
15
+ StackActionHelpers,
16
+ StackActionType,
17
+ StackNavigationState,
18
+ StackRouterOptions,
19
+ } from './StackRouter';
20
+ export { StackActions, default as StackRouter } from './StackRouter';
21
+ export type {
22
+ TabActionHelpers,
23
+ TabActionType,
24
+ TabNavigationState,
25
+ TabRouterOptions,
26
+ } from './TabRouter';
27
+ export { TabActions, default as TabRouter } from './TabRouter';
28
+ export * from './types';
package/src/types.tsx ADDED
@@ -0,0 +1,228 @@
1
+ import type * as CommonActions from './CommonActions';
2
+
3
+ export type CommonNavigationAction = CommonActions.Action;
4
+
5
+ type NavigationRoute<
6
+ ParamList extends ParamListBase,
7
+ RouteName extends keyof ParamList
8
+ > = Route<Extract<RouteName, string>, ParamList[RouteName]> & {
9
+ state?: NavigationState | PartialState<NavigationState>;
10
+ };
11
+
12
+ export type NavigationState<ParamList extends ParamListBase = ParamListBase> =
13
+ Readonly<{
14
+ /**
15
+ * Unique key for the navigation state.
16
+ */
17
+ key: string;
18
+ /**
19
+ * Index of the currently focused route.
20
+ */
21
+ index: number;
22
+ /**
23
+ * List of valid route names as defined in the screen components.
24
+ */
25
+ routeNames: Extract<keyof ParamList, string>[];
26
+ /**
27
+ * Alternative entries for history.
28
+ */
29
+ history?: unknown[];
30
+ /**
31
+ * List of rendered routes.
32
+ */
33
+ routes: NavigationRoute<ParamList, keyof ParamList>[];
34
+ /**
35
+ * Custom type for the state, whether it's for tab, stack, drawer etc.
36
+ * During rehydration, the state will be discarded if type doesn't match with router type.
37
+ * It can also be used to detect the type of the navigator we're dealing with.
38
+ */
39
+ type: string;
40
+ /**
41
+ * Whether the navigation state has been rehydrated.
42
+ */
43
+ stale: false;
44
+ }>;
45
+
46
+ export type InitialState = Readonly<
47
+ Partial<Omit<NavigationState, 'stale' | 'routes'>> & {
48
+ routes: (Omit<Route<string>, 'key'> & { state?: InitialState })[];
49
+ }
50
+ >;
51
+
52
+ export type PartialRoute<R extends Route<string>> = Omit<R, 'key'> & {
53
+ key?: string;
54
+ state?: PartialState<NavigationState>;
55
+ };
56
+
57
+ export type PartialState<State extends NavigationState> = Partial<
58
+ Omit<State, 'stale' | 'routes'>
59
+ > &
60
+ Readonly<{
61
+ stale?: true;
62
+ routes: PartialRoute<Route<State['routeNames'][number]>>[];
63
+ }>;
64
+
65
+ export type Route<
66
+ RouteName extends string,
67
+ Params extends object | undefined = object | undefined
68
+ > = Readonly<{
69
+ /**
70
+ * Unique key for the route.
71
+ */
72
+ key: string;
73
+ /**
74
+ * User-provided name for the route.
75
+ */
76
+ name: RouteName;
77
+ /**
78
+ * Path associated with the route.
79
+ * Usually present when the screen was opened from a deep link.
80
+ */
81
+ path?: string;
82
+ }> &
83
+ (undefined extends Params
84
+ ? Readonly<{
85
+ /**
86
+ * Params for this route
87
+ */
88
+ params?: Readonly<Params>;
89
+ }>
90
+ : Readonly<{
91
+ /**
92
+ * Params for this route
93
+ */
94
+ params: Readonly<Params>;
95
+ }>);
96
+
97
+ export type ParamListBase = Record<string, object | undefined>;
98
+
99
+ export type NavigationAction = Readonly<{
100
+ /**
101
+ * Type of the action (e.g. `NAVIGATE`)
102
+ */
103
+ type: string;
104
+ /**
105
+ * Additional data for the action
106
+ */
107
+ payload?: object;
108
+ /**
109
+ * Key of the route which dispatched this action.
110
+ */
111
+ source?: string;
112
+ /**
113
+ * Key of the navigator which should handle this action.
114
+ */
115
+ target?: string;
116
+ }>;
117
+
118
+ export type ActionCreators<Action extends NavigationAction> = {
119
+ [key: string]: (...args: any) => Action;
120
+ };
121
+
122
+ export type DefaultRouterOptions<RouteName extends string = string> = {
123
+ /**
124
+ * Name of the route to focus by on initial render.
125
+ * If not specified, usually the first route is used.
126
+ */
127
+ initialRouteName?: RouteName;
128
+ };
129
+
130
+ export type RouterFactory<
131
+ State extends NavigationState,
132
+ Action extends NavigationAction,
133
+ RouterOptions extends DefaultRouterOptions
134
+ > = (options: RouterOptions) => Router<State, Action>;
135
+
136
+ export type RouterConfigOptions = {
137
+ routeNames: string[];
138
+ routeParamList: ParamListBase;
139
+ routeGetIdList: Record<
140
+ string,
141
+ | ((options: { params?: Record<string, any> }) => string | undefined)
142
+ | undefined
143
+ >;
144
+ };
145
+
146
+ export type Router<
147
+ State extends NavigationState,
148
+ Action extends NavigationAction
149
+ > = {
150
+ /**
151
+ * Type of the router. Should match the `type` property in state.
152
+ * If the type doesn't match, the state will be discarded during rehydration.
153
+ */
154
+ type: State['type'];
155
+
156
+ /**
157
+ * Initialize the navigation state.
158
+ *
159
+ * @param options.routeNames List of valid route names as defined in the screen components.
160
+ * @param options.routeParamsList Object containing params for each route.
161
+ */
162
+ getInitialState(options: RouterConfigOptions): State;
163
+
164
+ /**
165
+ * Rehydrate the full navigation state from a given partial state.
166
+ *
167
+ * @param partialState Navigation state to rehydrate from.
168
+ * @param options.routeNames List of valid route names as defined in the screen components.
169
+ * @param options.routeParamsList Object containing params for each route.
170
+ */
171
+ getRehydratedState(
172
+ partialState: PartialState<State> | State,
173
+ options: RouterConfigOptions
174
+ ): State;
175
+
176
+ /**
177
+ * Take the current state and updated list of route names, and return a new state.
178
+ *
179
+ * @param state State object to update.
180
+ * @param options.routeNames New list of route names.
181
+ * @param options.routeParamsList Object containing params for each route.
182
+ */
183
+ getStateForRouteNamesChange(
184
+ state: State,
185
+ options: RouterConfigOptions & {
186
+ /**
187
+ * List of routes whose key has changed even if they still have the same name.
188
+ * This allows to remove screens declaratively.
189
+ */
190
+ routeKeyChanges: string[];
191
+ }
192
+ ): State;
193
+
194
+ /**
195
+ * Take the current state and key of a route, and return a new state with the route focused
196
+ *
197
+ * @param state State object to apply the action on.
198
+ * @param key Key of the route to focus.
199
+ */
200
+ getStateForRouteFocus(state: State, key: string): State;
201
+
202
+ /**
203
+ * Take the current state and action, and return a new state.
204
+ * If the action cannot be handled, return `null`.
205
+ *
206
+ * @param state State object to apply the action on.
207
+ * @param action Action object to apply.
208
+ * @param options.routeNames List of valid route names as defined in the screen components.
209
+ * @param options.routeParamsList Object containing params for each route.
210
+ */
211
+ getStateForAction(
212
+ state: State,
213
+ action: Action,
214
+ options: RouterConfigOptions
215
+ ): State | PartialState<State> | null;
216
+
217
+ /**
218
+ * Whether the action should also change focus in parent navigator
219
+ *
220
+ * @param action Action object to check.
221
+ */
222
+ shouldActionChangeFocus(action: NavigationAction): boolean;
223
+
224
+ /**
225
+ * Action creators for the router.
226
+ */
227
+ actionCreators?: ActionCreators<Action>;
228
+ };