@tanstack/react-router 0.0.1-beta.26 → 0.0.1-beta.261

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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/build/cjs/CatchBoundary.js +128 -0
  3. package/build/cjs/CatchBoundary.js.map +1 -0
  4. package/build/cjs/Matches.js +244 -0
  5. package/build/cjs/Matches.js.map +1 -0
  6. package/build/cjs/RouterProvider.js +166 -0
  7. package/build/cjs/RouterProvider.js.map +1 -0
  8. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +2 -22
  9. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
  10. package/build/cjs/awaited.js +43 -0
  11. package/build/cjs/awaited.js.map +1 -0
  12. package/build/cjs/defer.js +37 -0
  13. package/build/cjs/defer.js.map +1 -0
  14. package/build/cjs/fileRoute.js +27 -0
  15. package/build/cjs/fileRoute.js.map +1 -0
  16. package/build/cjs/index.js +125 -0
  17. package/build/cjs/index.js.map +1 -0
  18. package/build/cjs/lazyRouteComponent.js +54 -0
  19. package/build/cjs/lazyRouteComponent.js.map +1 -0
  20. package/build/cjs/link.js +149 -0
  21. package/build/cjs/link.js.map +1 -0
  22. package/build/cjs/path.js +214 -0
  23. package/build/cjs/path.js.map +1 -0
  24. package/build/cjs/qss.js +63 -0
  25. package/build/cjs/qss.js.map +1 -0
  26. package/build/cjs/redirects.js +28 -0
  27. package/build/cjs/redirects.js.map +1 -0
  28. package/build/cjs/route.js +140 -0
  29. package/build/cjs/route.js.map +1 -0
  30. package/build/cjs/router.js +1144 -0
  31. package/build/cjs/router.js.map +1 -0
  32. package/build/cjs/scroll-restoration.js +202 -0
  33. package/build/cjs/scroll-restoration.js.map +1 -0
  34. package/build/cjs/searchParams.js +81 -0
  35. package/build/cjs/searchParams.js.map +1 -0
  36. package/build/cjs/useBlocker.js +55 -0
  37. package/build/cjs/useBlocker.js.map +1 -0
  38. package/build/cjs/useNavigate.js +75 -0
  39. package/build/cjs/useNavigate.js.map +1 -0
  40. package/build/cjs/useParams.js +26 -0
  41. package/build/cjs/useParams.js.map +1 -0
  42. package/build/cjs/useSearch.js +25 -0
  43. package/build/cjs/useSearch.js.map +1 -0
  44. package/build/cjs/utils.js +239 -0
  45. package/build/cjs/utils.js.map +1 -0
  46. package/build/esm/index.js +2214 -2529
  47. package/build/esm/index.js.map +1 -1
  48. package/build/stats-html.html +3498 -2694
  49. package/build/stats-react.json +1210 -44
  50. package/build/types/CatchBoundary.d.ts +36 -0
  51. package/build/types/Matches.d.ts +57 -0
  52. package/build/types/RouterProvider.d.ts +36 -0
  53. package/build/types/awaited.d.ts +9 -0
  54. package/build/types/defer.d.ts +19 -0
  55. package/build/types/fileRoute.d.ts +34 -0
  56. package/build/types/history.d.ts +7 -0
  57. package/build/types/index.d.ts +27 -114
  58. package/build/types/injectHtml.d.ts +0 -0
  59. package/build/types/lazyRouteComponent.d.ts +2 -0
  60. package/build/types/link.d.ts +105 -0
  61. package/build/types/location.d.ts +14 -0
  62. package/build/types/path.d.ts +17 -0
  63. package/build/types/qss.d.ts +2 -0
  64. package/build/types/redirects.d.ts +11 -0
  65. package/build/types/route.d.ts +279 -0
  66. package/build/types/routeInfo.d.ts +22 -0
  67. package/build/types/router.d.ts +183 -0
  68. package/build/types/scroll-restoration.d.ts +18 -0
  69. package/build/types/searchParams.d.ts +7 -0
  70. package/build/types/useBlocker.d.ts +8 -0
  71. package/build/types/useNavigate.d.ts +20 -0
  72. package/build/types/useParams.d.ts +7 -0
  73. package/build/types/useSearch.d.ts +7 -0
  74. package/build/types/utils.d.ts +66 -0
  75. package/build/umd/index.development.js +2794 -2481
  76. package/build/umd/index.development.js.map +1 -1
  77. package/build/umd/index.production.js +4 -4
  78. package/build/umd/index.production.js.map +1 -1
  79. package/package.json +11 -10
  80. package/src/CatchBoundary.tsx +101 -0
  81. package/src/Matches.tsx +428 -0
  82. package/src/RouterProvider.tsx +254 -0
  83. package/src/awaited.tsx +40 -0
  84. package/src/defer.ts +55 -0
  85. package/src/fileRoute.ts +154 -0
  86. package/src/history.ts +8 -0
  87. package/src/index.tsx +28 -714
  88. package/src/injectHtml.ts +28 -0
  89. package/src/lazyRouteComponent.tsx +33 -0
  90. package/src/link.tsx +509 -0
  91. package/src/location.ts +15 -0
  92. package/src/path.ts +261 -0
  93. package/src/qss.ts +53 -0
  94. package/src/redirects.ts +39 -0
  95. package/src/route.ts +915 -0
  96. package/src/routeInfo.ts +68 -0
  97. package/src/router.ts +1750 -0
  98. package/src/scroll-restoration.tsx +230 -0
  99. package/src/searchParams.ts +79 -0
  100. package/src/useBlocker.tsx +26 -0
  101. package/src/useNavigate.tsx +110 -0
  102. package/src/useParams.tsx +25 -0
  103. package/src/useSearch.tsx +25 -0
  104. package/src/utils.ts +350 -0
  105. package/build/cjs/react-router/src/index.js +0 -473
  106. package/build/cjs/react-router/src/index.js.map +0 -1
  107. package/build/cjs/router-core/build/esm/index.js +0 -2530
  108. package/build/cjs/router-core/build/esm/index.js.map +0 -1
@@ -0,0 +1,28 @@
1
+ // export function useInjectHtml() {
2
+ // const { } = useRouter()
3
+ // return React.useCallback(
4
+ // (html: string | (() => Promise<string> | string)) => {
5
+ // router.injectHtml(html)
6
+ // },
7
+ // [],
8
+ // )
9
+ // }
10
+ // export function useDehydrate() {
11
+ // const { } = useRouter()
12
+ // return React.useCallback(function dehydrate<T>(
13
+ // key: any,
14
+ // data: T | (() => Promise<T> | T),
15
+ // ) {
16
+ // return router.dehydrateData(key, data)
17
+ // },
18
+ // [])
19
+ // }
20
+ // export function useHydrate() {
21
+ // const { } = useRouter()
22
+ // return function hydrate<T = unknown>(key: any) {
23
+ // return router.hydrateData(key) as T
24
+ // }
25
+ // }
26
+ // This is the messiest thing ever... I'm either seriously tired (likely) or
27
+ // there has to be a better way to reset error boundaries when the
28
+ // router's location key changes.
@@ -0,0 +1,33 @@
1
+ import * as React from 'react'
2
+ import { AsyncRouteComponent } from './route'
3
+
4
+ export function lazyRouteComponent<
5
+ T extends Record<string, any>,
6
+ TKey extends keyof T = 'default',
7
+ >(
8
+ importer: () => Promise<T>,
9
+ exportName?: TKey,
10
+ ): T[TKey] extends (props: infer TProps) => any
11
+ ? AsyncRouteComponent<TProps>
12
+ : never {
13
+ let loadPromise: Promise<any>
14
+
15
+ const load = () => {
16
+ if (!loadPromise) {
17
+ loadPromise = importer()
18
+ }
19
+
20
+ return loadPromise
21
+ }
22
+
23
+ const lazyComp = React.lazy(async () => {
24
+ const moduleExports = await load()
25
+ const comp = moduleExports[exportName ?? 'default']
26
+ return {
27
+ default: comp,
28
+ }
29
+ })
30
+ ;(lazyComp as any).preload = load
31
+
32
+ return lazyComp as any
33
+ }
package/src/link.tsx ADDED
@@ -0,0 +1,509 @@
1
+ import * as React from 'react'
2
+ import { useMatch } from './Matches'
3
+ import { useRouter } from './RouterProvider'
4
+ import { Trim } from './fileRoute'
5
+ import { LocationState, ParsedLocation } from './location'
6
+ import { AnyRoute, ReactNode } from './route'
7
+ import {
8
+ AllParams,
9
+ FullSearchSchema,
10
+ RouteByPath,
11
+ RouteIds,
12
+ RoutePaths,
13
+ } from './routeInfo'
14
+ import { RegisteredRouter } from './router'
15
+ import { MakeLinkOptions, MakeLinkPropsOptions } from './useNavigate'
16
+ import {
17
+ Expand,
18
+ NoInfer,
19
+ NonNullableUpdater,
20
+ PickRequired,
21
+ UnionToIntersection,
22
+ Updater,
23
+ functionalUpdate,
24
+ } from './utils'
25
+
26
+ export type LinkInfo =
27
+ | {
28
+ type: 'external'
29
+ href: string
30
+ }
31
+ | {
32
+ type: 'internal'
33
+ next: ParsedLocation
34
+ handleFocus: (e: any) => void
35
+ handleClick: (e: any) => void
36
+ handleEnter: (e: any) => void
37
+ handleLeave: (e: any) => void
38
+ handleTouchStart: (e: any) => void
39
+ isActive: boolean
40
+ disabled?: boolean
41
+ }
42
+
43
+ export type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
44
+ ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>
45
+ : T extends `${infer L}//`
46
+ ? `${CleanPath<L>}/`
47
+ : T extends `//${infer L}`
48
+ ? `/${CleanPath<L>}`
49
+ : T
50
+
51
+ export type Split<S, TIncludeTrailingSlash = true> = S extends unknown
52
+ ? string extends S
53
+ ? string[]
54
+ : S extends string
55
+ ? CleanPath<S> extends ''
56
+ ? []
57
+ : TIncludeTrailingSlash extends true
58
+ ? CleanPath<S> extends `${infer T}/`
59
+ ? [...Split<T>, '/']
60
+ : CleanPath<S> extends `/${infer U}`
61
+ ? Split<U>
62
+ : CleanPath<S> extends `${infer T}/${infer U}`
63
+ ? [...Split<T>, ...Split<U>]
64
+ : [S]
65
+ : CleanPath<S> extends `${infer T}/${infer U}`
66
+ ? [...Split<T>, ...Split<U>]
67
+ : S extends string
68
+ ? [S]
69
+ : never
70
+ : never
71
+ : never
72
+
73
+ export type ParsePathParams<T extends string> = keyof {
74
+ [K in Trim<Split<T>[number], '_'> as K extends `$${infer L}` ? L : never]: K
75
+ }
76
+
77
+ export type Join<T, Delimiter extends string = '/'> = T extends []
78
+ ? ''
79
+ : T extends [infer L extends string]
80
+ ? L
81
+ : T extends [infer L extends string, ...infer Tail extends [...string[]]]
82
+ ? CleanPath<`${L}${Delimiter}${Join<Tail>}`>
83
+ : never
84
+
85
+ export type Last<T extends any[]> = T extends [...infer _, infer L] ? L : never
86
+
87
+ export type RelativeToPathAutoComplete<
88
+ AllPaths extends string,
89
+ TFrom extends string,
90
+ TTo extends string,
91
+ SplitPaths extends string[] = Split<AllPaths, false>,
92
+ > = TTo extends `..${infer _}`
93
+ ? SplitPaths extends [
94
+ ...Split<ResolveRelativePath<TFrom, TTo>, false>,
95
+ ...infer TToRest,
96
+ ]
97
+ ? `${CleanPath<
98
+ Join<
99
+ [
100
+ ...Split<TTo, false>,
101
+ ...(
102
+ | TToRest
103
+ | (Split<
104
+ ResolveRelativePath<TFrom, TTo>,
105
+ false
106
+ >['length'] extends 1
107
+ ? never
108
+ : ['../'])
109
+ ),
110
+ ]
111
+ >
112
+ >}`
113
+ : never
114
+ : TTo extends `./${infer RestTTo}`
115
+ ? SplitPaths extends [
116
+ ...Split<TFrom, false>,
117
+ ...Split<RestTTo, false>,
118
+ ...infer RestPath,
119
+ ]
120
+ ? `${TTo}${Join<RestPath>}`
121
+ : never
122
+ :
123
+ | (TFrom extends `/`
124
+ ? never
125
+ : SplitPaths extends [...Split<TFrom, false>, ...infer RestPath]
126
+ ? Join<RestPath> extends { length: 0 }
127
+ ? never
128
+ : './'
129
+ : never)
130
+ | (TFrom extends `/` ? never : '../')
131
+ | AllPaths
132
+
133
+ export type NavigateOptions<
134
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
135
+ TFrom extends RoutePaths<TRouteTree> = '/',
136
+ TTo extends string = '',
137
+ TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
138
+ TMaskTo extends string = '',
139
+ > = ToOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
140
+ // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
141
+ replace?: boolean
142
+ resetScroll?: boolean
143
+ // If set to `true`, the link's underlying navigate() call will be wrapped in a `React.startTransition` call. Defaults to `true`.
144
+ startTransition?: boolean
145
+ }
146
+
147
+ export type ToOptions<
148
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
149
+ TFrom extends RoutePaths<TRouteTree> = '/',
150
+ TTo extends string = '',
151
+ TMaskFrom extends RoutePaths<TRouteTree> = '/',
152
+ TMaskTo extends string = '',
153
+ > = ToSubOptions<TRouteTree, TFrom, TTo> & {
154
+ mask?: ToMaskOptions<TRouteTree, TMaskFrom, TMaskTo>
155
+ }
156
+
157
+ export type ToMaskOptions<
158
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
159
+ TMaskFrom extends RoutePaths<TRouteTree> = '/',
160
+ TMaskTo extends string = '',
161
+ > = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {
162
+ unmaskOnReload?: boolean
163
+ }
164
+
165
+ export type ToSubOptions<
166
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
167
+ TFrom extends RoutePaths<TRouteTree> = '/',
168
+ TTo extends string = '',
169
+ TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
170
+ > = {
171
+ to?: ToPathOption<TRouteTree, TFrom, TTo>
172
+ // The new has string or a function to update it
173
+ hash?: true | Updater<string>
174
+ // State to pass to the history stack
175
+ state?: true | NonNullableUpdater<LocationState>
176
+ // The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required
177
+ from?: TFrom
178
+ // // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
179
+ // fromCurrent?: boolean
180
+ } & CheckPath<TRouteTree, NoInfer<TResolved>, {}> &
181
+ SearchParamOptions<TRouteTree, TFrom, TTo, TResolved> &
182
+ PathParamOptions<TRouteTree, TFrom, TResolved>
183
+
184
+ export type SearchParamOptions<
185
+ TRouteTree extends AnyRoute,
186
+ TFrom,
187
+ TTo,
188
+ TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
189
+ TFromSearchEnsured = '/' extends TFrom
190
+ ? FullSearchSchema<TRouteTree>
191
+ : Expand<
192
+ UnionToIntersection<
193
+ PickRequired<
194
+ RouteByPath<TRouteTree, TFrom>['types']['fullSearchSchema']
195
+ >
196
+ >
197
+ >,
198
+ TFromSearchOptional = Omit<AllParams<TRouteTree>, keyof TFromSearchEnsured>,
199
+ TFromSearch = Expand<TFromSearchEnsured & TFromSearchOptional>,
200
+ TToSearch = '' extends TTo
201
+ ? FullSearchSchema<TRouteTree>
202
+ : Expand<RouteByPath<TRouteTree, TResolved>['types']['fullSearchSchema']>,
203
+ > = keyof PickRequired<TToSearch> extends never
204
+ ? {
205
+ search?: true | SearchReducer<TFromSearch, TToSearch>
206
+ }
207
+ : {
208
+ search: TFromSearchEnsured extends PickRequired<TToSearch>
209
+ ? true | SearchReducer<TFromSearch, TToSearch>
210
+ : SearchReducer<TFromSearch, TToSearch>
211
+ }
212
+
213
+ type SearchReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
214
+
215
+ export type PathParamOptions<
216
+ TRouteTree extends AnyRoute,
217
+ TFrom,
218
+ TTo,
219
+ TFromParamsEnsured = Expand<
220
+ UnionToIntersection<
221
+ PickRequired<RouteByPath<TRouteTree, TFrom>['types']['allParams']>
222
+ >
223
+ >,
224
+ TFromParamsOptional = Omit<AllParams<TRouteTree>, keyof TFromParamsEnsured>,
225
+ TFromParams = Expand<TFromParamsOptional & TFromParamsEnsured>,
226
+ TToParams = Expand<RouteByPath<TRouteTree, TTo>['types']['allParams']>,
227
+ > = keyof PickRequired<TToParams> extends never
228
+ ? {
229
+ params?: true | ParamsReducer<TFromParams, TToParams>
230
+ }
231
+ : {
232
+ params: TFromParamsEnsured extends PickRequired<TToParams>
233
+ ? true | ParamsReducer<TFromParams, TToParams>
234
+ : ParamsReducer<TFromParams, TToParams>
235
+ }
236
+
237
+ type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
238
+
239
+ export type ToPathOption<
240
+ TRouteTree extends AnyRoute = AnyRoute,
241
+ TFrom extends RoutePaths<TRouteTree> = '/',
242
+ TTo extends string = '',
243
+ > =
244
+ | TTo
245
+ | RelativeToPathAutoComplete<
246
+ RoutePaths<TRouteTree>,
247
+ NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
248
+ NoInfer<TTo> & string
249
+ >
250
+
251
+ export type ToIdOption<
252
+ TRouteTree extends AnyRoute = AnyRoute,
253
+ TFrom extends RoutePaths<TRouteTree> = '/',
254
+ TTo extends string = '',
255
+ > =
256
+ | TTo
257
+ | RelativeToPathAutoComplete<
258
+ RouteIds<TRouteTree>,
259
+ NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
260
+ NoInfer<TTo> & string
261
+ >
262
+
263
+ export interface ActiveOptions {
264
+ exact?: boolean
265
+ includeHash?: boolean
266
+ includeSearch?: boolean
267
+ }
268
+
269
+ export type LinkOptions<
270
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
271
+ TFrom extends RoutePaths<TRouteTree> = '/',
272
+ TTo extends string = '',
273
+ TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
274
+ TMaskTo extends string = '',
275
+ > = NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
276
+ // The standard anchor tag target attribute
277
+ target?: HTMLAnchorElement['target']
278
+ // Defaults to `{ exact: false, includeHash: false }`
279
+ activeOptions?: ActiveOptions
280
+ // If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
281
+ preload?: false | 'intent'
282
+ // Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
283
+ preloadDelay?: number
284
+ // If true, will render the link without the href attribute
285
+ disabled?: boolean
286
+ }
287
+
288
+ export type CheckRelativePath<
289
+ TRouteTree extends AnyRoute,
290
+ TFrom,
291
+ TTo,
292
+ > = TTo extends string
293
+ ? TFrom extends string
294
+ ? ResolveRelativePath<TFrom, TTo> extends RoutePaths<TRouteTree>
295
+ ? {}
296
+ : {
297
+ Error: `${TFrom} + ${TTo} resolves to ${ResolveRelativePath<
298
+ TFrom,
299
+ TTo
300
+ >}, which is not a valid route path.`
301
+ 'Valid Route Paths': RoutePaths<TRouteTree>
302
+ }
303
+ : {}
304
+ : {}
305
+
306
+ export type CheckPath<TRouteTree extends AnyRoute, TPath, TPass> = Exclude<
307
+ TPath,
308
+ RoutePaths<TRouteTree>
309
+ > extends never
310
+ ? TPass
311
+ : CheckPathError<TRouteTree, Exclude<TPath, RoutePaths<TRouteTree>>>
312
+
313
+ export type CheckPathError<TRouteTree extends AnyRoute, TInvalids> = {
314
+ to: RoutePaths<TRouteTree>
315
+ }
316
+
317
+ export type CheckId<TRouteTree extends AnyRoute, TPath, TPass> = Exclude<
318
+ TPath,
319
+ RouteIds<TRouteTree>
320
+ > extends never
321
+ ? TPass
322
+ : CheckIdError<TRouteTree, Exclude<TPath, RouteIds<TRouteTree>>>
323
+
324
+ export type CheckIdError<TRouteTree extends AnyRoute, TInvalids> = {
325
+ Error: `${TInvalids extends string
326
+ ? TInvalids
327
+ : never} is not a valid route ID.`
328
+ 'Valid Route IDs': RouteIds<TRouteTree>
329
+ }
330
+
331
+ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
332
+ ? TTo extends string
333
+ ? TTo extends '.'
334
+ ? TFrom
335
+ : TTo extends `./`
336
+ ? Join<[TFrom, '/']>
337
+ : TTo extends `./${infer TRest}`
338
+ ? ResolveRelativePath<TFrom, TRest>
339
+ : TTo extends `/${infer TRest}`
340
+ ? TTo
341
+ : Split<TTo> extends ['..', ...infer ToRest]
342
+ ? Split<TFrom> extends [...infer FromRest, infer FromTail]
343
+ ? ToRest extends ['/']
344
+ ? Join<[...FromRest, '/']>
345
+ : ResolveRelativePath<Join<FromRest>, Join<ToRest>>
346
+ : never
347
+ : Split<TTo> extends ['.', ...infer ToRest]
348
+ ? ToRest extends ['/']
349
+ ? Join<[TFrom, '/']>
350
+ : ResolveRelativePath<TFrom, Join<ToRest>>
351
+ : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>
352
+ : never
353
+ : never
354
+
355
+ export function useLinkProps<
356
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
357
+ TFrom extends RoutePaths<TRouteTree> = '/',
358
+ TTo extends string = '',
359
+ TMaskFrom extends RoutePaths<TRouteTree> = '/',
360
+ TMaskTo extends string = '',
361
+ >(
362
+ options: MakeLinkPropsOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
363
+ ): React.AnchorHTMLAttributes<HTMLAnchorElement> {
364
+ const { buildLink } = useRouter()
365
+ const matchPathname = useMatch({
366
+ strict: false,
367
+ select: (s) => s.pathname,
368
+ })
369
+
370
+ const {
371
+ // custom props
372
+ type,
373
+ children,
374
+ target,
375
+ activeProps = () => ({ className: 'active' }),
376
+ inactiveProps = () => ({}),
377
+ activeOptions,
378
+ disabled,
379
+ hash,
380
+ search,
381
+ params,
382
+ to,
383
+ state,
384
+ mask,
385
+ preload,
386
+ preloadDelay,
387
+ replace,
388
+ startTransition,
389
+ resetScroll,
390
+ // element props
391
+ style,
392
+ className,
393
+ onClick,
394
+ onFocus,
395
+ onMouseEnter,
396
+ onMouseLeave,
397
+ onTouchStart,
398
+ ...rest
399
+ } = options
400
+
401
+ const linkInfo = buildLink({
402
+ from: options.to ? matchPathname : undefined,
403
+ ...options,
404
+ } as any)
405
+
406
+ if (linkInfo.type === 'external') {
407
+ const { href } = linkInfo
408
+ return { href }
409
+ }
410
+
411
+ const {
412
+ handleClick,
413
+ handleFocus,
414
+ handleEnter,
415
+ handleLeave,
416
+ handleTouchStart,
417
+ isActive,
418
+ next,
419
+ } = linkInfo
420
+
421
+ const composeHandlers =
422
+ (handlers: (undefined | ((e: any) => void))[]) =>
423
+ (e: React.SyntheticEvent) => {
424
+ if (e.persist) e.persist()
425
+ handlers.filter(Boolean).forEach((handler) => {
426
+ if (e.defaultPrevented) return
427
+ handler!(e)
428
+ })
429
+ }
430
+
431
+ // Get the active props
432
+ const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> = isActive
433
+ ? functionalUpdate(activeProps as any, {}) ?? {}
434
+ : {}
435
+
436
+ // Get the inactive props
437
+ const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =
438
+ isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {}
439
+
440
+ return {
441
+ ...resolvedActiveProps,
442
+ ...resolvedInactiveProps,
443
+ ...rest,
444
+ href: disabled
445
+ ? undefined
446
+ : next.maskedLocation
447
+ ? next.maskedLocation.href
448
+ : next.href,
449
+ onClick: composeHandlers([onClick, handleClick]),
450
+ onFocus: composeHandlers([onFocus, handleFocus]),
451
+ onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
452
+ onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
453
+ onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
454
+ target,
455
+ style: {
456
+ ...style,
457
+ ...resolvedActiveProps.style,
458
+ ...resolvedInactiveProps.style,
459
+ },
460
+ className:
461
+ [
462
+ className,
463
+ resolvedActiveProps.className,
464
+ resolvedInactiveProps.className,
465
+ ]
466
+ .filter(Boolean)
467
+ .join(' ') || undefined,
468
+ ...(disabled
469
+ ? {
470
+ role: 'link',
471
+ 'aria-disabled': true,
472
+ }
473
+ : undefined),
474
+ ['data-status']: isActive ? 'active' : undefined,
475
+ }
476
+ }
477
+
478
+ export interface LinkComponent<TProps extends Record<string, any> = {}> {
479
+ <
480
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
481
+ TFrom extends RoutePaths<TRouteTree> = '/',
482
+ TTo extends string = '',
483
+ TMaskFrom extends RoutePaths<TRouteTree> = '/',
484
+ TMaskTo extends string = '',
485
+ >(
486
+ props: MakeLinkOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> &
487
+ TProps &
488
+ React.RefAttributes<HTMLAnchorElement>,
489
+ ): ReactNode
490
+ }
491
+
492
+ export const Link: LinkComponent = React.forwardRef((props: any, ref) => {
493
+ const linkProps = useLinkProps(props)
494
+
495
+ return (
496
+ <a
497
+ {...{
498
+ ref: ref as any,
499
+ ...linkProps,
500
+ children:
501
+ typeof props.children === 'function'
502
+ ? props.children({
503
+ isActive: (linkProps as any)['data-status'] === 'active',
504
+ })
505
+ : props.children,
506
+ }}
507
+ />
508
+ )
509
+ }) as any
@@ -0,0 +1,15 @@
1
+ import { HistoryState } from '@tanstack/history'
2
+ import { AnySearchSchema } from './route'
3
+
4
+ export interface ParsedLocation<TSearchObj extends AnySearchSchema = {}> {
5
+ href: string
6
+ pathname: string
7
+ search: TSearchObj
8
+ searchStr: string
9
+ state: HistoryState
10
+ hash: string
11
+ maskedLocation?: ParsedLocation<TSearchObj>
12
+ unmaskOnReload?: boolean
13
+ }
14
+
15
+ export interface LocationState {}