@tanstack/react-router 0.0.1-beta.204 → 0.0.1-beta.206

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 (73) hide show
  1. package/build/cjs/RouterProvider.js +963 -0
  2. package/build/cjs/RouterProvider.js.map +1 -0
  3. package/build/cjs/fileRoute.js +29 -0
  4. package/build/cjs/fileRoute.js.map +1 -0
  5. package/build/cjs/index.js +69 -21
  6. package/build/cjs/index.js.map +1 -1
  7. package/build/cjs/path.js +211 -0
  8. package/build/cjs/path.js.map +1 -0
  9. package/build/cjs/qss.js +65 -0
  10. package/build/cjs/qss.js.map +1 -0
  11. package/build/cjs/react.js +148 -190
  12. package/build/cjs/react.js.map +1 -1
  13. package/build/cjs/redirects.js +27 -0
  14. package/build/cjs/redirects.js.map +1 -0
  15. package/build/cjs/route.js +136 -0
  16. package/build/cjs/route.js.map +1 -0
  17. package/build/cjs/router.js +203 -0
  18. package/build/cjs/router.js.map +1 -0
  19. package/build/cjs/searchParams.js +83 -0
  20. package/build/cjs/searchParams.js.map +1 -0
  21. package/build/cjs/utils.js +196 -0
  22. package/build/cjs/utils.js.map +1 -0
  23. package/build/esm/index.js +1801 -211
  24. package/build/esm/index.js.map +1 -1
  25. package/build/stats-html.html +1 -1
  26. package/build/stats-react.json +385 -164
  27. package/build/types/RouteMatch.d.ts +23 -0
  28. package/build/types/RouterProvider.d.ts +54 -0
  29. package/build/types/awaited.d.ts +0 -8
  30. package/build/types/defer.d.ts +0 -0
  31. package/build/types/fileRoute.d.ts +17 -0
  32. package/build/types/history.d.ts +7 -0
  33. package/build/types/index.d.ts +17 -4
  34. package/build/types/link.d.ts +98 -0
  35. package/build/types/location.d.ts +14 -0
  36. package/build/types/path.d.ts +16 -0
  37. package/build/types/qss.d.ts +2 -0
  38. package/build/types/react.d.ts +23 -83
  39. package/build/types/redirects.d.ts +10 -0
  40. package/build/types/route.d.ts +222 -0
  41. package/build/types/routeInfo.d.ts +22 -0
  42. package/build/types/router.d.ts +115 -0
  43. package/build/types/scroll-restoration.d.ts +0 -3
  44. package/build/types/searchParams.d.ts +7 -0
  45. package/build/types/utils.d.ts +48 -0
  46. package/build/umd/index.development.js +1118 -1540
  47. package/build/umd/index.development.js.map +1 -1
  48. package/build/umd/index.production.js +2 -33
  49. package/build/umd/index.production.js.map +1 -1
  50. package/package.json +2 -4
  51. package/src/RouteMatch.ts +28 -0
  52. package/src/RouterProvider.tsx +1390 -0
  53. package/src/awaited.tsx +40 -40
  54. package/src/defer.ts +55 -0
  55. package/src/fileRoute.ts +143 -0
  56. package/src/history.ts +8 -0
  57. package/src/index.tsx +18 -5
  58. package/src/link.ts +347 -0
  59. package/src/location.ts +14 -0
  60. package/src/path.ts +256 -0
  61. package/src/qss.ts +53 -0
  62. package/src/react.tsx +174 -422
  63. package/src/redirects.ts +31 -0
  64. package/src/route.ts +710 -0
  65. package/src/routeInfo.ts +68 -0
  66. package/src/router.ts +373 -0
  67. package/src/scroll-restoration.tsx +205 -27
  68. package/src/searchParams.ts +78 -0
  69. package/src/utils.ts +257 -0
  70. package/build/cjs/awaited.js +0 -45
  71. package/build/cjs/awaited.js.map +0 -1
  72. package/build/cjs/scroll-restoration.js +0 -56
  73. package/build/cjs/scroll-restoration.js.map +0 -1
package/src/route.ts ADDED
@@ -0,0 +1,710 @@
1
+ import invariant from 'tiny-invariant'
2
+ import { RoutePaths } from './routeInfo'
3
+ import { joinPaths, trimPath } from './path'
4
+ import { AnyRouter } from './router'
5
+ import { AnyRouteMatch } from './RouteMatch'
6
+ import {
7
+ Expand,
8
+ IsAny,
9
+ NoInfer,
10
+ PickRequired,
11
+ UnionToIntersection,
12
+ Assign,
13
+ } from './utils'
14
+ import { ParsePathParams, ToSubOptions } from './link'
15
+ import {
16
+ ErrorRouteComponent,
17
+ PendingRouteComponent,
18
+ RouteComponent,
19
+ RouteProps,
20
+ useMatch,
21
+ useParams,
22
+ useSearch,
23
+ } from './react'
24
+ import { HistoryLocation } from '@tanstack/history'
25
+ import { ParsedLocation } from './location'
26
+
27
+ export const rootRouteId = '__root__' as const
28
+ export type RootRouteId = typeof rootRouteId
29
+ export type AnyPathParams = {}
30
+ export type AnySearchSchema = {}
31
+ export type AnyContext = {}
32
+ export interface RouteMeta {}
33
+
34
+ export type PreloadableObj = { preload?: () => Promise<void> }
35
+
36
+ export type RoutePathOptions<TCustomId, TPath> =
37
+ | {
38
+ path: TPath
39
+ }
40
+ | {
41
+ id: TCustomId
42
+ }
43
+
44
+ export type RoutePathOptionsIntersection<TCustomId, TPath> =
45
+ UnionToIntersection<RoutePathOptions<TCustomId, TPath>>
46
+
47
+ // export type MetaOptions = keyof PickRequired<RouteMeta> extends never
48
+ // ? {
49
+ // meta?: RouteMeta
50
+ // }
51
+ // : {
52
+ // meta: RouteMeta
53
+ // }
54
+
55
+ export type RouteOptions<
56
+ TParentRoute extends AnyRoute = AnyRoute,
57
+ TCustomId extends string = string,
58
+ TPath extends string = string,
59
+ TSearchSchema extends Record<string, any> = {},
60
+ TFullSearchSchema extends Record<string, any> = TSearchSchema,
61
+ TParams extends AnyPathParams = AnyPathParams,
62
+ TAllParams extends AnyPathParams = TParams,
63
+ TRouteMeta extends RouteMeta = RouteMeta,
64
+ TAllMeta extends Record<string, any> = AnyContext,
65
+ > = BaseRouteOptions<
66
+ TParentRoute,
67
+ TCustomId,
68
+ TPath,
69
+ TSearchSchema,
70
+ TFullSearchSchema,
71
+ TParams,
72
+ TAllParams,
73
+ TRouteMeta,
74
+ TAllMeta
75
+ > &
76
+ NoInfer<UpdatableRouteOptions<TFullSearchSchema, TAllParams, TAllMeta>>
77
+
78
+ export type ParamsFallback<
79
+ TPath extends string,
80
+ TParams,
81
+ > = unknown extends TParams ? Record<ParsePathParams<TPath>, string> : TParams
82
+
83
+ type Prefix<T extends string, U extends string> = U extends `${T}${infer _}`
84
+ ? U
85
+ : never
86
+
87
+ export type BaseRouteOptions<
88
+ TParentRoute extends AnyRoute = AnyRoute,
89
+ TCustomId extends string = string,
90
+ TPath extends string = string,
91
+ TSearchSchema extends Record<string, any> = {},
92
+ TFullSearchSchema extends Record<string, any> = TSearchSchema,
93
+ TParams extends AnyPathParams = {},
94
+ TAllParams = ParamsFallback<TPath, TParams>,
95
+ TRouteMeta extends RouteMeta = RouteMeta,
96
+ TAllContext extends Record<string, any> = AnyContext,
97
+ > = RoutePathOptions<TCustomId, TPath> & {
98
+ getParentRoute: () => TParentRoute
99
+ validateSearch?: SearchSchemaValidator<TSearchSchema>
100
+ } & (keyof PickRequired<RouteMeta> extends never
101
+ ? // This async function is called before a route is loaded.
102
+ // If an error is thrown here, the route's loader will not be called.
103
+ // If thrown during a navigation, the navigation will be cancelled and the error will be passed to the `onError` function.
104
+ // If thrown during a preload event, the error will be logged to the console.
105
+ {
106
+ beforeLoad?: BeforeLoadFn<
107
+ TFullSearchSchema,
108
+ TParentRoute,
109
+ TAllParams,
110
+ TRouteMeta
111
+ >
112
+ }
113
+ : {
114
+ beforeLoad: BeforeLoadFn<
115
+ TFullSearchSchema,
116
+ TParentRoute,
117
+ TAllParams,
118
+ TRouteMeta
119
+ >
120
+ }) & {
121
+ load?: RouteLoadFn<
122
+ TAllParams,
123
+ TFullSearchSchema,
124
+ NoInfer<TAllContext>,
125
+ NoInfer<TRouteMeta>
126
+ >
127
+ } & (
128
+ | {
129
+ // Both or none
130
+ parseParams?: (
131
+ rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,
132
+ ) => TParams extends Record<ParsePathParams<TPath>, any>
133
+ ? TParams
134
+ : 'parseParams must return an object'
135
+ stringifyParams?: (
136
+ params: NoInfer<ParamsFallback<TPath, TParams>>,
137
+ ) => Record<ParsePathParams<TPath>, string>
138
+ }
139
+ | {
140
+ stringifyParams?: never
141
+ parseParams?: never
142
+ }
143
+ )
144
+
145
+ type BeforeLoadFn<
146
+ TFullSearchSchema extends Record<string, any>,
147
+ TParentRoute extends AnyRoute,
148
+ TAllParams,
149
+ TRouteMeta,
150
+ > = (opts: {
151
+ search: TFullSearchSchema
152
+ abortController: AbortController
153
+ preload: boolean
154
+ params: TAllParams
155
+ meta: TParentRoute['types']['allMeta']
156
+ location: ParsedLocation
157
+ }) => Promise<TRouteMeta> | TRouteMeta | void
158
+
159
+ export type UpdatableRouteOptions<
160
+ TFullSearchSchema extends Record<string, any>,
161
+ TAllParams extends AnyPathParams,
162
+ TAllContext extends AnyContext,
163
+ > =
164
+ // MetaOptions &
165
+ {
166
+ // test?: (args: TAllContext) => void
167
+ // If true, this route will be matched as case-sensitive
168
+ caseSensitive?: boolean
169
+ // If true, this route will be forcefully wrapped in a suspense boundary
170
+ wrapInSuspense?: boolean
171
+ // The content to be rendered when the route is matched. If no component is provided, defaults to `<Outlet />`
172
+ component?: RouteComponent<TFullSearchSchema, TAllParams, TAllContext>
173
+ // The content to be rendered when the route encounters an error
174
+ errorComponent?: ErrorRouteComponent<
175
+ TFullSearchSchema,
176
+ TAllParams,
177
+ {}
178
+ // TAllContext // TODO: I have no idea why this breaks the universe,
179
+ // so we'll come back to it later.
180
+ > //
181
+ // If supported by your framework, the content to be rendered as the fallback content until the route is ready to render
182
+ pendingComponent?: PendingRouteComponent<
183
+ TFullSearchSchema,
184
+ TAllParams,
185
+ TAllContext
186
+ >
187
+ // Filter functions that can manipulate search params *before* they are passed to links and navigate
188
+ // calls that match this route.
189
+ preSearchFilters?: SearchFilter<TFullSearchSchema>[]
190
+ // Filter functions that can manipulate search params *after* they are passed to links and navigate
191
+ // calls that match this route.
192
+ postSearchFilters?: SearchFilter<TFullSearchSchema>[]
193
+ onError?: (err: any) => void
194
+ // These functions are called as route matches are loaded, stick around and leave the active
195
+ // matches
196
+ onEnter?: (match: AnyRouteMatch) => void
197
+ onTransition?: (match: AnyRouteMatch) => void
198
+ onLeave?: (match: AnyRouteMatch) => void
199
+ // Set this to true or false to specifically set whether or not this route should be preloaded. If unset, will
200
+ // default to router.options.reloadOnWindowFocus
201
+ reloadOnWindowFocus?: boolean
202
+ }
203
+
204
+ export type ParseParamsOption<TPath extends string, TParams> = ParseParamsFn<
205
+ TPath,
206
+ TParams
207
+ >
208
+
209
+ export type ParseParamsFn<TPath extends string, TParams> = (
210
+ rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>,
211
+ ) => TParams extends Record<ParsePathParams<TPath>, any>
212
+ ? TParams
213
+ : 'parseParams must return an object'
214
+
215
+ export type ParseParamsObj<TPath extends string, TParams> = {
216
+ parse?: ParseParamsFn<TPath, TParams>
217
+ }
218
+
219
+ // The parse type here allows a zod schema to be passed directly to the validator
220
+ export type SearchSchemaValidator<TReturn> =
221
+ | SearchSchemaValidatorObj<TReturn>
222
+ | SearchSchemaValidatorFn<TReturn>
223
+
224
+ export type SearchSchemaValidatorObj<TReturn> = {
225
+ parse?: SearchSchemaValidatorFn<TReturn>
226
+ }
227
+
228
+ export type SearchSchemaValidatorFn<TReturn> = (
229
+ searchObj: Record<string, unknown>,
230
+ ) => TReturn
231
+
232
+ export type DefinedPathParamWarning =
233
+ 'Path params cannot be redefined by child routes!'
234
+
235
+ export type ParentParams<TParentParams> = AnyPathParams extends TParentParams
236
+ ? {}
237
+ : {
238
+ [Key in keyof TParentParams]?: DefinedPathParamWarning
239
+ }
240
+
241
+ export type RouteLoadFn<
242
+ TAllParams = {},
243
+ TFullSearchSchema extends Record<string, any> = {},
244
+ TAllContext extends Record<string, any> = AnyContext,
245
+ TRouteMeta extends Record<string, any> = AnyContext,
246
+ > = (
247
+ match: LoadFnContext<
248
+ TAllParams,
249
+ TFullSearchSchema,
250
+ TAllContext,
251
+ TRouteMeta
252
+ > & {
253
+ parentMatchPromise?: Promise<void>
254
+ },
255
+ ) => any
256
+
257
+ export interface LoadFnContext<
258
+ TAllParams = {},
259
+ TFullSearchSchema extends Record<string, any> = {},
260
+ TAllContext extends Record<string, any> = AnyContext,
261
+ TRouteMeta extends Record<string, any> = AnyContext,
262
+ > {
263
+ abortController: AbortController
264
+ preload: boolean
265
+ params: TAllParams
266
+ search: TFullSearchSchema
267
+ meta: Expand<Assign<TAllContext, TRouteMeta>>
268
+ }
269
+
270
+ export type SearchFilter<T, U = T> = (prev: T) => U
271
+
272
+ export type ResolveId<
273
+ TParentRoute,
274
+ TCustomId extends string,
275
+ TPath extends string,
276
+ > = TParentRoute extends { id: infer TParentId extends string }
277
+ ? RoutePrefix<TParentId, string extends TCustomId ? TPath : TCustomId>
278
+ : RootRouteId
279
+
280
+ export type InferFullSearchSchema<TRoute> = TRoute extends {
281
+ types: {
282
+ fullSearchSchema: infer TFullSearchSchema
283
+ }
284
+ }
285
+ ? TFullSearchSchema
286
+ : {}
287
+
288
+ export type ResolveFullSearchSchema<TParentRoute, TSearchSchema> = Expand<
289
+ Assign<InferFullSearchSchema<TParentRoute>, TSearchSchema>
290
+ >
291
+
292
+ export interface AnyRoute
293
+ extends Route<
294
+ any,
295
+ any,
296
+ any,
297
+ any,
298
+ any,
299
+ any,
300
+ any,
301
+ any,
302
+ any,
303
+ any,
304
+ any,
305
+ any,
306
+ any,
307
+ any
308
+ > {}
309
+
310
+ export type MergeFromFromParent<T, U> = IsAny<T, U, T & U>
311
+
312
+ export type StreamedPromise<T> = {
313
+ promise: Promise<T>
314
+ status: 'resolved' | 'pending'
315
+ data: T
316
+ resolve: (value: T) => void
317
+ }
318
+
319
+ export type ResolveAllParams<
320
+ TParentRoute extends AnyRoute,
321
+ TParams extends AnyPathParams,
322
+ > = Record<never, string> extends TParentRoute['types']['allParams']
323
+ ? TParams
324
+ : Expand<
325
+ UnionToIntersection<TParentRoute['types']['allParams'] & TParams> & {}
326
+ >
327
+
328
+ export type RouteConstraints = {
329
+ TParentRoute: AnyRoute
330
+ TPath: string
331
+ TFullPath: string
332
+ TCustomId: string
333
+ TId: string
334
+ TSearchSchema: AnySearchSchema
335
+ TFullSearchSchema: AnySearchSchema
336
+ TParams: Record<string, any>
337
+ TAllParams: Record<string, any>
338
+ TParentContext: AnyContext
339
+ TRouteMeta: RouteMeta
340
+ TAllContext: AnyContext
341
+ TRouterMeta: AnyContext
342
+ TChildren: unknown
343
+ TRouteTree: AnyRoute
344
+ }
345
+
346
+ export class Route<
347
+ TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute,
348
+ TPath extends RouteConstraints['TPath'] = '/',
349
+ TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<
350
+ TParentRoute,
351
+ TPath
352
+ >,
353
+ TCustomId extends RouteConstraints['TCustomId'] = string,
354
+ TId extends RouteConstraints['TId'] = ResolveId<
355
+ TParentRoute,
356
+ TCustomId,
357
+ TPath
358
+ >,
359
+ TSearchSchema extends RouteConstraints['TSearchSchema'] = {},
360
+ TFullSearchSchema extends RouteConstraints['TFullSearchSchema'] = ResolveFullSearchSchema<
361
+ TParentRoute,
362
+ TSearchSchema
363
+ >,
364
+ TParams extends RouteConstraints['TParams'] = Expand<
365
+ Record<ParsePathParams<TPath>, string>
366
+ >,
367
+ TAllParams extends RouteConstraints['TAllParams'] = ResolveAllParams<
368
+ TParentRoute,
369
+ TParams
370
+ >,
371
+ TRouteMeta extends RouteConstraints['TRouteMeta'] = RouteMeta,
372
+ TAllMeta extends Expand<
373
+ Assign<IsAny<TParentRoute['types']['allMeta'], {}>, TRouteMeta>
374
+ > = Expand<Assign<IsAny<TParentRoute['types']['allMeta'], {}>, TRouteMeta>>,
375
+ TRouterMeta extends RouteConstraints['TRouterMeta'] = AnyContext,
376
+ TChildren extends RouteConstraints['TChildren'] = unknown,
377
+ TRouteTree extends RouteConstraints['TRouteTree'] = AnyRoute,
378
+ > {
379
+ isRoot: TParentRoute extends Route<any> ? true : false
380
+ options: RouteOptions<
381
+ TParentRoute,
382
+ TCustomId,
383
+ TPath,
384
+ TSearchSchema,
385
+ TFullSearchSchema,
386
+ TParams,
387
+ TAllParams,
388
+ TRouteMeta,
389
+ TAllMeta
390
+ >
391
+
392
+ test!: Expand<Assign<IsAny<TParentRoute['types']['allMeta'], {}>, TRouteMeta>>
393
+
394
+ // Set up in this.init()
395
+ parentRoute!: TParentRoute
396
+ id!: TId
397
+ // customId!: TCustomId
398
+ path!: TPath
399
+ fullPath!: TFullPath
400
+ to!: TrimPathRight<TFullPath>
401
+
402
+ // Optional
403
+ children?: TChildren
404
+ originalIndex?: number
405
+ router?: AnyRouter
406
+ rank!: number
407
+
408
+ constructor(
409
+ options: RouteOptions<
410
+ TParentRoute,
411
+ TCustomId,
412
+ TPath,
413
+ TSearchSchema,
414
+ TFullSearchSchema,
415
+ TParams,
416
+ TAllParams,
417
+ TRouteMeta,
418
+ TAllMeta
419
+ >,
420
+ ) {
421
+ this.options = (options as any) || {}
422
+ this.isRoot = !options?.getParentRoute as any
423
+ Route.__onInit(this)
424
+ }
425
+
426
+ types!: {
427
+ parentRoute: TParentRoute
428
+ path: TPath
429
+ to: TrimPathRight<TFullPath>
430
+ fullPath: TFullPath
431
+ customId: TCustomId
432
+ id: TId
433
+ searchSchema: TSearchSchema
434
+ fullSearchSchema: TFullSearchSchema
435
+ params: TParams
436
+ allParams: TAllParams
437
+ routeMeta: TRouteMeta
438
+ allMeta: TAllMeta
439
+ children: TChildren
440
+ routeTree: TRouteTree
441
+ routerMeta: TRouterMeta
442
+ }
443
+
444
+ init = (opts: { originalIndex: number }) => {
445
+ this.originalIndex = opts.originalIndex
446
+
447
+ const options = this.options as RouteOptions<
448
+ TParentRoute,
449
+ TCustomId,
450
+ TPath,
451
+ TSearchSchema,
452
+ TFullSearchSchema,
453
+ TParams,
454
+ TAllParams,
455
+ TRouteMeta,
456
+ TAllMeta
457
+ > &
458
+ RoutePathOptionsIntersection<TCustomId, TPath>
459
+
460
+ const isRoot = !options?.path && !options?.id
461
+
462
+ this.parentRoute = this.options?.getParentRoute?.()
463
+
464
+ if (isRoot) {
465
+ this.path = rootRouteId as TPath
466
+ } else {
467
+ invariant(
468
+ this.parentRoute,
469
+ `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
470
+ )
471
+ }
472
+
473
+ let path: undefined | string = isRoot ? rootRouteId : options.path
474
+
475
+ // If the path is anything other than an index path, trim it up
476
+ if (path && path !== '/') {
477
+ path = trimPath(path)
478
+ }
479
+
480
+ const customId = options?.id || path
481
+
482
+ // Strip the parentId prefix from the first level of children
483
+ let id = isRoot
484
+ ? rootRouteId
485
+ : joinPaths([
486
+ (this.parentRoute.id as any) === rootRouteId
487
+ ? ''
488
+ : this.parentRoute.id,
489
+ customId,
490
+ ])
491
+
492
+ if (path === rootRouteId) {
493
+ path = '/'
494
+ }
495
+
496
+ if (id !== rootRouteId) {
497
+ id = joinPaths(['/', id])
498
+ }
499
+
500
+ const fullPath =
501
+ id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path])
502
+
503
+ this.path = path as TPath
504
+ this.id = id as TId
505
+ // this.customId = customId as TCustomId
506
+ this.fullPath = fullPath as TFullPath
507
+ this.to = fullPath as TrimPathRight<TFullPath>
508
+ }
509
+
510
+ addChildren = <TNewChildren extends AnyRoute[]>(
511
+ children: TNewChildren,
512
+ ): Route<
513
+ TParentRoute,
514
+ TPath,
515
+ TFullPath,
516
+ TCustomId,
517
+ TId,
518
+ TSearchSchema,
519
+ TFullSearchSchema,
520
+ TParams,
521
+ TAllParams,
522
+ TRouteMeta,
523
+ TAllMeta,
524
+ TRouterMeta,
525
+ TNewChildren,
526
+ TRouteTree
527
+ > => {
528
+ this.children = children as any
529
+ return this as any
530
+ }
531
+
532
+ update = (
533
+ options: UpdatableRouteOptions<
534
+ TFullSearchSchema,
535
+ TAllParams,
536
+ Expand<Assign<IsAny<TParentRoute['types']['allMeta'], {}>, TRouteMeta>>
537
+ >,
538
+ ) => {
539
+ Object.assign(this.options, options)
540
+ return this
541
+ }
542
+
543
+ static __onInit = (route: any) => {
544
+ // This is a dummy static method that should get
545
+ // replaced by a framework specific implementation if necessary
546
+ }
547
+
548
+ useMatch = <TSelected = TAllMeta>(opts?: {
549
+ select?: (search: TAllMeta) => TSelected
550
+ }): TSelected => {
551
+ return useMatch({ ...opts, from: this.id }) as any
552
+ }
553
+ useRouteMeta = <TSelected = TAllMeta>(opts?: {
554
+ select?: (search: TAllMeta) => TSelected
555
+ }): TSelected => {
556
+ return useMatch({
557
+ ...opts,
558
+ from: this.id,
559
+ select: (d: any) => (opts?.select ? opts.select(d.meta) : d.meta),
560
+ } as any)
561
+ }
562
+ useSearch = <TSelected = TFullSearchSchema>(opts?: {
563
+ select?: (search: TFullSearchSchema) => TSelected
564
+ }): TSelected => {
565
+ return useSearch({ ...opts, from: this.id } as any)
566
+ }
567
+ useParams = <TSelected = TAllParams>(opts?: {
568
+ select?: (search: TAllParams) => TSelected
569
+ }): TSelected => {
570
+ return useParams({ ...opts, from: this.id } as any)
571
+ }
572
+ }
573
+
574
+ export type AnyRootRoute = RootRoute<any, any, any>
575
+
576
+ export class RouterMeta<TRouterMeta extends {}> {
577
+ constructor() {}
578
+
579
+ createRootRoute = <
580
+ TSearchSchema extends Record<string, any> = {},
581
+ TRouteMeta extends RouteMeta = RouteMeta,
582
+ >(
583
+ options?: Omit<
584
+ RouteOptions<
585
+ AnyRoute, // TParentRoute
586
+ RootRouteId, // TCustomId
587
+ '', // TPath
588
+ TSearchSchema, // TSearchSchema
589
+ TSearchSchema, // TFullSearchSchema
590
+ {}, // TParams
591
+ {}, // TAllParams
592
+ TRouteMeta, // TRouteMeta
593
+ Assign<TRouterMeta, TRouteMeta> // TAllContext
594
+ >,
595
+ | 'path'
596
+ | 'id'
597
+ | 'getParentRoute'
598
+ | 'caseSensitive'
599
+ | 'parseParams'
600
+ | 'stringifyParams'
601
+ >,
602
+ ): RootRoute<TSearchSchema, TRouteMeta, TRouterMeta> => {
603
+ return new RootRoute(options) as any
604
+ }
605
+ }
606
+
607
+ export class RootRoute<
608
+ TSearchSchema extends Record<string, any> = {},
609
+ TRouteMeta extends RouteMeta = RouteMeta,
610
+ TRouterMeta extends {} = {},
611
+ > extends Route<
612
+ any, // TParentRoute
613
+ '/', // TPath
614
+ '/', // TFullPath
615
+ string, // TCustomId
616
+ RootRouteId, // TId
617
+ TSearchSchema, // TSearchSchema
618
+ TSearchSchema, // TFullSearchSchema
619
+ {}, // TParams
620
+ {}, // TAllParams
621
+ TRouteMeta, // TRouteMeta
622
+ Expand<Assign<TRouterMeta, TRouteMeta>>, // TAllContext
623
+ TRouterMeta, // TRouterMeta
624
+ any, // TChildren
625
+ any // TRouteTree
626
+ > {
627
+ constructor(
628
+ options?: Omit<
629
+ RouteOptions<
630
+ AnyRoute, // TParentRoute
631
+ RootRouteId, // TCustomId
632
+ '', // TPath
633
+ TSearchSchema, // TSearchSchema
634
+ TSearchSchema, // TFullSearchSchema
635
+ {}, // TParams
636
+ {}, // TAllParams
637
+ TRouteMeta, // TRouteMeta
638
+ Assign<TRouterMeta, TRouteMeta> // TAllContext
639
+ >,
640
+ | 'path'
641
+ | 'id'
642
+ | 'getParentRoute'
643
+ | 'caseSensitive'
644
+ | 'parseParams'
645
+ | 'stringifyParams'
646
+ >,
647
+ ) {
648
+ super(options as any)
649
+ }
650
+ }
651
+
652
+ export type ResolveFullPath<
653
+ TParentRoute extends AnyRoute,
654
+ TPath extends string,
655
+ TPrefixed = RoutePrefix<TParentRoute['fullPath'], TPath>,
656
+ > = TPrefixed extends RootRouteId ? '/' : TPrefixed
657
+
658
+ type RoutePrefix<
659
+ TPrefix extends string,
660
+ TPath extends string,
661
+ > = string extends TPath
662
+ ? RootRouteId
663
+ : TPath extends string
664
+ ? TPrefix extends RootRouteId
665
+ ? TPath extends '/'
666
+ ? '/'
667
+ : `/${TrimPath<TPath>}`
668
+ : `${TPrefix}/${TPath}` extends '/'
669
+ ? '/'
670
+ : `/${TrimPathLeft<`${TrimPathRight<TPrefix>}/${TrimPath<TPath>}`>}`
671
+ : never
672
+
673
+ export type TrimPath<T extends string> = '' extends T
674
+ ? ''
675
+ : TrimPathRight<TrimPathLeft<T>>
676
+
677
+ export type TrimPathLeft<T extends string> =
678
+ T extends `${RootRouteId}/${infer U}`
679
+ ? TrimPathLeft<U>
680
+ : T extends `/${infer U}`
681
+ ? TrimPathLeft<U>
682
+ : T
683
+ export type TrimPathRight<T extends string> = T extends '/'
684
+ ? '/'
685
+ : T extends `${infer U}/`
686
+ ? TrimPathRight<U>
687
+ : T
688
+
689
+ export type RouteMask<TRouteTree extends AnyRoute> = {
690
+ routeTree: TRouteTree
691
+ from: RoutePaths<TRouteTree>
692
+ to?: any
693
+ params?: any
694
+ search?: any
695
+ hash?: any
696
+ state?: any
697
+ unmaskOnReload?: boolean
698
+ }
699
+
700
+ export function createRouteMask<
701
+ TRouteTree extends AnyRoute,
702
+ TFrom extends RoutePaths<TRouteTree>,
703
+ TTo extends string,
704
+ >(
705
+ opts: {
706
+ routeTree: TRouteTree
707
+ } & ToSubOptions<TRouteTree, TFrom, TTo>,
708
+ ): RouteMask<TRouteTree> {
709
+ return opts as any
710
+ }