@react-navigation/routers 8.0.0-alpha.0 → 8.0.0-alpha.10

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.
@@ -47,11 +47,12 @@ export const BaseRouter = {
47
47
  case 'RESET':
48
48
  {
49
49
  const nextState = action.payload;
50
- if (nextState.routes.length === 0 || nextState.routes.some(route => !state.routeNames.includes(route.name))) {
50
+ const routeNamesSet = new Set(state.routeNames);
51
+ if (nextState.routes.length === 0 || nextState.routes.some(route => !routeNamesSet.has(route.name))) {
51
52
  return null;
52
53
  }
53
54
  if (nextState.stale === false) {
54
- if (state.routeNames.length !== nextState.routeNames.length || nextState.routeNames.some(name => !state.routeNames.includes(name))) {
55
+ if (state.routeNames.length !== nextState.routeNames.length || nextState.routeNames.some(name => !routeNamesSet.has(name))) {
55
56
  return null;
56
57
  }
57
58
  return {
@@ -1 +1 @@
1
- {"version":3,"names":["nanoid","BaseRouter","getStateForAction","state","action","type","index","source","routes","findIndex","r","key","map","i","params","payload","history","nextState","length","some","route","routeNames","includes","name","stale","shouldActionChangeFocus"],"sourceRoot":"../../src","sources":["BaseRouter.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["nanoid","BaseRouter","getStateForAction","state","action","type","index","source","routes","findIndex","r","key","map","i","params","payload","history","nextState","routeNamesSet","Set","routeNames","length","some","route","has","name","stale","shouldActionChangeFocus"],"sourceRoot":"../../src","sources":["BaseRouter.tsx"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["goBack","type","navigate","args","name","params","options","payload","merge","pop","Error","reset","state","setParams","replaceParams","pushParams","preload"],"sourceRoot":"../../src","sources":["CommonActions.tsx"],"mappings":";;AA2EA,OAAO,SAASA,MAAMA,CAAA,EAAW;EAC/B,OAAO;IAAEC,IAAI,EAAE;EAAU,CAAC;AAC5B;AAmBA,OAAO,SAASC,QAAQA,CAAC,GAAGC,IAAS,EAAU;EAC7C,IAAI,OAAOA,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;IAC/B,MAAM,CAACC,IAAI,EAAEC,MAAM,EAAEC,OAAO,CAAC,GAAGH,IAAI;IAEpC,OAAO;MACLF,IAAI,EAAE,UAAU;MAChBM,OAAO,EAAE;QACPH,IAAI;QACJC,MAAM;QACNG,KAAK,EAAEF,OAAO,EAAEE,KAAK;QACrBC,GAAG,EAAEH,OAAO,EAAEG;MAChB;IACF,CAAC;EACH,CAAC,MAAM;IACL,MAAMF,OAAO,GAAGJ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE7B,IAAI,EAAE,MAAM,IAAII,OAAO,CAAC,EAAE;MACxB,MAAM,IAAIG,KAAK,CACb,8JACF,CAAC;IACH;IAEA,OAAO;MAAET,IAAI,EAAE,UAAU;MAAEM;IAAQ,CAAC;EACtC;AACF;AAEA,OAAO,SAASI,KAAKA,CAACC,KAA6B,EAAE;EACnD,OAAO;IAAEX,IAAI,EAAE,OAAO;IAAEM,OAAO,EAAEK;EAAM,CAAC;AAC1C;AAEA,OAAO,SAASC,SAASA,CAACR,MAAc,EAAE;EACxC,OAAO;IACLJ,IAAI,EAAE,YAAY;IAClBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASS,aAAaA,CAACT,MAAc,EAAE;EAC5C,OAAO;IACLJ,IAAI,EAAE,gBAAgB;IACtBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASU,UAAUA,CAACV,MAAc,EAAE;EACzC,OAAO;IACLJ,IAAI,EAAE,aAAa;IACnBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASW,OAAOA,CAACZ,IAAY,EAAEC,MAAe,EAAE;EACrD,OAAO;IACLJ,IAAI,EAAE,SAAS;IACfM,OAAO,EAAE;MAAEH,IAAI;MAAEC;IAAO;EAC1B,CAAC;AACH","ignoreList":[]}
1
+ {"version":3,"names":["goBack","type","navigate","args","name","params","options","payload","merge","pop","Error","reset","state","setParams","replaceParams","pushParams","preload"],"sourceRoot":"../../src","sources":["CommonActions.tsx"],"mappings":";;AA2EA,OAAO,SAASA,MAAMA,CAAA,EAAW;EAC/B,OAAO;IAAEC,IAAI,EAAE;EAAU,CAAC;AAC5B;AAqBA,OAAO,SAASC,QAAQA,CAAC,GAAGC,IAAS,EAAU;EAC7C,IAAI,OAAOA,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;IAC/B,MAAM,CAACC,IAAI,EAAEC,MAAM,EAAEC,OAAO,CAAC,GAAGH,IAAI;IAEpC,OAAO;MACLF,IAAI,EAAE,UAAU;MAChBM,OAAO,EAAE;QACPH,IAAI;QACJC,MAAM;QACNG,KAAK,EAAEF,OAAO,EAAEE,KAAK;QACrBC,GAAG,EAAEH,OAAO,EAAEG;MAChB;IACF,CAAC;EACH,CAAC,MAAM;IACL,MAAMF,OAAO,GAAGJ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE7B,IAAI,EAAE,MAAM,IAAII,OAAO,CAAC,EAAE;MACxB,MAAM,IAAIG,KAAK,CACb,8JACF,CAAC;IACH;IAEA,OAAO;MAAET,IAAI,EAAE,UAAU;MAAEM;IAAQ,CAAC;EACtC;AACF;AAEA,OAAO,SAASI,KAAKA,CAACC,KAAiB,EAAE;EACvC,OAAO;IAAEX,IAAI,EAAE,OAAO;IAAEM,OAAO,EAAEK;EAAM,CAAC;AAC1C;AAEA,OAAO,SAASC,SAASA,CAACR,MAAc,EAAE;EACxC,OAAO;IACLJ,IAAI,EAAE,YAAY;IAClBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASS,aAAaA,CAACT,MAAc,EAAE;EAC5C,OAAO;IACLJ,IAAI,EAAE,gBAAgB;IACtBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASU,UAAUA,CAACV,MAAc,EAAE;EACzC,OAAO;IACLJ,IAAI,EAAE,aAAa;IACnBM,OAAO,EAAE;MAAEF;IAAO;EACpB,CAAC;AACH;AAEA,OAAO,SAASW,OAAOA,CAACZ,IAAY,EAAEC,MAA2B,EAAE;EACjE,OAAO;IACLJ,IAAI,EAAE,SAAS;IACfM,OAAO,EAAE;MAAEH,IAAI;MAAEC;IAAO;EAC1B,CAAC;AACH","ignoreList":[]}
@@ -45,8 +45,50 @@ export const StackActions = {
45
45
  merge: options?.merge
46
46
  }
47
47
  };
48
+ },
49
+ retain(enable) {
50
+ return {
51
+ type: 'RETAIN',
52
+ payload: {
53
+ enable
54
+ }
55
+ };
48
56
  }
49
57
  };
58
+ function retainRoutes(previousState, nextState) {
59
+ if (!nextState.retainedRouteKeys.length) {
60
+ return nextState;
61
+ }
62
+ const retainedRouteKeySet = new Set(nextState.retainedRouteKeys);
63
+ const nextRouteKeySet = new Set(nextState.routes.map(route => route.key));
64
+ const retainedRoutes = getActiveRoutes(previousState).filter(route => retainedRouteKeySet.has(route.key) && !nextRouteKeySet.has(route.key));
65
+ if (!retainedRoutes.length) {
66
+ return nextState;
67
+ }
68
+ const removedRetainedRouteKeys = new Set(retainedRoutes.map(route => route.key));
69
+ return getStateWithRoutes(nextState, getActiveRoutes(nextState), getPreloadedRoutes(nextState), retainedRoutes.concat(getRetainedRoutes(nextState).filter(route => !removedRetainedRouteKeys.has(route.key))));
70
+ }
71
+ const getActiveRoutes = state => state.routes.slice(0, state.index + 1);
72
+ const getInactiveRoutes = state => state.routes.slice(state.index + 1);
73
+ const getPreloadedRoutes = state => {
74
+ const retainedRouteKeySet = new Set(state.retainedRouteKeys);
75
+ return getInactiveRoutes(state).filter(route => !retainedRouteKeySet.has(route.key));
76
+ };
77
+ const getRetainedRoutes = state => {
78
+ const retainedRouteKeySet = new Set(state.retainedRouteKeys);
79
+ return getInactiveRoutes(state).filter(route => retainedRouteKeySet.has(route.key));
80
+ };
81
+ const getStateWithRoutes = (state, activeRoutes, preloadedRoutes = getPreloadedRoutes(state), retainedRoutes = getRetainedRoutes(state)) => {
82
+ const routeKeySet = new Set(activeRoutes.map(route => route.key));
83
+ const retainedRouteKeySet = new Set(state.retainedRouteKeys);
84
+ const filteredRetainedRoutes = retainedRoutes.filter(route => !routeKeySet.has(route.key));
85
+ const filteredPreloadedRoutes = preloadedRoutes.filter(route => !retainedRouteKeySet.has(route.key) && !routeKeySet.has(route.key));
86
+ return {
87
+ ...state,
88
+ index: activeRoutes.length - 1,
89
+ routes: activeRoutes.concat(filteredRetainedRoutes, filteredPreloadedRoutes)
90
+ };
91
+ };
50
92
  export function StackRouter(options) {
51
93
  const router = {
52
94
  ...BaseRouter,
@@ -62,7 +104,7 @@ export function StackRouter(options) {
62
104
  key: `stack-${nanoid()}`,
63
105
  index: 0,
64
106
  routeNames,
65
- preloadedRoutes: [],
107
+ retainedRouteKeys: [],
66
108
  routes: [{
67
109
  key: `${initialRouteName}-${nanoid()}`,
68
110
  name: initialRouteName,
@@ -86,14 +128,6 @@ export function StackRouter(options) {
86
128
  ...route.params
87
129
  } : route.params
88
130
  }));
89
- const preloadedRoutes = state.preloadedRoutes?.filter(route => routeNames.includes(route.name)).map(route => ({
90
- ...route,
91
- key: route.key || `${route.name}-${nanoid()}`,
92
- params: routeParamList[route.name] !== undefined ? {
93
- ...routeParamList[route.name],
94
- ...route.params
95
- } : route.params
96
- })) ?? [];
97
131
  if (routes.length === 0) {
98
132
  const initialRouteName = options.initialRouteName !== undefined ? options.initialRouteName : routeNames[0];
99
133
  routes.push({
@@ -102,14 +136,17 @@ export function StackRouter(options) {
102
136
  params: routeParamList[initialRouteName]
103
137
  });
104
138
  }
139
+ const index = Math.min(Math.max(state.index ?? routes.length - 1, 0), routes.length - 1);
140
+ const routeKeys = new Set(routes.map(route => route.key));
141
+ const retainedRouteKeys = state.retainedRouteKeys?.filter(key => routeKeys.has(key)) ?? [];
105
142
  return {
106
143
  stale: false,
107
144
  type: 'stack',
108
145
  key: `stack-${nanoid()}`,
109
- index: routes.length - 1,
146
+ index,
110
147
  routeNames,
111
148
  routes,
112
- preloadedRoutes
149
+ retainedRouteKeys
113
150
  };
114
151
  },
115
152
  getStateForRouteNamesChange(state, {
@@ -117,7 +154,9 @@ export function StackRouter(options) {
117
154
  routeParamList,
118
155
  routeKeyChanges
119
156
  }) {
120
- const routes = state.routes.filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
157
+ const routes = getActiveRoutes(state).filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
158
+ const preloadedRoutes = getPreloadedRoutes(state).filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
159
+ const retainedRoutes = getRetainedRoutes(state).filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
121
160
  if (routes.length === 0) {
122
161
  const initialRouteName = options.initialRouteName !== undefined && routeNames.includes(options.initialRouteName) ? options.initialRouteName : routeNames[0];
123
162
  routes.push({
@@ -126,32 +165,33 @@ export function StackRouter(options) {
126
165
  params: routeParamList[initialRouteName]
127
166
  });
128
167
  }
129
- return {
168
+ const routeKeys = new Set([...routes, ...preloadedRoutes, ...retainedRoutes].map(route => route.key));
169
+ const retainedRouteKeys = state.retainedRouteKeys.filter(key => routeKeys.has(key));
170
+ return getStateWithRoutes({
130
171
  ...state,
131
172
  routeNames,
132
- routes,
133
- index: Math.min(state.index, routes.length - 1)
134
- };
173
+ retainedRouteKeys
174
+ }, routes, preloadedRoutes, retainedRoutes);
135
175
  },
136
176
  getStateForRouteFocus(state, key) {
137
- const index = state.routes.findIndex(r => r.key === key);
177
+ const routes = getActiveRoutes(state);
178
+ const index = routes.findIndex(r => r.key === key);
138
179
  if (index === -1 || index === state.index) {
139
180
  return state;
140
181
  }
141
- return {
142
- ...state,
143
- index,
144
- routes: state.routes.slice(0, index + 1)
145
- };
182
+ return retainRoutes(state, getStateWithRoutes(state, routes.slice(0, index + 1)));
146
183
  },
147
184
  getStateForAction(state, action, options) {
148
185
  const {
149
186
  routeParamList
150
187
  } = options;
188
+ const routes = getActiveRoutes(state);
189
+ const preloadedRoutes = getPreloadedRoutes(state);
190
+ const inactiveRoutes = getInactiveRoutes(state);
151
191
  switch (action.type) {
152
192
  case 'REPLACE':
153
193
  {
154
- const currentIndex = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
194
+ const currentIndex = action.target === state.key && action.source ? routes.findIndex(r => r.key === action.source) : state.index;
155
195
  if (currentIndex === -1) {
156
196
  return null;
157
197
  }
@@ -163,8 +203,8 @@ export function StackRouter(options) {
163
203
  params: action.payload.params
164
204
  });
165
205
 
166
- // Re-use preloaded route if available
167
- let route = state.preloadedRoutes.find(route => route.name === action.payload.name && id === getId?.({
206
+ // Re-use inactive route if available
207
+ let route = inactiveRoutes.find(route => route.name === action.payload.name && id === getId?.({
168
208
  params: route.params
169
209
  }));
170
210
  if (!route) {
@@ -172,12 +212,19 @@ export function StackRouter(options) {
172
212
  action,
173
213
  routeParamList
174
214
  });
215
+ } else {
216
+ const params = createParamsFromAction({
217
+ action,
218
+ routeParamList
219
+ });
220
+ if (route.params !== params) {
221
+ route = {
222
+ ...route,
223
+ params
224
+ };
225
+ }
175
226
  }
176
- return {
177
- ...state,
178
- routes: state.routes.map((r, i) => i === currentIndex ? route : r),
179
- preloadedRoutes: state.preloadedRoutes.filter(r => r.key !== route.key)
180
- };
227
+ return retainRoutes(state, getStateWithRoutes(state, routes.map((r, i) => i === currentIndex ? route : r), preloadedRoutes.filter(r => r.key !== route.key)));
181
228
  }
182
229
  case 'PUSH':
183
230
  case 'NAVIGATE':
@@ -190,22 +237,55 @@ export function StackRouter(options) {
190
237
  params: action.payload.params
191
238
  });
192
239
  let route;
193
- if (id !== undefined) {
194
- route = state.routes.findLast(route => route.name === action.payload.name && id === getId?.({
195
- params: route.params
196
- }));
197
- } else if (action.type === 'NAVIGATE') {
198
- const currentRoute = state.routes[state.index];
199
-
200
- // If the route matches the current one, then navigate to it
201
- if (action.payload.name === currentRoute.name) {
202
- route = currentRoute;
203
- } else if (action.payload.pop) {
204
- route = state.routes.findLast(route => route.name === action.payload.name);
240
+ if (action.type === 'NAVIGATE') {
241
+ const currentRoute = routes[state.index];
242
+ if (id !== undefined) {
243
+ if (currentRoute.name === action.payload.name && id === getId?.({
244
+ params: currentRoute.params
245
+ })) {
246
+ route = currentRoute;
247
+ } else if (action.payload.pop) {
248
+ for (let i = routes.length - 1; i >= 0; i--) {
249
+ const r = routes[i];
250
+ if (r.name !== action.payload.name) {
251
+ continue;
252
+ }
253
+ if (id === getId?.({
254
+ params: r.params
255
+ })) {
256
+ route = r;
257
+ break;
258
+ }
259
+ if (r.history?.length) {
260
+ for (let j = r.history.length - 1; j >= 0; j--) {
261
+ if (r.history[j].type === 'params' && id === getId?.({
262
+ params: r.history[j].params
263
+ })) {
264
+ route = {
265
+ ...r,
266
+ params: r.history[j].params,
267
+ history: r.history.slice(0, j)
268
+ };
269
+ break;
270
+ }
271
+ }
272
+ if (route) {
273
+ break;
274
+ }
275
+ }
276
+ }
277
+ }
278
+ } else {
279
+ // If the route matches the current one, then navigate to it
280
+ if (action.payload.name === currentRoute.name) {
281
+ route = currentRoute;
282
+ } else if (action.payload.pop) {
283
+ route = routes.findLast(route => route.name === action.payload.name);
284
+ }
205
285
  }
206
286
  }
207
287
  if (!route) {
208
- route = state.preloadedRoutes.find(route => route.name === action.payload.name && id === getId?.({
288
+ route = inactiveRoutes.find(route => route.name === action.payload.name && id === getId?.({
209
289
  params: route.params
210
290
  }));
211
291
  }
@@ -222,50 +302,55 @@ export function StackRouter(options) {
222
302
  routeParamList
223
303
  });
224
304
  }
225
- let routes;
305
+ let nextRoutes;
226
306
  if (route) {
227
307
  if (action.type === 'NAVIGATE' && action.payload.pop) {
228
- routes = [];
308
+ nextRoutes = [];
229
309
 
230
310
  // Get all routes until the matching one
231
- for (const r of state.routes) {
311
+ for (const r of routes) {
232
312
  if (r.key === route.key) {
233
- routes.push({
313
+ nextRoutes.push({
234
314
  ...route,
235
315
  path: action.payload.path !== undefined ? action.payload.path : route.path,
236
316
  params
237
317
  });
238
318
  break;
239
319
  }
240
- routes.push(r);
320
+ nextRoutes.push(r);
321
+ }
322
+ if (!nextRoutes.some(r => r.key === route.key)) {
323
+ nextRoutes.push({
324
+ ...route,
325
+ path: action.payload.path !== undefined ? action.payload.path : route.path,
326
+ params
327
+ });
241
328
  }
242
329
  } else {
243
- routes = state.routes.filter(r => r.key !== route.key);
244
- routes.push({
330
+ nextRoutes = routes.filter(r => r.key !== route.key);
331
+ nextRoutes.push({
245
332
  ...route,
246
333
  path: action.type === 'NAVIGATE' && action.payload.path !== undefined ? action.payload.path : route.path,
247
334
  params
248
335
  });
249
336
  }
250
337
  } else {
251
- routes = [...state.routes, {
338
+ nextRoutes = [...routes, {
252
339
  key: `${action.payload.name}-${nanoid()}`,
253
340
  name: action.payload.name,
254
341
  path: action.type === 'NAVIGATE' ? action.payload.path : undefined,
255
342
  params
256
343
  }];
257
344
  }
258
- return {
259
- ...state,
260
- index: routes.length - 1,
261
- preloadedRoutes: state.preloadedRoutes.filter(route => routes[routes.length - 1].key !== route.key),
262
- routes
263
- };
345
+ return retainRoutes(state, getStateWithRoutes(state, nextRoutes, preloadedRoutes.filter(route => nextRoutes[nextRoutes.length - 1].key !== route.key)));
264
346
  }
265
347
  case 'POP':
266
348
  {
267
- let currentIndex = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
268
- let route = state.routes[currentIndex];
349
+ let currentIndex = action.target === state.key && action.source ? routes.findIndex(r => r.key === action.source) : state.index;
350
+ if (currentIndex === -1) {
351
+ return null;
352
+ }
353
+ let route = routes[currentIndex];
269
354
 
270
355
  /**
271
356
  * When popping entries,
@@ -278,42 +363,38 @@ export function StackRouter(options) {
278
363
  */
279
364
  if (route.history?.length || currentIndex > 0) {
280
365
  let count = action.payload.count;
281
- let routes = state.routes;
366
+ let nextRoutes = routes;
282
367
  while (count > 0 && (route.history?.length || currentIndex > 0)) {
283
368
  if (route.history?.length) {
284
- routes = [...routes];
369
+ nextRoutes = [...nextRoutes];
285
370
  const end = Math.min(count, route.history.length);
286
371
  const last = route.history.at(-end);
287
372
  const history = route.history.slice(0, -end);
288
373
  const removed = route.history.length - history.length;
289
374
  count = count - removed;
290
- routes[currentIndex] = {
375
+ nextRoutes[currentIndex] = {
291
376
  ...route,
292
377
  params: last?.type === 'params' ? last.params : route.params,
293
378
  history
294
379
  };
295
380
  }
296
381
  if (currentIndex > 0 && count > 0) {
297
- const length = routes.length;
382
+ const length = nextRoutes.length;
298
383
  const end = Math.max(currentIndex - count + 1, 1);
299
- routes = routes.slice(0, end).concat(routes.slice(currentIndex + 1));
300
- const removed = length - routes.length;
384
+ nextRoutes = nextRoutes.slice(0, end).concat(nextRoutes.slice(currentIndex + 1));
385
+ const removed = length - nextRoutes.length;
301
386
  count = count - removed;
302
- currentIndex = routes.length - 1;
303
- route = routes[currentIndex];
387
+ currentIndex = nextRoutes.length - 1;
388
+ route = nextRoutes[currentIndex];
304
389
  }
305
390
  }
306
- return {
307
- ...state,
308
- index: routes.length - 1,
309
- routes
310
- };
391
+ return retainRoutes(state, getStateWithRoutes(state, nextRoutes));
311
392
  }
312
393
  return null;
313
394
  }
314
395
  case 'POP_TO_TOP':
315
396
  {
316
- let route = state.routes[0];
397
+ let route = routes[0];
317
398
  if (state.index > 0 || route.history?.length) {
318
399
  if (route.history?.length) {
319
400
  route = {
@@ -321,17 +402,13 @@ export function StackRouter(options) {
321
402
  history: undefined
322
403
  };
323
404
  }
324
- return {
325
- ...state,
326
- index: 0,
327
- routes: [route]
328
- };
405
+ return retainRoutes(state, getStateWithRoutes(state, [route]));
329
406
  }
330
407
  return null;
331
408
  }
332
409
  case 'POP_TO':
333
410
  {
334
- const currentIndex = action.target === state.key && action.source ? state.routes.findLastIndex(r => r.key === action.source) : state.index;
411
+ const currentIndex = action.target === state.key && action.source ? routes.findLastIndex(r => r.key === action.source) : state.index;
335
412
  if (currentIndex === -1) {
336
413
  return null;
337
414
  }
@@ -341,19 +418,43 @@ export function StackRouter(options) {
341
418
 
342
419
  // If the route already exists, navigate to it
343
420
  let index = -1;
421
+ let historyIndex;
344
422
  const getId = options.routeGetIdList[action.payload.name];
345
423
  const id = getId?.({
346
424
  params: action.payload.params
347
425
  });
348
426
  if (id !== undefined) {
349
- index = state.routes.findIndex(route => route.name === action.payload.name && id === getId?.({
350
- params: route.params
351
- }));
352
- } else if (state.routes[currentIndex].name === action.payload.name) {
427
+ for (let i = currentIndex; i >= 0; i--) {
428
+ const r = routes[i];
429
+ if (r.name !== action.payload.name) {
430
+ continue;
431
+ }
432
+ if (id === getId?.({
433
+ params: r.params
434
+ })) {
435
+ index = i;
436
+ break;
437
+ }
438
+ if (r.history?.length) {
439
+ for (let j = r.history.length - 1; j >= 0; j--) {
440
+ if (r.history[j].type === 'params' && id === getId?.({
441
+ params: r.history[j].params
442
+ })) {
443
+ index = i;
444
+ historyIndex = j;
445
+ break;
446
+ }
447
+ }
448
+ if (index !== -1) {
449
+ break;
450
+ }
451
+ }
452
+ }
453
+ } else if (routes[currentIndex].name === action.payload.name) {
353
454
  index = currentIndex;
354
455
  } else {
355
456
  for (let i = currentIndex; i >= 0; i--) {
356
- if (state.routes[i].name === action.payload.name) {
457
+ if (routes[i].name === action.payload.name) {
357
458
  index = i;
358
459
  break;
359
460
  }
@@ -362,8 +463,8 @@ export function StackRouter(options) {
362
463
 
363
464
  // If the route doesn't exist, remove the current route and add the new one
364
465
  if (index === -1) {
365
- // Re-use preloaded route if available
366
- let route = state.preloadedRoutes.find(route => route.name === action.payload.name && id === getId?.({
466
+ // Re-use inactive route if available
467
+ let route = inactiveRoutes.find(route => route.name === action.payload.name && id === getId?.({
367
468
  params: route.params
368
469
  }));
369
470
  if (!route) {
@@ -371,40 +472,49 @@ export function StackRouter(options) {
371
472
  action,
372
473
  routeParamList
373
474
  });
475
+ } else {
476
+ const params = createParamsFromAction({
477
+ action,
478
+ routeParamList
479
+ });
480
+ if (route.params !== params) {
481
+ route = {
482
+ ...route,
483
+ params
484
+ };
485
+ }
374
486
  }
375
- const routes = state.routes.slice(0, currentIndex).concat(route);
376
- return {
377
- ...state,
378
- index: routes.length - 1,
379
- routes,
380
- preloadedRoutes: state.preloadedRoutes.filter(r => r.key !== route.key)
381
- };
487
+ const nextRoutes = routes.slice(0, currentIndex).concat(route);
488
+ return retainRoutes(state, getStateWithRoutes(state, nextRoutes, preloadedRoutes.filter(r => r.key !== route.key)));
489
+ }
490
+ const route = routes[index];
491
+ let baseParams = route.params;
492
+ let history = route.history;
493
+ if (historyIndex !== undefined && route.history) {
494
+ baseParams = route.history[historyIndex].params;
495
+ history = route.history.slice(0, historyIndex);
382
496
  }
383
- const route = state.routes[index];
384
497
  let params;
385
498
  if (action.payload.merge) {
386
499
  params = action.payload.params !== undefined || routeParamList[route.name] !== undefined ? {
387
500
  ...routeParamList[route.name],
388
- ...route.params,
501
+ ...baseParams,
389
502
  ...action.payload.params
390
- } : route.params;
503
+ } : baseParams;
391
504
  } else {
392
505
  params = createParamsFromAction({
393
506
  action,
394
507
  routeParamList
395
508
  });
396
509
  }
397
- return {
398
- ...state,
399
- index,
400
- routes: [...state.routes.slice(0, index), params !== route.params ? {
401
- ...route,
402
- params
403
- } : state.routes[index]]
404
- };
510
+ return retainRoutes(state, getStateWithRoutes(state, [...routes.slice(0, index), params !== baseParams || historyIndex !== undefined ? {
511
+ ...route,
512
+ params,
513
+ history
514
+ } : routes[index]]));
405
515
  }
406
516
  case 'GO_BACK':
407
- if (state.index > 0 || state.routes[state.index].history?.length) {
517
+ if (state.index > 0 || routes[state.index].history?.length) {
408
518
  return router.getStateForAction(state, {
409
519
  type: 'POP',
410
520
  payload: {
@@ -415,45 +525,55 @@ export function StackRouter(options) {
415
525
  }, options);
416
526
  }
417
527
  return null;
528
+ case 'RETAIN':
529
+ {
530
+ const routeKey = action.source ?? routes[state.index].key;
531
+ if (!state.routes.some(route => route.key === routeKey)) {
532
+ return null;
533
+ }
534
+ if (action.payload.enable) {
535
+ if (state.retainedRouteKeys.includes(routeKey)) {
536
+ return state;
537
+ }
538
+ return {
539
+ ...state,
540
+ retainedRouteKeys: [...state.retainedRouteKeys, routeKey]
541
+ };
542
+ }
543
+ if (!state.retainedRouteKeys.includes(routeKey)) {
544
+ return state;
545
+ }
546
+ return getStateWithRoutes({
547
+ ...state,
548
+ retainedRouteKeys: state.retainedRouteKeys.filter(key => key !== routeKey)
549
+ }, routes, preloadedRoutes.filter(route => route.key !== routeKey));
550
+ }
418
551
  case 'PRELOAD':
419
552
  {
553
+ if (!state.routeNames.includes(action.payload.name)) {
554
+ return null;
555
+ }
420
556
  const getId = options.routeGetIdList[action.payload.name];
421
557
  const id = getId?.({
422
558
  params: action.payload.params
423
559
  });
424
- let route;
425
- if (id !== undefined) {
426
- route = state.routes.find(route => route.name === action.payload.name && id === getId?.({
427
- params: route.params
428
- }));
429
- }
560
+ const params = createParamsFromAction({
561
+ action,
562
+ routeParamList
563
+ });
564
+ const route = preloadedRoutes.findLast(route => route.name === action.payload.name && (id === undefined || id === getId?.({
565
+ params: route.params
566
+ })));
430
567
  if (route) {
431
- return {
432
- ...state,
433
- routes: state.routes.map(r => {
434
- if (r.key !== route?.key) {
435
- return r;
436
- }
437
- return {
438
- ...r,
439
- params: createParamsFromAction({
440
- action,
441
- routeParamList
442
- })
443
- };
444
- })
445
- };
446
- } else {
447
- return {
448
- ...state,
449
- preloadedRoutes: state.preloadedRoutes.filter(r => r.name !== action.payload.name || id !== getId?.({
450
- params: r.params
451
- })).concat(createRouteFromAction({
452
- action,
453
- routeParamList
454
- }))
455
- };
568
+ return getStateWithRoutes(state, routes, preloadedRoutes.map(r => r.key === route.key && r.params !== params ? {
569
+ ...r,
570
+ params
571
+ } : r));
456
572
  }
573
+ return getStateWithRoutes(state, routes, preloadedRoutes.concat(createRouteFromAction({
574
+ action,
575
+ routeParamList
576
+ })));
457
577
  }
458
578
  default:
459
579
  return BaseRouter.getStateForAction(state, action);