@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,254 @@
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 {
6
+ LinkInfo,
7
+ LinkOptions,
8
+ NavigateOptions,
9
+ ResolveRelativePath,
10
+ ToOptions,
11
+ } from './link'
12
+ import { ParsedLocation } from './location'
13
+ import { AnyRoute } from './route'
14
+ import { RouteById, RoutePaths } from './routeInfo'
15
+ import {
16
+ BuildNextOptions,
17
+ RegisteredRouter,
18
+ Router,
19
+ RouterOptions,
20
+ RouterState,
21
+ } from './router'
22
+ import { NoInfer, PickAsRequired, pick, useLayoutEffect } from './utils'
23
+ import { MatchRouteOptions } from './Matches'
24
+ import { RouteMatch } from './Matches'
25
+
26
+ export interface CommitLocationOptions {
27
+ replace?: boolean
28
+ resetScroll?: boolean
29
+ startTransition?: boolean
30
+ }
31
+
32
+ export interface MatchLocation {
33
+ to?: string | number | null
34
+ fuzzy?: boolean
35
+ caseSensitive?: boolean
36
+ from?: string
37
+ }
38
+
39
+ export type BuildLinkFn<TRouteTree extends AnyRoute> = <
40
+ TFrom extends RoutePaths<TRouteTree> = '/',
41
+ TTo extends string = '',
42
+ >(
43
+ dest: LinkOptions<TRouteTree, TFrom, TTo>,
44
+ ) => LinkInfo
45
+
46
+ export type NavigateFn<TRouteTree extends AnyRoute> = <
47
+ TFrom extends RoutePaths<TRouteTree> = '/',
48
+ TTo extends string = '',
49
+ TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
50
+ TMaskTo extends string = '',
51
+ >(
52
+ opts: NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
53
+ ) => Promise<void>
54
+
55
+ export type MatchRouteFn<TRouteTree extends AnyRoute> = <
56
+ TFrom extends RoutePaths<TRouteTree> = '/',
57
+ TTo extends string = '',
58
+ TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
59
+ >(
60
+ location: ToOptions<TRouteTree, TFrom, TTo>,
61
+ opts?: MatchRouteOptions,
62
+ ) => false | RouteById<TRouteTree, TResolved>['types']['allParams']
63
+
64
+ export type BuildLocationFn<TRouteTree extends AnyRoute> = (
65
+ opts: BuildNextOptions,
66
+ ) => ParsedLocation
67
+
68
+ export type InjectedHtmlEntry = string | (() => Promise<string> | string)
69
+
70
+ export const routerContext = React.createContext<Router<any>>(null!)
71
+
72
+ if (typeof document !== 'undefined') {
73
+ window.__TSR_ROUTER_CONTEXT__ = routerContext as any
74
+ }
75
+
76
+ export function RouterProvider<
77
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
78
+ TDehydrated extends Record<string, any> = Record<string, any>,
79
+ >({ router, ...rest }: RouterProps<TRouteTree, TDehydrated>) {
80
+ // Allow the router to update options on the router instance
81
+ router.update({
82
+ ...router.options,
83
+ ...rest,
84
+ context: {
85
+ ...router.options.context,
86
+ ...rest?.context,
87
+ },
88
+ } as any)
89
+
90
+ const inner = (
91
+ <routerContext.Provider value={router}>
92
+ <Matches />
93
+ <Transitioner />
94
+ </routerContext.Provider>
95
+ )
96
+
97
+ if (router.options.Wrap) {
98
+ return <router.options.Wrap>{inner}</router.options.Wrap>
99
+ }
100
+
101
+ return inner
102
+ }
103
+
104
+ function Transitioner() {
105
+ const router = useRouter()
106
+ const routerState = useRouterState({
107
+ select: (s) =>
108
+ pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning']),
109
+ })
110
+
111
+ const [isTransitioning, startReactTransition] = React.useTransition()
112
+
113
+ router.startReactTransition = startReactTransition
114
+
115
+ React.useEffect(() => {
116
+ if (isTransitioning) {
117
+ router.__store.setState((s) => ({
118
+ ...s,
119
+ isTransitioning,
120
+ }))
121
+ }
122
+ }, [isTransitioning])
123
+
124
+ const tryLoad = () => {
125
+ const apply = (cb: () => void) => {
126
+ if (!routerState.isTransitioning) {
127
+ startReactTransition(() => cb())
128
+ } else {
129
+ cb()
130
+ }
131
+ }
132
+
133
+ apply(() => {
134
+ try {
135
+ router.load()
136
+ } catch (err) {
137
+ console.error(err)
138
+ }
139
+ })
140
+ }
141
+
142
+ useLayoutEffect(() => {
143
+ const unsub = router.history.subscribe(() => {
144
+ router.latestLocation = router.parseLocation(router.latestLocation)
145
+ if (routerState.location !== router.latestLocation) {
146
+ tryLoad()
147
+ }
148
+ })
149
+
150
+ const nextLocation = router.buildLocation({
151
+ search: true,
152
+ params: true,
153
+ hash: true,
154
+ state: true,
155
+ })
156
+
157
+ if (routerState.location.href !== nextLocation.href) {
158
+ router.commitLocation({ ...nextLocation, replace: true })
159
+ }
160
+
161
+ return () => {
162
+ unsub()
163
+ }
164
+ }, [router.history])
165
+
166
+ useLayoutEffect(() => {
167
+ if (
168
+ routerState.isTransitioning &&
169
+ !isTransitioning &&
170
+ !routerState.isLoading &&
171
+ routerState.resolvedLocation !== routerState.location
172
+ ) {
173
+ router.emit({
174
+ type: 'onResolved',
175
+ fromLocation: routerState.resolvedLocation,
176
+ toLocation: routerState.location,
177
+ pathChanged:
178
+ routerState.location!.href !== routerState.resolvedLocation?.href,
179
+ })
180
+
181
+ if (
182
+ routerState.location.hash !== routerState.resolvedLocation?.hash &&
183
+ (document as any).querySelector
184
+ ) {
185
+ console.log('hello', routerState.location.hash)
186
+ const el = document.getElementById(
187
+ routerState.location.hash,
188
+ ) as HTMLElement | null
189
+ if (el) {
190
+ el.scrollIntoView()
191
+ }
192
+ }
193
+ router.pendingMatches = []
194
+
195
+ router.__store.setState((s) => ({
196
+ ...s,
197
+ isTransitioning: false,
198
+ resolvedLocation: s.location,
199
+ }))
200
+ }
201
+ }, [
202
+ routerState.isTransitioning,
203
+ isTransitioning,
204
+ routerState.isLoading,
205
+ routerState.resolvedLocation,
206
+ routerState.location,
207
+ ])
208
+
209
+ useLayoutEffect(() => {
210
+ if (!window.__TSR_DEHYDRATED__) {
211
+ tryLoad()
212
+ }
213
+ }, [])
214
+
215
+ return null
216
+ }
217
+
218
+ export function getRouteMatch<TRouteTree extends AnyRoute>(
219
+ state: RouterState<TRouteTree>,
220
+ id: string,
221
+ ): undefined | RouteMatch<TRouteTree> {
222
+ return [...(state.pendingMatches ?? []), ...state.matches].find(
223
+ (d) => d.id === id,
224
+ )
225
+ }
226
+
227
+ export function useRouterState<
228
+ TSelected = RouterState<RegisteredRouter['routeTree']>,
229
+ >(opts?: {
230
+ select: (state: RouterState<RegisteredRouter['routeTree']>) => TSelected
231
+ }): TSelected {
232
+ const router = useRouter()
233
+ return useStore(router.__store, opts?.select as any)
234
+ }
235
+
236
+ export type RouterProps<
237
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
238
+ TDehydrated extends Record<string, any> = Record<string, any>,
239
+ > = Omit<RouterOptions<TRouteTree, TDehydrated>, 'context'> & {
240
+ router: Router<TRouteTree>
241
+ context?: Partial<RouterOptions<TRouteTree, TDehydrated>['context']>
242
+ }
243
+
244
+ export function useRouter<
245
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
246
+ >(): Router<TRouteTree> {
247
+ const resolvedContext =
248
+ typeof document !== 'undefined'
249
+ ? window.__TSR_ROUTER_CONTEXT__ || routerContext
250
+ : routerContext
251
+ const value = React.useContext(resolvedContext)
252
+ warning(value, 'useRouter must be used inside a <RouterProvider> component!')
253
+ return value as any
254
+ }
@@ -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,154 @@
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<
128
+ TFullSearchSchema,
129
+ TAllParams,
130
+ TContext,
131
+ TLoaderData
132
+ >,
133
+ ): Route<
134
+ TParentRoute,
135
+ TPath,
136
+ TFullPath,
137
+ TFilePath,
138
+ TId,
139
+ TSearchSchema,
140
+ TFullSearchSchema,
141
+ TParams,
142
+ TAllParams,
143
+ TRouteContext,
144
+ TContext,
145
+ TRouterContext,
146
+ TLoaderData,
147
+ TChildren,
148
+ TRouteTree
149
+ > => {
150
+ const route = new Route(options as any)
151
+ ;(route as any).isRoot = false
152
+ return route as any
153
+ }
154
+ }
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
+ }