@tanstack/react-router 1.63.5 → 1.64.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.
@@ -379,6 +379,10 @@ export interface BuildNextOptions {
379
379
  from?: string;
380
380
  _fromLocation?: ParsedLocation;
381
381
  }
382
+ export interface MatchedRoutesResult {
383
+ matchedRoutes: Array<AnyRoute>;
384
+ routeParams: Record<string, string>;
385
+ }
382
386
  export interface DehydratedRouterState {
383
387
  dehydratedMatches: Array<DehydratedRouteMatch>;
384
388
  }
@@ -425,6 +429,7 @@ type MatchRoutesOpts = {
425
429
  preload?: boolean;
426
430
  throwOnError?: boolean;
427
431
  _buildLocation?: boolean;
432
+ dest?: BuildNextOptions;
428
433
  };
429
434
  export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailingSlashOption extends TrailingSlashOption, in out TDehydrated extends Record<string, any> = Record<string, any>, in out TSerializedError extends Record<string, any> = Record<string, any>> {
430
435
  tempLocationKey: string | undefined;
@@ -480,6 +485,11 @@ export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailing
480
485
  matchRoutes(pathname: string, locationSearch: AnySearchSchema, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
481
486
  matchRoutes(next: ParsedLocation, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
482
487
  private matchRoutesInternal;
488
+ getMatchedRoutes: (next: ParsedLocation, dest?: BuildNextOptions) => {
489
+ matchedRoutes: AnyRoute[];
490
+ routeParams: Record<string, string>;
491
+ foundRoute: AnyRoute | undefined;
492
+ };
483
493
  cancelMatch: (id: string) => void;
484
494
  cancelMatches: () => void;
485
495
  buildLocation: BuildLocationFn;
@@ -379,6 +379,10 @@ export interface BuildNextOptions {
379
379
  from?: string;
380
380
  _fromLocation?: ParsedLocation;
381
381
  }
382
+ export interface MatchedRoutesResult {
383
+ matchedRoutes: Array<AnyRoute>;
384
+ routeParams: Record<string, string>;
385
+ }
382
386
  export interface DehydratedRouterState {
383
387
  dehydratedMatches: Array<DehydratedRouteMatch>;
384
388
  }
@@ -425,6 +429,7 @@ type MatchRoutesOpts = {
425
429
  preload?: boolean;
426
430
  throwOnError?: boolean;
427
431
  _buildLocation?: boolean;
432
+ dest?: BuildNextOptions;
428
433
  };
429
434
  export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailingSlashOption extends TrailingSlashOption, in out TDehydrated extends Record<string, any> = Record<string, any>, in out TSerializedError extends Record<string, any> = Record<string, any>> {
430
435
  tempLocationKey: string | undefined;
@@ -480,6 +485,11 @@ export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailing
480
485
  matchRoutes(pathname: string, locationSearch: AnySearchSchema, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
481
486
  matchRoutes(next: ParsedLocation, opts?: MatchRoutesOpts): Array<AnyRouteMatch>;
482
487
  private matchRoutesInternal;
488
+ getMatchedRoutes: (next: ParsedLocation, dest?: BuildNextOptions) => {
489
+ matchedRoutes: AnyRoute[];
490
+ routeParams: Record<string, string>;
491
+ foundRoute: AnyRoute | undefined;
492
+ };
483
493
  cancelMatch: (id: string) => void;
484
494
  cancelMatches: () => void;
485
495
  buildLocation: BuildLocationFn;
@@ -5,7 +5,7 @@ import warning from "tiny-warning";
5
5
  import { rootRouteId } from "./root.js";
6
6
  import { defaultStringifySearch, defaultParseSearch } from "./searchParams.js";
7
7
  import { pick, createControlledPromise, deepEqual, replaceEqualDeep, last, functionalUpdate } from "./utils.js";
8
- import { trimPath, trimPathLeft, parsePathname, resolvePath, cleanPath, matchPathname, trimPathRight, interpolatePath, joinPaths } from "./path.js";
8
+ import { trimPath, trimPathLeft, parsePathname, resolvePath, cleanPath, trimPathRight, matchPathname, interpolatePath, joinPaths } from "./path.js";
9
9
  import { isResolvedRedirect, isRedirect } from "./redirects.js";
10
10
  import { isNotFound } from "./not-found.js";
11
11
  import { defaultTransformer } from "./transformer.js";
@@ -224,6 +224,38 @@ class Router {
224
224
  });
225
225
  return resolvedPath;
226
226
  };
227
+ this.getMatchedRoutes = (next, dest) => {
228
+ let routeParams = {};
229
+ const trimmedPath = trimPathRight(next.pathname);
230
+ const getMatchedParams = (route) => {
231
+ const result = matchPathname(this.basepath, trimmedPath, {
232
+ to: route.fullPath,
233
+ caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
234
+ fuzzy: true
235
+ });
236
+ return result;
237
+ };
238
+ let foundRoute = (dest == null ? void 0 : dest.to) !== void 0 ? this.routesByPath[dest.to] : void 0;
239
+ if (foundRoute) {
240
+ routeParams = getMatchedParams(foundRoute);
241
+ } else {
242
+ foundRoute = this.flatRoutes.find((route) => {
243
+ const matchedParams = getMatchedParams(route);
244
+ if (matchedParams) {
245
+ routeParams = matchedParams;
246
+ return true;
247
+ }
248
+ return false;
249
+ });
250
+ }
251
+ let routeCursor = foundRoute || this.routesById[rootRouteId];
252
+ const matchedRoutes = [routeCursor];
253
+ while (routeCursor.parentRoute) {
254
+ routeCursor = routeCursor.parentRoute;
255
+ matchedRoutes.unshift(routeCursor);
256
+ }
257
+ return { matchedRoutes, routeParams, foundRoute };
258
+ };
227
259
  this.cancelMatch = (id) => {
228
260
  const match = this.getMatch(id);
229
261
  if (!match) return;
@@ -237,7 +269,7 @@ class Router {
237
269
  });
238
270
  };
239
271
  this.buildLocation = (opts) => {
240
- const build = (dest = {}, matches) => {
272
+ const build = (dest = {}, matchedRoutesResult) => {
241
273
  var _a, _b, _c, _d, _e;
242
274
  const fromMatches = dest._fromLocation ? this.matchRoutes(dest._fromLocation, { _buildLocation: true }) : this.state.matches;
243
275
  const fromMatch = dest.from != null ? fromMatches.find(
@@ -253,21 +285,32 @@ class Router {
253
285
  "Could not find match for from: " + dest.from
254
286
  );
255
287
  const fromSearch = ((_a = this.state.pendingMatches) == null ? void 0 : _a.length) ? (_b = last(this.state.pendingMatches)) == null ? void 0 : _b.search : ((_c = last(fromMatches)) == null ? void 0 : _c.search) || this.latestLocation.search;
256
- const stayingMatches = matches == null ? void 0 : matches.filter(
257
- (d) => fromMatches.find((e) => e.routeId === d.routeId)
258
- );
259
- const fromRouteByFromPathRouteId = this.routesById[(_d = stayingMatches == null ? void 0 : stayingMatches.find((d) => d.pathname === fromPath)) == null ? void 0 : _d.routeId];
260
- let pathname = dest.to ? this.resolvePathWithBase(fromPath, `${dest.to}`) : this.resolvePathWithBase(
261
- fromPath,
262
- (fromRouteByFromPathRouteId == null ? void 0 : fromRouteByFromPathRouteId.to) ?? fromPath
288
+ const stayingMatches = matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.filter(
289
+ (d) => fromMatches.find((e) => e.routeId === d.id)
263
290
  );
291
+ let pathname;
292
+ if (dest.to) {
293
+ pathname = this.resolvePathWithBase(fromPath, `${dest.to}`);
294
+ } else {
295
+ const fromRouteByFromPathRouteId = this.routesById[(_d = stayingMatches == null ? void 0 : stayingMatches.find((route) => {
296
+ const interpolatedPath = interpolatePath({
297
+ path: route.fullPath,
298
+ params: (matchedRoutesResult == null ? void 0 : matchedRoutesResult.routeParams) ?? {}
299
+ });
300
+ const pathname2 = joinPaths([this.basepath, interpolatedPath]);
301
+ return pathname2 === fromPath;
302
+ })) == null ? void 0 : _d.id];
303
+ pathname = this.resolvePathWithBase(
304
+ fromPath,
305
+ (fromRouteByFromPathRouteId == null ? void 0 : fromRouteByFromPathRouteId.to) ?? fromPath
306
+ );
307
+ }
264
308
  const prevParams = { ...(_e = last(fromMatches)) == null ? void 0 : _e.params };
265
309
  let nextParams = (dest.params ?? true) === true ? prevParams : { ...prevParams, ...functionalUpdate(dest.params, prevParams) };
266
310
  if (Object.keys(nextParams).length > 0) {
267
- matches == null ? void 0 : matches.map((d) => {
311
+ matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.map((route) => {
268
312
  var _a2;
269
- const route = this.looseRoutesById[d.routeId];
270
- return ((_a2 = route == null ? void 0 : route.options.params) == null ? void 0 : _a2.stringify) ?? route.options.stringifyParams;
313
+ return ((_a2 = route.options.params) == null ? void 0 : _a2.stringify) ?? route.options.stringifyParams;
271
314
  }).filter(Boolean).forEach((fn) => {
272
315
  nextParams = { ...nextParams, ...fn(nextParams) };
273
316
  });
@@ -278,12 +321,8 @@ class Router {
278
321
  leaveWildcards: false,
279
322
  leaveParams: opts.leaveParams
280
323
  });
281
- const preSearchFilters = (stayingMatches == null ? void 0 : stayingMatches.map(
282
- (match) => this.looseRoutesById[match.routeId].options.preSearchFilters ?? []
283
- ).flat().filter(Boolean)) ?? [];
284
- const postSearchFilters = (stayingMatches == null ? void 0 : stayingMatches.map(
285
- (match) => this.looseRoutesById[match.routeId].options.postSearchFilters ?? []
286
- ).flat().filter(Boolean)) ?? [];
324
+ const preSearchFilters = (stayingMatches == null ? void 0 : stayingMatches.map((route) => route.options.preSearchFilters ?? []).flat().filter(Boolean)) ?? [];
325
+ const postSearchFilters = (stayingMatches == null ? void 0 : stayingMatches.map((route) => route.options.postSearchFilters ?? []).flat().filter(Boolean)) ?? [];
287
326
  const preFilteredSearch = preSearchFilters.length ? preSearchFilters.reduce((prev, next) => next(prev), fromSearch) : fromSearch;
288
327
  const destSearch = dest.search === true ? preFilteredSearch : dest.search ? functionalUpdate(dest.search, preFilteredSearch) : preSearchFilters.length ? preFilteredSearch : {};
289
328
  const postFilteredSearch = postSearchFilters.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
@@ -331,11 +370,11 @@ class Router {
331
370
  maskedNext = build(maskedDest);
332
371
  }
333
372
  }
334
- const nextMatches = this.matchRoutes(next, { _buildLocation: true });
335
- const maskedMatches = maskedNext ? this.matchRoutes(maskedNext, { _buildLocation: true }) : void 0;
336
- const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : void 0;
373
+ const nextMatches = this.getMatchedRoutes(next, dest);
337
374
  const final = build(dest, nextMatches);
338
- if (maskedFinal) {
375
+ if (maskedNext) {
376
+ const maskedMatches = this.getMatchedRoutes(maskedNext, maskedDest);
377
+ const maskedFinal = build(maskedDest, maskedMatches);
339
378
  final.maskedLocation = maskedFinal;
340
379
  }
341
380
  return final;
@@ -1018,7 +1057,8 @@ class Router {
1018
1057
  const next = this.buildLocation(opts);
1019
1058
  let matches = this.matchRoutes(next, {
1020
1059
  throwOnError: true,
1021
- preload: true
1060
+ preload: true,
1061
+ dest: opts
1022
1062
  });
1023
1063
  const loadedMatchIds = Object.fromEntries(
1024
1064
  [
@@ -1263,25 +1303,10 @@ class Router {
1263
1303
  }
1264
1304
  }
1265
1305
  matchRoutesInternal(next, opts) {
1266
- let routeParams = {};
1267
- const foundRoute = this.flatRoutes.find((route) => {
1268
- const matchedParams = matchPathname(
1269
- this.basepath,
1270
- trimPathRight(next.pathname),
1271
- {
1272
- to: route.fullPath,
1273
- caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
1274
- fuzzy: true
1275
- }
1276
- );
1277
- if (matchedParams) {
1278
- routeParams = matchedParams;
1279
- return true;
1280
- }
1281
- return false;
1282
- });
1283
- let routeCursor = foundRoute || this.routesById[rootRouteId];
1284
- const matchedRoutes = [routeCursor];
1306
+ const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
1307
+ next,
1308
+ opts == null ? void 0 : opts.dest
1309
+ );
1285
1310
  let isGlobalNotFound = false;
1286
1311
  if (
1287
1312
  // If we found a route, and it's not an index route and we have left over path
@@ -1296,10 +1321,6 @@ class Router {
1296
1321
  isGlobalNotFound = true;
1297
1322
  }
1298
1323
  }
1299
- while (routeCursor.parentRoute) {
1300
- routeCursor = routeCursor.parentRoute;
1301
- matchedRoutes.unshift(routeCursor);
1302
- }
1303
1324
  const globalNotFoundRouteId = (() => {
1304
1325
  if (!isGlobalNotFound) {
1305
1326
  return void 0;