@tanstack/react-router 0.0.1-alpha.9 → 0.0.1-beta.2

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.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-alpha.9",
4
+ "version": "0.0.1-beta.2",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
- "homepage": "https://react-router.tanstack.com/",
7
+ "homepage": "https://tanstack.com/router/",
8
8
  "description": "",
9
9
  "publishConfig": {
10
10
  "registry": "https://registry.npmjs.org/"
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@babel/runtime": "^7.16.7",
43
- "@tanstack/router-core": "0.0.1-alpha.9",
43
+ "@tanstack/router-core": "0.0.1-beta.2",
44
44
  "use-sync-external-store": "^1.2.0"
45
45
  },
46
46
  "devDependencies": {
package/src/index.tsx CHANGED
@@ -4,10 +4,11 @@ import { useSyncExternalStore } from 'use-sync-external-store/shim'
4
4
 
5
5
  import {
6
6
  AnyRoute,
7
- RootRouteId,
7
+ CheckId,
8
8
  rootRouteId,
9
9
  Router,
10
10
  RouterState,
11
+ ToIdOption,
11
12
  } from '@tanstack/router-core'
12
13
  import {
13
14
  warning,
@@ -37,19 +38,14 @@ export * from '@tanstack/router-core'
37
38
  declare module '@tanstack/router-core' {
38
39
  interface FrameworkGenerics {
39
40
  Element: React.ReactNode
40
- AsyncElement: (opts: {
41
- params: Record<string, string>
42
- }) => Promise<React.ReactNode>
43
- SyncOrAsyncElement: React.ReactNode | FrameworkGenerics['AsyncElement']
41
+ // Any is required here so import() will work without having to do import().then(d => d.default)
42
+ SyncOrAsyncElement: React.ReactNode | (() => Promise<any>)
44
43
  }
45
44
 
46
45
  interface Router<
47
46
  TRouteConfig extends AnyRouteConfig = RouteConfig,
48
47
  TAllRouteInfo extends AnyAllRouteInfo = AllRouteInfo<TRouteConfig>,
49
- > extends Pick<
50
- Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][RootRouteId]>,
51
- 'linkProps' | 'Link' | 'MatchRoute'
52
- > {
48
+ > {
53
49
  useState: () => RouterState
54
50
  useRoute: <TId extends keyof TAllRouteInfo['routeInfoById']>(
55
51
  routeId: TId,
@@ -91,6 +87,19 @@ declare module '@tanstack/router-core' {
91
87
  TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
92
88
  TRouteInfo extends AnyRouteInfo = RouteInfo,
93
89
  > {
90
+ useRoute: <
91
+ TTo extends string = '.',
92
+ TResolved extends string = ResolveRelativePath<
93
+ TRouteInfo['id'],
94
+ NoInfer<TTo>
95
+ >,
96
+ >(
97
+ routeId: CheckId<
98
+ TAllRouteInfo,
99
+ TResolved,
100
+ ToIdOption<TAllRouteInfo, TRouteInfo['id'], TTo>
101
+ >,
102
+ ) => Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TResolved]>
94
103
  linkProps: <TTo extends string = '.'>(
95
104
  props: LinkPropsOptions<TAllRouteInfo, TRouteInfo['fullPath'], TTo> &
96
105
  React.AnchorHTMLAttributes<HTMLAnchorElement>,
@@ -170,6 +179,7 @@ const useRouterSubscription = (router: Router<any, any>) => {
170
179
  useSyncExternalStore(
171
180
  (cb) => router.subscribe(() => cb()),
172
181
  () => router.state,
182
+ () => router.state,
173
183
  )
174
184
  }
175
185
 
@@ -179,8 +189,23 @@ export function createReactRouter<
179
189
  const makeRouteExt = (
180
190
  route: AnyRoute,
181
191
  router: Router<any, any>,
182
- ): Pick<AnyRoute, 'linkProps' | 'Link' | 'MatchRoute'> => {
192
+ ): Pick<AnyRoute, 'useRoute' | 'linkProps' | 'Link' | 'MatchRoute'> => {
183
193
  return {
194
+ useRoute: (subRouteId = '.' as any) => {
195
+ const resolvedRouteId = router.resolvePath(
196
+ route.routeId,
197
+ subRouteId as string,
198
+ )
199
+ const resolvedRoute = router.getRoute(resolvedRouteId)
200
+ useRouterSubscription(router)
201
+ invariant(
202
+ resolvedRoute,
203
+ `Could not find a route for route "${
204
+ resolvedRouteId as string
205
+ }"! Did you forget to add it to your route config?`,
206
+ )
207
+ return resolvedRoute
208
+ },
184
209
  linkProps: (options) => {
185
210
  const {
186
211
  // custom props
@@ -319,25 +344,11 @@ export function createReactRouter<
319
344
  const coreRouter = createRouter<TRouteConfig>({
320
345
  ...opts,
321
346
  createRouter: (router) => {
322
- const routerExt: Pick<
323
- Router<any, any>,
324
- 'useRoute' | 'useMatch' | 'useState'
325
- > = {
347
+ const routerExt: Pick<Router<any, any>, 'useMatch' | 'useState'> = {
326
348
  useState: () => {
327
349
  useRouterSubscription(router)
328
350
  return router.state
329
351
  },
330
- useRoute: (routeId) => {
331
- const route = router.getRoute(routeId)
332
- useRouterSubscription(router)
333
- invariant(
334
- route,
335
- `Could not find a route for route "${
336
- routeId as string
337
- }"! Did you forget to add it to your route config?`,
338
- )
339
- return route
340
- },
341
352
  useMatch: (routeId) => {
342
353
  useRouterSubscription(router)
343
354
 
@@ -384,6 +395,20 @@ export function createReactRouter<
384
395
 
385
396
  Object.assign(route, routeExt)
386
397
  },
398
+ createElement: async (element) => {
399
+ if (typeof element === 'function') {
400
+ const res = (await element()) as any
401
+
402
+ // Support direct import() calls
403
+ if (typeof res === 'object' && res.default) {
404
+ return React.createElement(res.default)
405
+ } else {
406
+ return res
407
+ }
408
+ }
409
+
410
+ return element
411
+ },
387
412
  })
388
413
 
389
414
  return coreRouter as any
@@ -576,4 +601,26 @@ export function DefaultErrorBoundary({ error }: { error: any }) {
576
601
  )
577
602
  }
578
603
 
579
- // TODO: Add prompt
604
+ export function usePrompt(message: string, when: boolean | any): void {
605
+ const router = useRouter()
606
+
607
+ React.useEffect(() => {
608
+ if (!when) return
609
+
610
+ let unblock = router.history.block((transition) => {
611
+ if (window.confirm(message)) {
612
+ unblock()
613
+ transition.retry()
614
+ } else {
615
+ router.location.pathname = window.location.pathname
616
+ }
617
+ })
618
+
619
+ return unblock
620
+ }, [when, location, message])
621
+ }
622
+
623
+ export function Prompt({ message, when, children }: PromptProps) {
624
+ usePrompt(message, when ?? true)
625
+ return (children ?? null) as React.ReactNode
626
+ }
package/src/qss.ts DELETED
@@ -1,53 +0,0 @@
1
- // @ts-nocheck
2
-
3
- // We're inlining qss here for compression's sake, but we've included it as a hard dependency for the MIT license it requires.
4
-
5
- export function encode(obj, pfx?: string) {
6
- var k,
7
- i,
8
- tmp,
9
- str = ''
10
-
11
- for (k in obj) {
12
- if ((tmp = obj[k]) !== void 0) {
13
- if (Array.isArray(tmp)) {
14
- for (i = 0; i < tmp.length; i++) {
15
- str && (str += '&')
16
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i])
17
- }
18
- } else {
19
- str && (str += '&')
20
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp)
21
- }
22
- }
23
- }
24
-
25
- return (pfx || '') + str
26
- }
27
-
28
- function toValue(mix) {
29
- if (!mix) return ''
30
- var str = decodeURIComponent(mix)
31
- if (str === 'false') return false
32
- if (str === 'true') return true
33
- return +str * 0 === 0 ? +str : str
34
- }
35
-
36
- export function decode(str) {
37
- var tmp,
38
- k,
39
- out = {},
40
- arr = str.split('&')
41
-
42
- while ((tmp = arr.shift())) {
43
- tmp = tmp.split('=')
44
- k = tmp.shift()
45
- if (out[k] !== void 0) {
46
- out[k] = [].concat(out[k], toValue(tmp.shift()))
47
- } else {
48
- out[k] = toValue(tmp.shift())
49
- }
50
- }
51
-
52
- return out
53
- }