@tanstack/react-router 0.0.1-beta.28 → 0.0.1-beta.280

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 (106) 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 +233 -0
  5. package/build/cjs/Matches.js.map +1 -0
  6. package/build/cjs/RouterProvider.js +170 -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 +130 -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 +223 -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 +191 -0
  29. package/build/cjs/route.js.map +1 -0
  30. package/build/cjs/router.js +1049 -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 +86 -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 +2255 -2571
  47. package/build/esm/index.js.map +1 -1
  48. package/build/stats-html.html +3498 -2694
  49. package/build/stats-react.json +1204 -44
  50. package/build/types/CatchBoundary.d.ts +36 -0
  51. package/build/types/Matches.d.ts +62 -0
  52. package/build/types/RouterProvider.d.ts +35 -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 +38 -0
  56. package/build/types/history.d.ts +7 -0
  57. package/build/types/index.d.ts +27 -114
  58. package/build/types/lazyRouteComponent.d.ts +2 -0
  59. package/build/types/link.d.ts +91 -0
  60. package/build/types/location.d.ts +12 -0
  61. package/build/types/path.d.ts +17 -0
  62. package/build/types/qss.d.ts +2 -0
  63. package/build/types/redirects.d.ts +11 -0
  64. package/build/types/route.d.ts +282 -0
  65. package/build/types/routeInfo.d.ts +22 -0
  66. package/build/types/router.d.ts +188 -0
  67. package/build/types/scroll-restoration.d.ts +18 -0
  68. package/build/types/searchParams.d.ts +7 -0
  69. package/build/types/useBlocker.d.ts +9 -0
  70. package/build/types/useNavigate.d.ts +19 -0
  71. package/build/types/useParams.d.ts +7 -0
  72. package/build/types/useSearch.d.ts +7 -0
  73. package/build/types/utils.d.ts +66 -0
  74. package/build/umd/index.development.js +2858 -2548
  75. package/build/umd/index.development.js.map +1 -1
  76. package/build/umd/index.production.js +4 -4
  77. package/build/umd/index.production.js.map +1 -1
  78. package/package.json +11 -10
  79. package/src/CatchBoundary.tsx +101 -0
  80. package/src/Matches.tsx +421 -0
  81. package/src/RouterProvider.tsx +252 -0
  82. package/src/awaited.tsx +40 -0
  83. package/src/defer.ts +55 -0
  84. package/src/fileRoute.ts +152 -0
  85. package/src/history.ts +8 -0
  86. package/src/index.tsx +28 -761
  87. package/src/lazyRouteComponent.tsx +33 -0
  88. package/src/link.tsx +598 -0
  89. package/src/location.ts +13 -0
  90. package/src/path.ts +261 -0
  91. package/src/qss.ts +53 -0
  92. package/src/redirects.ts +39 -0
  93. package/src/route.ts +872 -0
  94. package/src/routeInfo.ts +70 -0
  95. package/src/router.ts +1630 -0
  96. package/src/scroll-restoration.tsx +230 -0
  97. package/src/searchParams.ts +79 -0
  98. package/src/useBlocker.tsx +27 -0
  99. package/src/useNavigate.tsx +111 -0
  100. package/src/useParams.tsx +25 -0
  101. package/src/useSearch.tsx +25 -0
  102. package/src/utils.ts +350 -0
  103. package/build/cjs/react-router/src/index.js +0 -508
  104. package/build/cjs/react-router/src/index.js.map +0 -1
  105. package/build/cjs/router-core/build/esm/index.js +0 -2530
  106. package/build/cjs/router-core/build/esm/index.js.map +0 -1
package/src/index.tsx CHANGED
@@ -1,762 +1,29 @@
1
- import * as React from 'react'
2
-
3
- import { useSyncExternalStore } from 'use-sync-external-store/shim'
4
-
5
- import {
6
- AnyRoute,
7
- CheckId,
8
- rootRouteId,
9
- Route,
10
- RouterContext,
11
- RouterState,
12
- ToIdOption,
13
- } from '@tanstack/router-core'
14
- import {
15
- warning,
16
- RouterOptions,
17
- RouteMatch,
18
- MatchRouteOptions,
19
- RouteConfig,
20
- AnyRouteConfig,
21
- AnyAllRouteInfo,
22
- DefaultAllRouteInfo,
23
- functionalUpdate,
24
- createRouter,
25
- AnyRouteInfo,
26
- AllRouteInfo,
27
- RouteInfo,
28
- ValidFromPath,
29
- LinkOptions,
30
- RouteInfoByPath,
31
- ResolveRelativePath,
32
- NoInfer,
33
- ToOptions,
34
- invariant,
35
- Router,
36
- } from '@tanstack/router-core'
37
- import { restElement } from '@babel/types'
38
-
39
- export * from '@tanstack/router-core'
40
-
41
- export interface RegisterRouter {
42
- // router: Router
43
- }
44
-
45
- export type RegisteredRouter = RegisterRouter extends {
46
- router: Router<infer TRouteConfig, infer TAllRouteInfo>
47
- }
48
- ? Router<TRouteConfig, TAllRouteInfo>
49
- : Router
50
-
51
- export type RegisteredAllRouteInfo = RegisterRouter extends {
52
- router: Router<infer TRouteConfig, infer TAllRouteInfo>
53
- }
54
- ? TAllRouteInfo
55
- : AnyAllRouteInfo
56
-
57
- export type SyncRouteComponent<TProps = {}> = (
58
- props: TProps,
59
- ) => JSX.Element | React.ReactNode
60
-
61
- export type RouteComponent<TProps = {}> = SyncRouteComponent<TProps> & {
62
- preload?: () => Promise<SyncRouteComponent<TProps>>
63
- }
64
-
65
- export function lazy(
66
- importer: () => Promise<{ default: SyncRouteComponent }>,
67
- ): RouteComponent {
68
- const lazyComp = React.lazy(importer as any)
69
- let promise: Promise<SyncRouteComponent>
70
- let resolvedComp: SyncRouteComponent
71
-
72
- const forwardedComp = React.forwardRef((props, ref) => {
73
- const resolvedCompRef = React.useRef(resolvedComp || lazyComp)
74
- return React.createElement(
75
- resolvedCompRef.current as any,
76
- { ...(ref ? { ref } : {}), ...props } as any,
77
- )
78
- })
79
-
80
- const finalComp = forwardedComp as unknown as RouteComponent
81
-
82
- finalComp.preload = () => {
83
- if (!promise) {
84
- promise = importer().then((module) => {
85
- resolvedComp = module.default
86
- return resolvedComp
87
- })
88
- }
89
-
90
- return promise
91
- }
92
-
93
- return finalComp
94
- }
95
-
96
- type LinkPropsOptions<
97
- TAllRouteInfo extends AnyAllRouteInfo,
98
- TFrom extends ValidFromPath<TAllRouteInfo>,
99
- TTo extends string,
100
- > = LinkOptions<TAllRouteInfo, TFrom, TTo> & {
101
- // A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
102
- activeProps?:
103
- | React.AnchorHTMLAttributes<HTMLAnchorElement>
104
- | (() => React.AnchorHTMLAttributes<HTMLAnchorElement>)
105
- // A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
106
- inactiveProps?:
107
- | React.AnchorHTMLAttributes<HTMLAnchorElement>
108
- | (() => React.AnchorHTMLAttributes<HTMLAnchorElement>)
109
- }
110
-
111
- type MakeMatchRouteOptions<
112
- TAllRouteInfo extends AnyAllRouteInfo,
113
- TFrom extends ValidFromPath<TAllRouteInfo>,
114
- TTo extends string,
115
- > = ToOptions<TAllRouteInfo, TFrom, TTo> &
116
- MatchRouteOptions & {
117
- // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
118
- children?:
119
- | React.ReactNode
120
- | ((
121
- params: RouteInfoByPath<
122
- TAllRouteInfo,
123
- ResolveRelativePath<TFrom, NoInfer<TTo>>
124
- >['allParams'],
125
- ) => React.ReactNode)
126
- }
127
-
128
- type MakeLinkPropsOptions<
129
- TAllRouteInfo extends AnyAllRouteInfo,
130
- TFrom extends ValidFromPath<TAllRouteInfo>,
131
- TTo extends string,
132
- > = LinkPropsOptions<TAllRouteInfo, TFrom, TTo> &
133
- React.AnchorHTMLAttributes<HTMLAnchorElement>
134
-
135
- type MakeLinkOptions<
136
- TAllRouteInfo extends AnyAllRouteInfo,
137
- TFrom extends ValidFromPath<TAllRouteInfo>,
138
- TTo extends string,
139
- > = LinkPropsOptions<TAllRouteInfo, TFrom, TTo> &
140
- React.AnchorHTMLAttributes<HTMLAnchorElement> &
141
- Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
142
- // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
143
- children?:
144
- | React.ReactNode
145
- | ((state: { isActive: boolean }) => React.ReactNode)
146
- }
147
-
148
- declare module '@tanstack/router-core' {
149
- interface FrameworkGenerics {
150
- Component: RouteComponent
151
- ErrorComponent: RouteComponent<{
152
- error: unknown
153
- info: { componentStack: string }
154
- }>
155
- }
156
-
157
- interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
158
- useContext?: () => RouterContext
159
- }
160
-
161
- interface Router<
162
- TRouteConfig extends AnyRouteConfig = RouteConfig,
163
- TAllRouteInfo extends AnyAllRouteInfo = AllRouteInfo<TRouteConfig>,
164
- > {
165
- useState: () => RouterState
166
- useRoute: <TId extends keyof TAllRouteInfo['routeInfoById']>(
167
- routeId: TId,
168
- ) => Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
169
- useNearestMatch: () => RouteMatch<TAllRouteInfo, RouteInfo>
170
- useMatch: <
171
- TId extends keyof TAllRouteInfo['routeInfoById'],
172
- TStrict extends boolean = true,
173
- >(
174
- routeId: TId,
175
- opts?: { strict?: TStrict },
176
- ) => TStrict extends true
177
- ? RouteMatch<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
178
- :
179
- | RouteMatch<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
180
- | undefined
181
- linkProps: <TTo extends string = '.'>(
182
- props: MakeLinkPropsOptions<TAllRouteInfo, '/', TTo>,
183
- ) => React.AnchorHTMLAttributes<HTMLAnchorElement>
184
- Link: <TTo extends string = '.'>(
185
- props: MakeLinkOptions<TAllRouteInfo, '/', TTo>,
186
- ) => JSX.Element
187
- MatchRoute: <TTo extends string = '.'>(
188
- props: MakeMatchRouteOptions<TAllRouteInfo, '/', TTo>,
189
- ) => JSX.Element
190
- }
191
-
192
- interface Route<
193
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
194
- TRouteInfo extends AnyRouteInfo = RouteInfo,
195
- > {
196
- useRoute: <
197
- TTo extends string = '.',
198
- TResolved extends string = ResolveRelativePath<
199
- TRouteInfo['id'],
200
- NoInfer<TTo>
201
- >,
202
- >(
203
- routeId: CheckId<
204
- TAllRouteInfo,
205
- TResolved,
206
- ToIdOption<TAllRouteInfo, TRouteInfo['id'], TTo>
207
- >,
208
- opts?: { strict?: boolean },
209
- ) => Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TResolved]>
210
- linkProps: <TTo extends string = '.'>(
211
- props: MakeLinkPropsOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
212
- ) => React.AnchorHTMLAttributes<HTMLAnchorElement>
213
- Link: <TTo extends string = '.'>(
214
- props: MakeLinkOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
215
- ) => JSX.Element
216
- MatchRoute: <TTo extends string = '.'>(
217
- props: MakeMatchRouteOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo>,
218
- ) => JSX.Element
219
- }
220
- }
221
-
222
- export type PromptProps = {
223
- message: string
224
- when?: boolean | any
225
- children?: React.ReactNode
226
- }
227
-
228
1
  //
229
-
230
- export function Link<TTo extends string = '.'>(
231
- props: MakeLinkOptions<RegisteredAllRouteInfo, '/', TTo>,
232
- ): JSX.Element {
233
- const router = useRouter()
234
- return <router.Link {...(props as any)} />
235
- }
236
-
237
- export const matchesContext = React.createContext<RouteMatch[]>(null!)
238
- export const routerContext = React.createContext<{ router: RegisteredRouter }>(
239
- null!,
240
- )
241
-
242
- export type MatchesProviderProps = {
243
- value: RouteMatch[]
244
- children: React.ReactNode
245
- }
246
-
247
- export function MatchesProvider(props: MatchesProviderProps) {
248
- return <matchesContext.Provider {...props} />
249
- }
250
-
251
- const useRouterSubscription = (router: Router<any, any>) => {
252
- useSyncExternalStore(
253
- (cb) => router.subscribe(() => cb()),
254
- () => router.state,
255
- () => router.state,
256
- )
257
- }
258
-
259
- export function createReactRouter<
260
- TRouteConfig extends AnyRouteConfig = RouteConfig,
261
- >(opts: RouterOptions<TRouteConfig>): Router<TRouteConfig> {
262
- const makeRouteExt = (
263
- route: AnyRoute,
264
- router: Router<any, any>,
265
- ): Pick<AnyRoute, 'useRoute' | 'linkProps' | 'Link' | 'MatchRoute'> => {
266
- return {
267
- useRoute: (subRouteId = '.' as any) => {
268
- const resolvedRouteId = router.resolvePath(
269
- route.routeId,
270
- subRouteId as string,
271
- )
272
- const resolvedRoute = router.getRoute(resolvedRouteId)
273
- useRouterSubscription(router)
274
- invariant(
275
- resolvedRoute,
276
- `Could not find a route for route "${
277
- resolvedRouteId as string
278
- }"! Did you forget to add it to your route config?`,
279
- )
280
- return resolvedRoute
281
- },
282
- linkProps: (options) => {
283
- const {
284
- // custom props
285
- type,
286
- children,
287
- target,
288
- activeProps = () => ({ className: 'active' }),
289
- inactiveProps = () => ({}),
290
- activeOptions,
291
- disabled,
292
- // fromCurrent,
293
- hash,
294
- search,
295
- params,
296
- to,
297
- preload,
298
- preloadDelay,
299
- preloadMaxAge,
300
- replace,
301
- // element props
302
- style,
303
- className,
304
- onClick,
305
- onFocus,
306
- onMouseEnter,
307
- onMouseLeave,
308
- onTouchStart,
309
- onTouchEnd,
310
- ...rest
311
- } = options
312
-
313
- const linkInfo = route.buildLink(options as any)
314
-
315
- if (linkInfo.type === 'external') {
316
- const { href } = linkInfo
317
- return { href }
318
- }
319
-
320
- const {
321
- handleClick,
322
- handleFocus,
323
- handleEnter,
324
- handleLeave,
325
- isActive,
326
- next,
327
- } = linkInfo
328
-
329
- const reactHandleClick = (e: Event) => {
330
- if (React.startTransition) // This is a hack for react < 18
331
- React.startTransition(() => {handleClick(e)})
332
- else handleClick(e)
333
- }
334
-
335
- const composeHandlers =
336
- (handlers: (undefined | ((e: any) => void))[]) =>
337
- (e: React.SyntheticEvent) => {
338
- e.persist()
339
- handlers.forEach((handler) => {
340
- if (handler) handler(e)
341
- })
342
- }
343
-
344
- // Get the active props
345
- const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> =
346
- isActive ? functionalUpdate(activeProps, {}) ?? {} : {}
347
-
348
- // Get the inactive props
349
- const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =
350
- isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {}
351
-
352
- return {
353
- ...resolvedActiveProps,
354
- ...resolvedInactiveProps,
355
- ...rest,
356
- href: disabled ? undefined : next.href,
357
- onClick: composeHandlers([reactHandleClick, onClick]),
358
- onFocus: composeHandlers([handleFocus, onFocus]),
359
- onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
360
- onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
361
- target,
362
- style: {
363
- ...style,
364
- ...resolvedActiveProps.style,
365
- ...resolvedInactiveProps.style,
366
- },
367
- className:
368
- [
369
- className,
370
- resolvedActiveProps.className,
371
- resolvedInactiveProps.className,
372
- ]
373
- .filter(Boolean)
374
- .join(' ') || undefined,
375
- ...(disabled
376
- ? {
377
- role: 'link',
378
- 'aria-disabled': true,
379
- }
380
- : undefined),
381
- ['data-status']: isActive ? 'active' : undefined,
382
- }
383
- },
384
- Link: React.forwardRef((props: any, ref) => {
385
- const linkProps = route.linkProps(props)
386
-
387
- useRouterSubscription(router)
388
-
389
- return (
390
- <a
391
- {...{
392
- ref: ref as any,
393
- ...linkProps,
394
- children:
395
- typeof props.children === 'function'
396
- ? props.children({
397
- isActive: (linkProps as any)['data-status'] === 'active',
398
- })
399
- : props.children,
400
- }}
401
- />
402
- )
403
- }) as any,
404
- MatchRoute: (opts) => {
405
- const { pending, caseSensitive, children, ...rest } = opts
406
-
407
- const params = route.matchRoute(rest as any, {
408
- pending,
409
- caseSensitive,
410
- })
411
-
412
- if (!params) {
413
- return null
414
- }
415
-
416
- return typeof opts.children === 'function'
417
- ? opts.children(params as any)
418
- : (opts.children as any)
419
- },
420
- }
421
- }
422
-
423
- const coreRouter = createRouter<TRouteConfig>({
424
- ...opts,
425
- createRouter: (router) => {
426
- const routerExt: Pick<Router<any, any>, 'useMatch' | 'useState'> = {
427
- useState: () => {
428
- useRouterSubscription(router)
429
- return router.state
430
- },
431
- useMatch: (routeId, opts) => {
432
- useRouterSubscription(router)
433
-
434
- invariant(
435
- routeId !== rootRouteId,
436
- `"${rootRouteId}" cannot be used with useMatch! Did you mean to useRoute("${rootRouteId}")?`,
437
- )
438
-
439
- const runtimeMatch = useMatches()?.[0]!
440
- const match = router.state.matches.find((d) => d.routeId === routeId)
441
-
442
- if (opts?.strict ?? true) {
443
- invariant(
444
- match,
445
- `Could not find an active match for "${routeId as string}"!`,
446
- )
447
-
448
- invariant(
449
- runtimeMatch.routeId == match?.routeId,
450
- `useMatch("${
451
- match?.routeId as string
452
- }") is being called in a component that is meant to render the '${
453
- runtimeMatch.routeId
454
- }' route. Did you mean to 'useMatch("${
455
- match?.routeId as string
456
- }", { strict: false })' or 'useRoute("${
457
- match?.routeId as string
458
- }")' instead?`,
459
- )
460
- }
461
-
462
- return match as any
463
- },
464
- }
465
-
466
- const routeExt = makeRouteExt(router.getRoute(rootRouteId), router)
467
-
468
- Object.assign(router, routerExt, routeExt)
469
- },
470
- createRoute: ({ router, route }) => {
471
- const routeExt = makeRouteExt(route, router)
472
-
473
- Object.assign(route, routeExt)
474
- },
475
- loadComponent: async (component) => {
476
- if (component.preload && typeof document !== 'undefined') {
477
- component.preload()
478
- // return await component.preload()
479
- }
480
-
481
- return component as any
482
- },
483
- })
484
-
485
- return coreRouter as any
486
- }
487
-
488
- export type RouterProps<
489
- TRouteConfig extends AnyRouteConfig = RouteConfig,
490
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
491
- > = RouterOptions<TRouteConfig> & {
492
- router: Router<TRouteConfig, TAllRouteInfo>
493
- // Children will default to `<Outlet />` if not provided
494
- children?: React.ReactNode
495
- }
496
-
497
- export function RouterProvider<
498
- TRouteConfig extends AnyRouteConfig = RouteConfig,
499
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
500
- >({ children, router, ...rest }: RouterProps<TRouteConfig, TAllRouteInfo>) {
501
- router.update(rest)
502
-
503
- const defaultRouterContext = React.useRef({})
504
-
505
- const userContext =
506
- router.options.useContext?.() ?? defaultRouterContext.current
507
-
508
- router.context = userContext
509
-
510
- useRouterSubscription(router)
511
- React.useEffect(() => {
512
- return router.mount()
513
- }, [router])
514
-
515
- return (
516
- <routerContext.Provider value={{ router: router as any }}>
517
- <MatchesProvider value={router.state.matches}>
518
- {children ?? <Outlet />}
519
- </MatchesProvider>
520
- </routerContext.Provider>
521
- )
522
- }
523
-
524
- export function useRouter(): RegisteredRouter {
525
- const value = React.useContext(routerContext)
526
- warning(!value, 'useRouter must be used inside a <Router> component!')
527
-
528
- useRouterSubscription(value.router)
529
-
530
- return value.router
531
- }
532
-
533
- export function useMatches(): RouteMatch[] {
534
- return React.useContext(matchesContext)
535
- }
536
-
537
- export function useMatch<
538
- TId extends keyof RegisteredAllRouteInfo['routeInfoById'],
539
- TStrict extends boolean = true,
540
- >(
541
- routeId: TId,
542
- opts?: { strict?: TStrict },
543
- ): TStrict extends true
544
- ? RouteMatch<
545
- RegisteredAllRouteInfo,
546
- RegisteredAllRouteInfo['routeInfoById'][TId]
547
- >
548
- :
549
- | RouteMatch<
550
- RegisteredAllRouteInfo,
551
- RegisteredAllRouteInfo['routeInfoById'][TId]
552
- >
553
- | undefined {
554
- const router = useRouter()
555
- return router.useMatch(routeId as any, opts) as any
556
- }
557
-
558
- export function useNearestMatch(): RouteMatch<
559
- RegisteredAllRouteInfo,
560
- RouteInfo
561
- > {
562
- const runtimeMatch = useMatches()?.[0]!
563
-
564
- invariant(runtimeMatch, `Could not find a nearest match!`)
565
-
566
- return runtimeMatch as any
567
- }
568
-
569
- export function useRoute<
570
- TId extends keyof RegisteredAllRouteInfo['routeInfoById'],
571
- >(
572
- routeId: TId,
573
- ): Route<RegisteredAllRouteInfo, RegisteredAllRouteInfo['routeInfoById'][TId]> {
574
- const router = useRouter()
575
- return router.useRoute(routeId as any) as any
576
- }
577
-
578
- export function useSearch<
579
- TId extends keyof RegisteredAllRouteInfo['routeInfoById'] = keyof RegisteredAllRouteInfo['routeInfoById'],
580
- >(_routeId?: TId): RegisteredAllRouteInfo['fullSearchSchema'] {
581
- return useRouter().state.location.search
582
- }
583
-
584
- export function linkProps<TTo extends string = '.'>(
585
- props: MakeLinkPropsOptions<RegisteredAllRouteInfo, '/', TTo>,
586
- ): React.AnchorHTMLAttributes<HTMLAnchorElement> {
587
- const router = useRouter()
588
- return router.linkProps(props as any)
589
- }
590
-
591
- export function MatchRoute<TTo extends string = '.'>(
592
- props: MakeMatchRouteOptions<RegisteredAllRouteInfo, '/', TTo>,
593
- ): JSX.Element {
594
- const router = useRouter()
595
- return React.createElement(router.MatchRoute, props as any)
596
- }
597
-
598
- export function Outlet() {
599
- const router = useRouter()
600
- const matches = useMatches().slice(1)
601
- const match = matches[0]
602
-
603
- const defaultPending = React.useCallback(() => null, [])
604
-
605
- if (!match) {
606
- return null
607
- }
608
-
609
- const PendingComponent = (match.__.pendingComponent ??
610
- router.options.defaultPendingComponent ??
611
- defaultPending) as any
612
-
613
- const errorComponent =
614
- match.__.errorComponent ?? router.options.defaultErrorComponent
615
-
616
- return (
617
- <MatchesProvider value={matches}>
618
- <React.Suspense fallback={<PendingComponent />}>
619
- <CatchBoundary errorComponent={errorComponent} key={match.routeId}>
620
- {
621
- ((): React.ReactNode => {
622
- if (match.status === 'error') {
623
- throw match.error
624
- }
625
-
626
- if (match.status === 'success') {
627
- return React.createElement(
628
- (match.__.component as any) ??
629
- router.options.defaultComponent ??
630
- Outlet,
631
- )
632
- }
633
- throw match.__.loadPromise
634
- })() as JSX.Element
635
- }
636
- </CatchBoundary>
637
- </React.Suspense>
638
- </MatchesProvider>
639
- )
640
- }
641
-
642
- class CatchBoundary extends React.Component<{
643
- children: any
644
- errorComponent: any
645
- }> {
646
- state = {
647
- error: false,
648
- info: undefined,
649
- }
650
-
651
- componentDidCatch(error: any, info: any) {
652
- console.error(error)
653
-
654
- this.setState({
655
- error,
656
- info,
657
- })
658
- }
659
-
660
- render() {
661
- return (
662
- <CatchBoundaryInner
663
- {...this.props}
664
- errorState={this.state}
665
- reset={() => this.setState({})}
666
- />
667
- )
668
- }
669
- }
670
-
671
- // This is the messiest thing ever... I'm either seriously tired (likely) or
672
- // there has to be a better way to reset error boundaries when the
673
- // router's location key changes.
674
- function CatchBoundaryInner(props: {
675
- children: any
676
- errorComponent: any
677
- errorState: { error: unknown; info: any }
678
- reset: () => void
679
- }) {
680
- const [activeErrorState, setActiveErrorState] = React.useState(
681
- props.errorState,
682
- )
683
- const router = useRouter()
684
- const errorComponent = props.errorComponent ?? DefaultErrorBoundary
685
-
686
- React.useEffect(() => {
687
- if (activeErrorState) {
688
- let prevKey = router.state.location.key
689
- return router.subscribe(() => {
690
- if (router.state.location.key !== prevKey) {
691
- prevKey = router.state.location.key
692
- setActiveErrorState({} as any)
693
- }
694
- })
695
- }
696
-
697
- return
698
- }, [activeErrorState])
699
-
700
- React.useEffect(() => {
701
- if (props.errorState.error) {
702
- setActiveErrorState(props.errorState)
703
- }
704
- props.reset()
705
- }, [props.errorState.error])
706
-
707
- if (activeErrorState.error) {
708
- return React.createElement(errorComponent, activeErrorState)
709
- }
710
-
711
- return props.children
712
- }
713
-
714
- export function DefaultErrorBoundary({ error }: { error: any }) {
715
- return (
716
- <div style={{ padding: '.5rem', maxWidth: '100%' }}>
717
- <strong style={{ fontSize: '1.2rem' }}>Something went wrong!</strong>
718
- <div style={{ height: '.5rem' }} />
719
- <div>
720
- <pre>
721
- {error.message ? (
722
- <code
723
- style={{
724
- fontSize: '.7em',
725
- border: '1px solid red',
726
- borderRadius: '.25rem',
727
- padding: '.5rem',
728
- color: 'red',
729
- }}
730
- >
731
- {error.message}
732
- </code>
733
- ) : null}
734
- </pre>
735
- </div>
736
- </div>
737
- )
738
- }
739
-
740
- export function usePrompt(message: string, when: boolean | any): void {
741
- const router = useRouter()
742
-
743
- React.useEffect(() => {
744
- if (!when) return
745
-
746
- let unblock = router.history.block((transition) => {
747
- if (window.confirm(message)) {
748
- unblock()
749
- transition.retry()
750
- } else {
751
- router.location.pathname = window.location.pathname
752
- }
753
- })
754
-
755
- return unblock
756
- }, [when, location, message])
757
- }
758
-
759
- export function Prompt({ message, when, children }: PromptProps) {
760
- usePrompt(message, when ?? true)
761
- return (children ?? null) as React.ReactNode
762
- }
2
+ export * from '@tanstack/history'
3
+ export { default as invariant } from 'tiny-invariant'
4
+ export { default as warning } from 'tiny-warning'
5
+ export * from './awaited'
6
+ export * from './defer'
7
+ export * from './CatchBoundary'
8
+ export * from './fileRoute'
9
+ export * from './history'
10
+ export * from './index'
11
+ // export * from './injectHtml'
12
+ export * from './lazyRouteComponent'
13
+ export * from './link'
14
+ export * from './location'
15
+ export * from './Matches'
16
+ export * from './path'
17
+ export * from './qss'
18
+ export * from './redirects'
19
+ export * from './route'
20
+ export * from './routeInfo'
21
+ export * from './router'
22
+ export * from './RouterProvider'
23
+ export * from './scroll-restoration'
24
+ export * from './searchParams'
25
+ export * from './useBlocker'
26
+ export * from './useNavigate'
27
+ export * from './useParams'
28
+ export * from './useSearch'
29
+ export * from './utils'