@tanstack/react-router 1.8.4 → 1.10.0

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 (52) hide show
  1. package/dist/cjs/Matches.cjs +1 -1
  2. package/dist/cjs/Matches.cjs.map +1 -1
  3. package/dist/cjs/Matches.d.cts +16 -11
  4. package/dist/cjs/RouterProvider.cjs.map +1 -1
  5. package/dist/cjs/RouterProvider.d.cts +1 -1
  6. package/dist/cjs/fileRoute.cjs +48 -1
  7. package/dist/cjs/fileRoute.cjs.map +1 -1
  8. package/dist/cjs/fileRoute.d.cts +40 -2
  9. package/dist/cjs/index.cjs +7 -0
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/route.cjs +13 -1
  12. package/dist/cjs/route.cjs.map +1 -1
  13. package/dist/cjs/route.d.cts +76 -4
  14. package/dist/cjs/router.cjs +44 -18
  15. package/dist/cjs/router.cjs.map +1 -1
  16. package/dist/cjs/router.d.cts +7 -3
  17. package/dist/cjs/useParams.cjs.map +1 -1
  18. package/dist/cjs/useParams.d.cts +3 -2
  19. package/dist/cjs/useSearch.cjs.map +1 -1
  20. package/dist/cjs/useSearch.d.cts +3 -3
  21. package/dist/cjs/utils.cjs.map +1 -1
  22. package/dist/cjs/utils.d.cts +2 -1
  23. package/dist/esm/Matches.d.ts +16 -11
  24. package/dist/esm/Matches.js +1 -1
  25. package/dist/esm/Matches.js.map +1 -1
  26. package/dist/esm/RouterProvider.d.ts +1 -1
  27. package/dist/esm/RouterProvider.js.map +1 -1
  28. package/dist/esm/fileRoute.d.ts +40 -2
  29. package/dist/esm/fileRoute.js +50 -3
  30. package/dist/esm/fileRoute.js.map +1 -1
  31. package/dist/esm/index.js +10 -3
  32. package/dist/esm/route.d.ts +76 -4
  33. package/dist/esm/route.js +13 -1
  34. package/dist/esm/route.js.map +1 -1
  35. package/dist/esm/router.d.ts +7 -3
  36. package/dist/esm/router.js +44 -18
  37. package/dist/esm/router.js.map +1 -1
  38. package/dist/esm/useParams.d.ts +3 -2
  39. package/dist/esm/useParams.js.map +1 -1
  40. package/dist/esm/useSearch.d.ts +3 -3
  41. package/dist/esm/useSearch.js.map +1 -1
  42. package/dist/esm/utils.d.ts +2 -1
  43. package/dist/esm/utils.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/Matches.tsx +50 -17
  46. package/src/RouterProvider.tsx +7 -2
  47. package/src/fileRoute.ts +113 -6
  48. package/src/route.ts +226 -20
  49. package/src/router.ts +54 -10
  50. package/src/useParams.tsx +7 -4
  51. package/src/useSearch.tsx +12 -7
  52. package/src/utils.ts +2 -1
package/src/router.ts CHANGED
@@ -176,7 +176,7 @@ export interface DehydratedRouterState {
176
176
 
177
177
  export type DehydratedRouteMatch = Pick<
178
178
  RouteMatch,
179
- 'id' | 'status' | 'updatedAt'
179
+ 'id' | 'status' | 'updatedAt' | 'loaderData'
180
180
  >
181
181
 
182
182
  export interface DehydratedRouter {
@@ -224,6 +224,19 @@ export type RouterListener<TRouterEvent extends RouterEvent> = {
224
224
  fn: ListenerFn<TRouterEvent>
225
225
  }
226
226
 
227
+ export function createRouter<
228
+ TRouteTree extends AnyRoute = AnyRoute,
229
+ TDehydrated extends Record<string, any> = Record<string, any>,
230
+ TSerializedError extends Record<string, any> = Record<string, any>,
231
+ >(
232
+ options: RouterConstructorOptions<TRouteTree, TDehydrated, TSerializedError>,
233
+ ) {
234
+ return new Router<TRouteTree, TDehydrated, TSerializedError>(options)
235
+ }
236
+
237
+ /**
238
+ * @deprecated Use the `createRouter` function instead
239
+ */
227
240
  export class Router<
228
241
  TRouteTree extends AnyRoute = AnyRoute,
229
242
  TDehydrated extends Record<string, any> = Record<string, any>,
@@ -691,6 +704,7 @@ export class Router<
691
704
  // Create a fresh route match
692
705
  const hasLoaders = !!(
693
706
  route.options.loader ||
707
+ route.options.lazy ||
694
708
  componentTypes.some((d) => (route.options[d] as any)?.preload)
695
709
  )
696
710
 
@@ -1142,6 +1156,9 @@ export class Router<
1142
1156
  ...beforeLoadContext,
1143
1157
  }
1144
1158
 
1159
+ const links = route.options.links?.()
1160
+ const scripts = route.options.scripts?.()
1161
+
1145
1162
  matches[index] = match = {
1146
1163
  ...match,
1147
1164
  routeContext: replaceEqualDeep(
@@ -1151,6 +1168,8 @@ export class Router<
1151
1168
  context: replaceEqualDeep(match.context, context),
1152
1169
  abortController,
1153
1170
  pendingPromise,
1171
+ links,
1172
+ scripts,
1154
1173
  }
1155
1174
  } catch (err) {
1156
1175
  handleErrorAndRedirect(err, 'BEFORE_LOAD')
@@ -1234,21 +1253,33 @@ export class Router<
1234
1253
  fetchCount: match.fetchCount + 1,
1235
1254
  }
1236
1255
 
1237
- const componentsPromise = Promise.all(
1238
- componentTypes.map(async (type) => {
1239
- const component = route.options[type]
1240
-
1241
- if ((component as any)?.preload) {
1242
- await (component as any).preload()
1243
- }
1244
- }),
1256
+ const lazyPromise =
1257
+ route.options.lazy?.().then((lazyRoute) => {
1258
+ Object.assign(route.options, lazyRoute.options)
1259
+ }) || Promise.resolve()
1260
+
1261
+ // If for some reason lazy resolves more lazy components...
1262
+ // We'll wait for that before pre attempt to preload any
1263
+ // components themselves.
1264
+ const componentsPromise = lazyPromise.then(() =>
1265
+ Promise.all(
1266
+ componentTypes.map(async (type) => {
1267
+ const component = route.options[type]
1268
+
1269
+ if ((component as any)?.preload) {
1270
+ await (component as any).preload()
1271
+ }
1272
+ }),
1273
+ ),
1245
1274
  )
1246
1275
 
1276
+ // Kick off the loader!
1247
1277
  const loaderPromise = route.options.loader?.(loaderContext)
1248
1278
 
1249
1279
  loadPromise = Promise.all([
1250
1280
  componentsPromise,
1251
1281
  loaderPromise,
1282
+ lazyPromise,
1252
1283
  ]).then((d) => d[1])
1253
1284
  }
1254
1285
 
@@ -1273,6 +1304,10 @@ export class Router<
1273
1304
 
1274
1305
  if ((latestPromise = checkLatest())) return await latestPromise
1275
1306
 
1307
+ const meta = route.options.meta?.({
1308
+ loaderData,
1309
+ })
1310
+
1276
1311
  matches[index] = match = {
1277
1312
  ...match,
1278
1313
  error: undefined,
@@ -1281,6 +1316,7 @@ export class Router<
1281
1316
  updatedAt: Date.now(),
1282
1317
  loaderData,
1283
1318
  loadPromise: undefined,
1319
+ meta,
1284
1320
  }
1285
1321
  } catch (error) {
1286
1322
  if ((latestPromise = checkLatest())) return await latestPromise
@@ -1704,9 +1740,16 @@ export class Router<
1704
1740
  )
1705
1741
 
1706
1742
  if (dehydratedMatch) {
1743
+ const route = this.looseRoutesById[match.routeId]!
1744
+
1707
1745
  return {
1708
1746
  ...match,
1709
1747
  ...dehydratedMatch,
1748
+ meta: route.options.meta?.({
1749
+ loaderData: dehydratedMatch.loaderData,
1750
+ }),
1751
+ links: route.options.links?.(),
1752
+ scripts: route.options.scripts?.(),
1710
1753
  }
1711
1754
  }
1712
1755
  return match
@@ -1716,6 +1759,7 @@ export class Router<
1716
1759
  return {
1717
1760
  ...s,
1718
1761
  matches: matches as any,
1762
+ lastUpdated: Date.now(),
1719
1763
  }
1720
1764
  })
1721
1765
  }
@@ -1758,7 +1802,7 @@ export function getInitialRouterState(
1758
1802
  matches: [],
1759
1803
  pendingMatches: [],
1760
1804
  cachedMatches: [],
1761
- lastUpdated: Date.now(),
1805
+ lastUpdated: 0,
1762
1806
  }
1763
1807
  }
1764
1808
 
package/src/useParams.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AnyRoute } from './route'
2
- import { RouteIds, RouteById } from './routeInfo'
2
+ import { RouteIds, RouteById, AllParams } from './routeInfo'
3
3
  import { RegisteredRouter } from './router'
4
- import { last } from './utils'
4
+ import { Expand, last } from './utils'
5
5
  import { useRouterState } from './useRouterState'
6
6
  import { StrictOrFrom } from './utils'
7
7
  import { getRenderedMatches } from './Matches'
@@ -9,10 +9,13 @@ import { getRenderedMatches } from './Matches'
9
9
  export function useParams<
10
10
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
11
11
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
12
- TParams = RouteById<TRouteTree, TFrom>['types']['allParams'],
12
+ TReturnIntersection extends boolean = false,
13
+ TParams = TReturnIntersection extends false
14
+ ? RouteById<TRouteTree, TFrom>['types']['allParams']
15
+ : Expand<Partial<AllParams<TRouteTree>>>,
13
16
  TSelected = TParams,
14
17
  >(
15
- opts: StrictOrFrom<TFrom> & {
18
+ opts: StrictOrFrom<TFrom, TReturnIntersection> & {
16
19
  select?: (params: TParams) => TSelected
17
20
  },
18
21
  ): TSelected {
package/src/useSearch.tsx CHANGED
@@ -1,20 +1,25 @@
1
1
  import { AnyRoute, RootSearchSchema } from './route'
2
- import { RouteIds, RouteById } from './routeInfo'
2
+ import { RouteIds, RouteById, FullSearchSchema } from './routeInfo'
3
3
  import { RegisteredRouter } from './router'
4
4
  import { RouteMatch } from './Matches'
5
5
  import { useMatch } from './Matches'
6
- import { StrictOrFrom } from './utils'
6
+ import { Expand, StrictOrFrom } from './utils'
7
7
 
8
8
  export function useSearch<
9
9
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
10
10
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
11
- TSearch = Exclude<
12
- RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'],
13
- RootSearchSchema
14
- >,
11
+ TReturnIntersection extends boolean = false,
12
+ TSearch = TReturnIntersection extends false
13
+ ? Exclude<
14
+ RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'],
15
+ RootSearchSchema
16
+ >
17
+ : Expand<
18
+ Partial<Omit<FullSearchSchema<TRouteTree>, keyof RootSearchSchema>>
19
+ >,
15
20
  TSelected = TSearch,
16
21
  >(
17
- opts: StrictOrFrom<TFrom> & {
22
+ opts: StrictOrFrom<TFrom, TReturnIntersection> & {
18
23
  select?: (search: TSearch) => TSelected
19
24
  },
20
25
  ): TSelected {
package/src/utils.ts CHANGED
@@ -300,7 +300,7 @@ export type StringLiteral<T> = T extends string
300
300
  : T
301
301
  : never
302
302
 
303
- export type StrictOrFrom<TFrom> =
303
+ export type StrictOrFrom<TFrom, TReturnIntersection extends boolean = false> =
304
304
  | {
305
305
  from: StringLiteral<TFrom> | TFrom
306
306
  strict?: true
@@ -308,6 +308,7 @@ export type StrictOrFrom<TFrom> =
308
308
  | {
309
309
  from?: never
310
310
  strict: false
311
+ experimental_returnIntersection?: TReturnIntersection
311
312
  }
312
313
 
313
314
  export const useLayoutEffect =