@tanstack/react-router 0.0.1-beta.27 → 0.0.1-beta.271

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 +220 -0
  5. package/build/cjs/Matches.js.map +1 -0
  6. package/build/cjs/RouterProvider.js +165 -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 +126 -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 +179 -0
  29. package/build/cjs/route.js.map +1 -0
  30. package/build/cjs/router.js +1032 -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 +2214 -2576
  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 +59 -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 +34 -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 +273 -0
  65. package/build/types/routeInfo.d.ts +22 -0
  66. package/build/types/router.d.ts +180 -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 +2815 -2551
  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 +394 -0
  81. package/src/RouterProvider.tsx +237 -0
  82. package/src/awaited.tsx +40 -0
  83. package/src/defer.ts +55 -0
  84. package/src/fileRoute.ts +149 -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 +854 -0
  94. package/src/routeInfo.ts +68 -0
  95. package/src/router.ts +1592 -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 -507
  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
@@ -0,0 +1,237 @@
1
+ import * as React from 'react'
2
+ import warning from 'tiny-warning'
3
+ import { useStore } from '@tanstack/react-store'
4
+ import { Matches } from './Matches'
5
+ import { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
6
+ import { ParsedLocation } from './location'
7
+ import { AnyRoute } from './route'
8
+ import { RouteById, RoutePaths } from './routeInfo'
9
+ import {
10
+ BuildNextOptions,
11
+ RegisteredRouter,
12
+ Router,
13
+ RouterOptions,
14
+ RouterState,
15
+ } from './router'
16
+ import { NoInfer, pick, useLayoutEffect } from './utils'
17
+ import { MatchRouteOptions } from './Matches'
18
+ import { RouteMatch } from './Matches'
19
+
20
+ export interface CommitLocationOptions {
21
+ replace?: boolean
22
+ resetScroll?: boolean
23
+ startTransition?: boolean
24
+ }
25
+
26
+ export interface MatchLocation {
27
+ to?: string | number | null
28
+ fuzzy?: boolean
29
+ caseSensitive?: boolean
30
+ from?: string
31
+ }
32
+
33
+ export type NavigateFn<TRouteTree extends AnyRoute> = <
34
+ TFrom extends RoutePaths<TRouteTree> = '/',
35
+ TTo extends string = '',
36
+ TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
37
+ TMaskTo extends string = '',
38
+ >(
39
+ opts: NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
40
+ ) => Promise<void>
41
+
42
+ export type MatchRouteFn<TRouteTree extends AnyRoute> = <
43
+ TFrom extends RoutePaths<TRouteTree> = '/',
44
+ TTo extends string = '',
45
+ TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
46
+ >(
47
+ location: ToOptions<TRouteTree, TFrom, TTo>,
48
+ opts?: MatchRouteOptions,
49
+ ) => false | RouteById<TRouteTree, TResolved>['types']['allParams']
50
+
51
+ export type BuildLocationFn<TRouteTree extends AnyRoute> = (
52
+ opts: BuildNextOptions,
53
+ ) => ParsedLocation
54
+
55
+ export type InjectedHtmlEntry = string | (() => Promise<string> | string)
56
+
57
+ export const routerContext = React.createContext<Router<any>>(null!)
58
+
59
+ if (typeof document !== 'undefined') {
60
+ window.__TSR_ROUTER_CONTEXT__ = routerContext as any
61
+ }
62
+
63
+ export function RouterProvider<
64
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
65
+ TDehydrated extends Record<string, any> = Record<string, any>,
66
+ >({ router, ...rest }: RouterProps<TRouteTree, TDehydrated>) {
67
+ // Allow the router to update options on the router instance
68
+ router.update({
69
+ ...router.options,
70
+ ...rest,
71
+ context: {
72
+ ...router.options.context,
73
+ ...rest?.context,
74
+ },
75
+ } as any)
76
+
77
+ const inner = (
78
+ <routerContext.Provider value={router}>
79
+ <Matches />
80
+ <Transitioner />
81
+ </routerContext.Provider>
82
+ )
83
+
84
+ if (router.options.Wrap) {
85
+ return <router.options.Wrap>{inner}</router.options.Wrap>
86
+ }
87
+
88
+ return inner
89
+ }
90
+
91
+ function Transitioner() {
92
+ const router = useRouter()
93
+ const routerState = useRouterState({
94
+ select: (s) =>
95
+ pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning']),
96
+ })
97
+
98
+ const [isTransitioning, startReactTransition] = React.useTransition()
99
+
100
+ router.startReactTransition = startReactTransition
101
+
102
+ React.useEffect(() => {
103
+ if (isTransitioning) {
104
+ router.__store.setState((s) => ({
105
+ ...s,
106
+ isTransitioning,
107
+ }))
108
+ }
109
+ }, [isTransitioning])
110
+
111
+ const tryLoad = () => {
112
+ const apply = (cb: () => void) => {
113
+ if (!routerState.isTransitioning) {
114
+ startReactTransition(() => cb())
115
+ } else {
116
+ cb()
117
+ }
118
+ }
119
+
120
+ apply(() => {
121
+ try {
122
+ router.load()
123
+ } catch (err) {
124
+ console.error(err)
125
+ }
126
+ })
127
+ }
128
+
129
+ useLayoutEffect(() => {
130
+ const unsub = router.history.subscribe(() => {
131
+ router.latestLocation = router.parseLocation(router.latestLocation)
132
+ if (routerState.location !== router.latestLocation) {
133
+ tryLoad()
134
+ }
135
+ })
136
+
137
+ const nextLocation = router.buildLocation({
138
+ search: true,
139
+ params: true,
140
+ hash: true,
141
+ state: true,
142
+ })
143
+
144
+ if (routerState.location.href !== nextLocation.href) {
145
+ router.commitLocation({ ...nextLocation, replace: true })
146
+ }
147
+
148
+ return () => {
149
+ unsub()
150
+ }
151
+ }, [router.history])
152
+
153
+ useLayoutEffect(() => {
154
+ if (
155
+ routerState.isTransitioning &&
156
+ !isTransitioning &&
157
+ !routerState.isLoading &&
158
+ routerState.resolvedLocation !== routerState.location
159
+ ) {
160
+ router.emit({
161
+ type: 'onResolved',
162
+ fromLocation: routerState.resolvedLocation,
163
+ toLocation: routerState.location,
164
+ pathChanged:
165
+ routerState.location!.href !== routerState.resolvedLocation?.href,
166
+ })
167
+
168
+ if ((document as any).querySelector) {
169
+ const el = document.getElementById(
170
+ routerState.location.hash,
171
+ ) as HTMLElement | null
172
+ if (el) {
173
+ el.scrollIntoView()
174
+ }
175
+ }
176
+ router.pendingMatches = []
177
+
178
+ router.__store.setState((s) => ({
179
+ ...s,
180
+ isTransitioning: false,
181
+ resolvedLocation: s.location,
182
+ }))
183
+ }
184
+ }, [
185
+ routerState.isTransitioning,
186
+ isTransitioning,
187
+ routerState.isLoading,
188
+ routerState.resolvedLocation,
189
+ routerState.location,
190
+ ])
191
+
192
+ useLayoutEffect(() => {
193
+ if (!window.__TSR_DEHYDRATED__) {
194
+ tryLoad()
195
+ }
196
+ }, [])
197
+
198
+ return null
199
+ }
200
+
201
+ export function getRouteMatch<TRouteTree extends AnyRoute>(
202
+ state: RouterState<TRouteTree>,
203
+ id: string,
204
+ ): undefined | RouteMatch<TRouteTree> {
205
+ return [...(state.pendingMatches ?? []), ...state.matches].find(
206
+ (d) => d.id === id,
207
+ )
208
+ }
209
+
210
+ export function useRouterState<
211
+ TSelected = RouterState<RegisteredRouter['routeTree']>,
212
+ >(opts?: {
213
+ select: (state: RouterState<RegisteredRouter['routeTree']>) => TSelected
214
+ }): TSelected {
215
+ const router = useRouter()
216
+ return useStore(router.__store, opts?.select as any)
217
+ }
218
+
219
+ export type RouterProps<
220
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
221
+ TDehydrated extends Record<string, any> = Record<string, any>,
222
+ > = Omit<RouterOptions<TRouteTree, TDehydrated>, 'context'> & {
223
+ router: Router<TRouteTree>
224
+ context?: Partial<RouterOptions<TRouteTree, TDehydrated>['context']>
225
+ }
226
+
227
+ export function useRouter<
228
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
229
+ >(): Router<TRouteTree> {
230
+ const resolvedContext =
231
+ typeof document !== 'undefined'
232
+ ? window.__TSR_ROUTER_CONTEXT__ || routerContext
233
+ : routerContext
234
+ const value = React.useContext(resolvedContext)
235
+ warning(value, 'useRouter must be used inside a <RouterProvider> component!')
236
+ return value as any
237
+ }
@@ -0,0 +1,40 @@
1
+ import { useRouter } from './RouterProvider'
2
+ import { DeferredPromise, isDehydratedDeferred } from './defer'
3
+
4
+ export type AwaitOptions<T> = {
5
+ promise: DeferredPromise<T>
6
+ }
7
+
8
+ export function useAwaited<T>({ promise }: AwaitOptions<T>): [T] {
9
+ const router = useRouter()
10
+
11
+ let state = promise.__deferredState
12
+ const key = `__TSR__DEFERRED__${state.uid}`
13
+
14
+ if (isDehydratedDeferred(promise)) {
15
+ state = router.hydrateData(key)!
16
+ promise = Promise.resolve(state.data) as DeferredPromise<any>
17
+ promise.__deferredState = state
18
+ }
19
+
20
+ if (state.status === 'pending') {
21
+ throw new Promise((r) => setTimeout(r, 1)).then(() => promise)
22
+ }
23
+
24
+ if (state.status === 'error') {
25
+ throw state.error
26
+ }
27
+
28
+ router.dehydrateData(key, state)
29
+
30
+ return [state.data]
31
+ }
32
+
33
+ export function Await<T>(
34
+ props: AwaitOptions<T> & {
35
+ children: (result: T) => JSX.Element
36
+ },
37
+ ) {
38
+ const awaited = useAwaited(props)
39
+ return props.children(...awaited)
40
+ }
package/src/defer.ts ADDED
@@ -0,0 +1,55 @@
1
+ export type DeferredPromiseState<T> = { uid: string } & (
2
+ | {
3
+ status: 'pending'
4
+ data?: T
5
+ error?: unknown
6
+ }
7
+ | {
8
+ status: 'success'
9
+ data: T
10
+ }
11
+ | {
12
+ status: 'error'
13
+ data?: T
14
+ error: unknown
15
+ }
16
+ )
17
+
18
+ export type DeferredPromise<T> = Promise<T> & {
19
+ __deferredState: DeferredPromiseState<T>
20
+ }
21
+
22
+ export function defer<T>(_promise: Promise<T>) {
23
+ const promise = _promise as DeferredPromise<T>
24
+
25
+ if (!promise.__deferredState) {
26
+ promise.__deferredState = {
27
+ uid: Math.random().toString(36).slice(2),
28
+ status: 'pending',
29
+ }
30
+
31
+ const state = promise.__deferredState
32
+
33
+ promise
34
+ .then((data) => {
35
+ state.status = 'success' as any
36
+ state.data = data
37
+ })
38
+ .catch((error) => {
39
+ state.status = 'error' as any
40
+ state.error = error
41
+ })
42
+ }
43
+
44
+ return promise
45
+ }
46
+
47
+ export function isDehydratedDeferred(obj: any): boolean {
48
+ return (
49
+ typeof obj === 'object' &&
50
+ obj !== null &&
51
+ !(obj instanceof Promise) &&
52
+ !obj.then &&
53
+ '__deferredState' in obj
54
+ )
55
+ }
@@ -0,0 +1,149 @@
1
+ import { ParsePathParams } from './link'
2
+ import {
3
+ AnyRoute,
4
+ ResolveFullPath,
5
+ ResolveFullSearchSchema,
6
+ MergeFromFromParent,
7
+ RouteContext,
8
+ AnyContext,
9
+ RouteOptions,
10
+ UpdatableRouteOptions,
11
+ Route,
12
+ AnyPathParams,
13
+ RootRouteId,
14
+ TrimPathLeft,
15
+ RouteConstraints,
16
+ } from './route'
17
+ import { Assign, Expand, IsAny } from './utils'
18
+
19
+ export interface FileRoutesByPath {
20
+ // '/': {
21
+ // parentRoute: typeof rootRoute
22
+ // }
23
+ }
24
+
25
+ type Replace<
26
+ S extends string,
27
+ From extends string,
28
+ To extends string,
29
+ > = S extends `${infer Start}${From}${infer Rest}`
30
+ ? `${Start}${To}${Replace<Rest, From, To>}`
31
+ : S
32
+
33
+ export type TrimLeft<
34
+ T extends string,
35
+ S extends string,
36
+ > = T extends `${S}${infer U}` ? U : T
37
+
38
+ export type TrimRight<
39
+ T extends string,
40
+ S extends string,
41
+ > = T extends `${infer U}${S}` ? U : T
42
+
43
+ export type Trim<T extends string, S extends string> = TrimLeft<
44
+ TrimRight<T, S>,
45
+ S
46
+ >
47
+
48
+ export type RemoveUnderScores<T extends string> = Replace<
49
+ Replace<TrimRight<TrimLeft<T, '/_'>, '_'>, '_/', '/'>,
50
+ '/_',
51
+ '/'
52
+ >
53
+
54
+ export type ResolveFilePath<
55
+ TParentRoute extends AnyRoute,
56
+ TFilePath extends string,
57
+ > = TParentRoute['id'] extends RootRouteId
58
+ ? TrimPathLeft<TFilePath>
59
+ : Replace<
60
+ TrimPathLeft<TFilePath>,
61
+ TrimPathLeft<TParentRoute['types']['customId']>,
62
+ ''
63
+ >
64
+
65
+ export type FileRoutePath<
66
+ TParentRoute extends AnyRoute,
67
+ TFilePath extends string,
68
+ > = ResolveFilePath<TParentRoute, TFilePath> extends `_${infer _}`
69
+ ? string
70
+ : ResolveFilePath<TParentRoute, TFilePath>
71
+
72
+ export class FileRoute<
73
+ TFilePath extends keyof FileRoutesByPath,
74
+ TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'],
75
+ TId extends RouteConstraints['TId'] = TFilePath,
76
+ TPath extends RouteConstraints['TPath'] = FileRoutePath<
77
+ TParentRoute,
78
+ TFilePath
79
+ >,
80
+ TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<
81
+ TParentRoute,
82
+ RemoveUnderScores<TPath>
83
+ >,
84
+ > {
85
+ constructor(public path: TFilePath) {}
86
+
87
+ createRoute = <
88
+ TSearchSchema extends RouteConstraints['TSearchSchema'] = {},
89
+ TFullSearchSchema extends
90
+ RouteConstraints['TFullSearchSchema'] = ResolveFullSearchSchema<
91
+ TParentRoute,
92
+ TSearchSchema
93
+ >,
94
+ TParams extends RouteConstraints['TParams'] = Expand<
95
+ Record<ParsePathParams<TPath>, string>
96
+ >,
97
+ TAllParams extends RouteConstraints['TAllParams'] = MergeFromFromParent<
98
+ TParentRoute['types']['allParams'],
99
+ TParams
100
+ >,
101
+ TRouteContext extends RouteConstraints['TRouteContext'] = RouteContext,
102
+ TContext extends Expand<
103
+ Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>
104
+ > = Expand<
105
+ Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>
106
+ >,
107
+ TRouterContext extends RouteConstraints['TRouterContext'] = AnyContext,
108
+ TLoaderData extends any = unknown,
109
+ TChildren extends RouteConstraints['TChildren'] = unknown,
110
+ TRouteTree extends RouteConstraints['TRouteTree'] = AnyRoute,
111
+ >(
112
+ options?: Omit<
113
+ RouteOptions<
114
+ TParentRoute,
115
+ string,
116
+ TPath,
117
+ TSearchSchema,
118
+ TFullSearchSchema,
119
+ TParams,
120
+ TAllParams,
121
+ TRouteContext,
122
+ TContext,
123
+ TLoaderData
124
+ >,
125
+ 'getParentRoute' | 'path' | 'id'
126
+ > &
127
+ UpdatableRouteOptions<TFullSearchSchema>,
128
+ ): Route<
129
+ TParentRoute,
130
+ TPath,
131
+ TFullPath,
132
+ TFilePath,
133
+ TId,
134
+ TSearchSchema,
135
+ TFullSearchSchema,
136
+ TParams,
137
+ TAllParams,
138
+ TRouteContext,
139
+ TContext,
140
+ TRouterContext,
141
+ TLoaderData,
142
+ TChildren,
143
+ TRouteTree
144
+ > => {
145
+ const route = new Route(options as any)
146
+ ;(route as any).isRoot = false
147
+ return route as any
148
+ }
149
+ }
package/src/history.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { HistoryLocation } from '@tanstack/history'
2
+
3
+ declare module '@tanstack/history' {
4
+ interface HistoryState {
5
+ __tempLocation?: HistoryLocation
6
+ __tempKey?: string
7
+ }
8
+ }