@tanstack/react-router 1.64.0 → 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.
- package/dist/cjs/router.cjs +66 -45
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +10 -0
- package/dist/esm/router.d.ts +10 -0
- package/dist/esm/router.js +67 -46
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
- package/src/router.ts +86 -70
package/dist/cjs/router.d.cts
CHANGED
|
@@ -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;
|
package/dist/esm/router.d.ts
CHANGED
|
@@ -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;
|
package/dist/esm/router.js
CHANGED
|
@@ -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,
|
|
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 = {},
|
|
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 =
|
|
257
|
-
(d) => fromMatches.find((e) => e.routeId === d.
|
|
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
|
-
|
|
311
|
+
matchedRoutesResult == null ? void 0 : matchedRoutesResult.matchedRoutes.map((route) => {
|
|
268
312
|
var _a2;
|
|
269
|
-
|
|
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
|
-
|
|
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.
|
|
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 (
|
|
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
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
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;
|