@tanstack/react-router 0.0.1-alpha.1 → 0.0.1-alpha.3

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-alpha.1",
4
+ "version": "0.0.1-alpha.3",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://react-router.tanstack.com/",
@@ -31,7 +31,7 @@
31
31
  "node": ">=12"
32
32
  },
33
33
  "files": [
34
- "build",
34
+ "build/**",
35
35
  "src"
36
36
  ],
37
37
  "peerDependencies": {
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@babel/runtime": "^7.16.7",
43
- "@tanstack/router-core": "0.0.1-alpha.1",
43
+ "@tanstack/router-core": "0.0.1-alpha.3",
44
44
  "use-sync-external-store": "^1.2.0"
45
45
  },
46
46
  "devDependencies": {
package/src/index.tsx CHANGED
@@ -55,34 +55,34 @@ declare module '@tanstack/router-core' {
55
55
  useMatch: <TId extends keyof TAllRouteInfo['routeInfoById']>(
56
56
  routeId: TId,
57
57
  ) => RouteMatch<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
58
- // linkProps: <TTo extends string = '.'>(
59
- // props: LinkPropsOptions<TAllRouteInfo, '/', TTo> &
60
- // React.AnchorHTMLAttributes<HTMLAnchorElement>,
61
- // ) => React.AnchorHTMLAttributes<HTMLAnchorElement>
62
- // Link: <TTo extends string = '.'>(
63
- // props: LinkPropsOptions<TAllRouteInfo, '/', TTo> &
64
- // React.AnchorHTMLAttributes<HTMLAnchorElement> &
65
- // Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
66
- // // 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
67
- // children?:
68
- // | React.ReactNode
69
- // | ((state: { isActive: boolean }) => React.ReactNode)
70
- // },
71
- // ) => JSX.Element
72
- // MatchRoute: <TTo extends string = '.'>(
73
- // props: ToOptions<TAllRouteInfo, '/', TTo> &
74
- // MatchRouteOptions & {
75
- // // 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
76
- // children?:
77
- // | React.ReactNode
78
- // | ((
79
- // params: RouteInfoByPath<
80
- // TAllRouteInfo,
81
- // ResolveRelativePath<'/', NoInfer<TTo>>
82
- // >['allParams'],
83
- // ) => React.ReactNode)
84
- // },
85
- // ) => JSX.Element
58
+ linkProps: <TTo extends string = '.'>(
59
+ props: LinkPropsOptions<TAllRouteInfo, '/', TTo> &
60
+ React.AnchorHTMLAttributes<HTMLAnchorElement>,
61
+ ) => React.AnchorHTMLAttributes<HTMLAnchorElement>
62
+ Link: <TTo extends string = '.'>(
63
+ props: LinkPropsOptions<TAllRouteInfo, '/', TTo> &
64
+ React.AnchorHTMLAttributes<HTMLAnchorElement> &
65
+ Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
66
+ // 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
67
+ children?:
68
+ | React.ReactNode
69
+ | ((state: { isActive: boolean }) => React.ReactNode)
70
+ },
71
+ ) => JSX.Element
72
+ MatchRoute: <TTo extends string = '.'>(
73
+ props: ToOptions<TAllRouteInfo, '/', TTo> &
74
+ MatchRouteOptions & {
75
+ // 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
76
+ children?:
77
+ | React.ReactNode
78
+ | ((
79
+ params: RouteInfoByPath<
80
+ TAllRouteInfo,
81
+ ResolveRelativePath<'/', NoInfer<TTo>>
82
+ >['allParams'],
83
+ ) => React.ReactNode)
84
+ },
85
+ ) => JSX.Element
86
86
  }
87
87
 
88
88
  interface Route<
@@ -174,6 +174,148 @@ const useRouterSubscription = (router: Router<any, any>) => {
174
174
  export function createReactRouter<
175
175
  TRouteConfig extends AnyRouteConfig = RouteConfig,
176
176
  >(opts: RouterOptions<TRouteConfig>): Router<TRouteConfig> {
177
+ const makeRouteExt = (
178
+ route: AnyRoute,
179
+ router: Router<any, any>,
180
+ ): Pick<AnyRoute, 'linkProps' | 'Link' | 'MatchRoute'> => {
181
+ return {
182
+ linkProps: (options) => {
183
+ const {
184
+ // custom props
185
+ type,
186
+ children,
187
+ target,
188
+ activeProps = () => ({ className: 'active' }),
189
+ inactiveProps = () => ({}),
190
+ activeOptions,
191
+ disabled,
192
+ // fromCurrent,
193
+ hash,
194
+ search,
195
+ params,
196
+ to,
197
+ preload,
198
+ preloadDelay,
199
+ preloadMaxAge,
200
+ replace,
201
+ // element props
202
+ style,
203
+ className,
204
+ onClick,
205
+ onFocus,
206
+ onMouseEnter,
207
+ onMouseLeave,
208
+ onTouchStart,
209
+ onTouchEnd,
210
+ ...rest
211
+ } = options
212
+
213
+ const linkInfo = route.buildLink(options)
214
+
215
+ if (linkInfo.type === 'external') {
216
+ const { href } = linkInfo
217
+ return { href }
218
+ }
219
+
220
+ const {
221
+ handleClick,
222
+ handleFocus,
223
+ handleEnter,
224
+ handleLeave,
225
+ isActive,
226
+ next,
227
+ } = linkInfo
228
+
229
+ const composeHandlers =
230
+ (handlers: (undefined | ((e: any) => void))[]) =>
231
+ (e: React.SyntheticEvent) => {
232
+ e.persist()
233
+ handlers.forEach((handler) => {
234
+ if (handler) handler(e)
235
+ })
236
+ }
237
+
238
+ // Get the active props
239
+ const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> =
240
+ isActive ? functionalUpdate(activeProps) ?? {} : {}
241
+
242
+ // Get the inactive props
243
+ const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =
244
+ isActive ? {} : functionalUpdate(inactiveProps) ?? {}
245
+
246
+ return {
247
+ ...resolvedActiveProps,
248
+ ...resolvedInactiveProps,
249
+ ...rest,
250
+ href: disabled ? undefined : next.href,
251
+ onClick: composeHandlers([handleClick, onClick]),
252
+ onFocus: composeHandlers([handleFocus, onFocus]),
253
+ onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
254
+ onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
255
+ target,
256
+ style: {
257
+ ...style,
258
+ ...resolvedActiveProps.style,
259
+ ...resolvedInactiveProps.style,
260
+ },
261
+ className:
262
+ [
263
+ className,
264
+ resolvedActiveProps.className,
265
+ resolvedInactiveProps.className,
266
+ ]
267
+ .filter(Boolean)
268
+ .join(' ') || undefined,
269
+ ...(disabled
270
+ ? {
271
+ role: 'link',
272
+ 'aria-disabled': true,
273
+ }
274
+ : undefined),
275
+ ['data-status']: isActive ? 'active' : undefined,
276
+ }
277
+ },
278
+ Link: React.forwardRef((props: any, ref) => {
279
+ const linkProps = route.linkProps(props)
280
+
281
+ useRouterSubscription(router)
282
+
283
+ return (
284
+ <a
285
+ {...{
286
+ ref: ref as any,
287
+ ...linkProps,
288
+ children:
289
+ typeof props.children === 'function'
290
+ ? props.children({
291
+ isActive: (linkProps as any)['data-status'] === 'active',
292
+ })
293
+ : props.children,
294
+ }}
295
+ />
296
+ )
297
+ }) as any,
298
+ MatchRoute: (opts) => {
299
+ const { pending, caseSensitive, children, ...rest } = opts
300
+
301
+ const params = route.matchRoute(rest as any, {
302
+ pending,
303
+ caseSensitive,
304
+ })
305
+
306
+ // useRouterSubscription(router)
307
+
308
+ if (!params) {
309
+ return null
310
+ }
311
+
312
+ return typeof opts.children === 'function'
313
+ ? opts.children(params as any)
314
+ : (opts.children as any)
315
+ },
316
+ }
317
+ }
318
+
177
319
  const coreRouter = createRouter<TRouteConfig>({
178
320
  ...opts,
179
321
  createRouter: (router) => {
@@ -229,146 +371,12 @@ export function createReactRouter<
229
371
  },
230
372
  }
231
373
 
232
- Object.assign(router, routerExt)
374
+ const routeExt = makeRouteExt(router.getRoute('/'), router)
375
+
376
+ Object.assign(router, routerExt, routeExt)
233
377
  },
234
378
  createRoute: ({ router, route }) => {
235
- const routeExt: Pick<AnyRoute, 'linkProps' | 'Link' | 'MatchRoute'> = {
236
- linkProps: (options) => {
237
- const {
238
- // custom props
239
- type,
240
- children,
241
- target,
242
- activeProps = () => ({ className: 'active' }),
243
- inactiveProps = () => ({}),
244
- activeOptions,
245
- disabled,
246
- // fromCurrent,
247
- hash,
248
- search,
249
- params,
250
- to,
251
- preload,
252
- preloadDelay,
253
- preloadMaxAge,
254
- replace,
255
- // element props
256
- style,
257
- className,
258
- onClick,
259
- onFocus,
260
- onMouseEnter,
261
- onMouseLeave,
262
- onTouchStart,
263
- onTouchEnd,
264
- ...rest
265
- } = options
266
-
267
- const linkInfo = route.buildLink(options)
268
-
269
- if (linkInfo.type === 'external') {
270
- const { href } = linkInfo
271
- return { href }
272
- }
273
-
274
- const {
275
- handleClick,
276
- handleFocus,
277
- handleEnter,
278
- handleLeave,
279
- isActive,
280
- next,
281
- } = linkInfo
282
-
283
- const composeHandlers =
284
- (handlers: (undefined | ((e: any) => void))[]) =>
285
- (e: React.SyntheticEvent) => {
286
- e.persist()
287
- handlers.forEach((handler) => {
288
- if (handler) handler(e)
289
- })
290
- }
291
-
292
- // Get the active props
293
- const resolvedActiveProps: React.HTMLAttributes<HTMLAnchorElement> =
294
- isActive ? functionalUpdate(activeProps) ?? {} : {}
295
-
296
- // Get the inactive props
297
- const resolvedInactiveProps: React.HTMLAttributes<HTMLAnchorElement> =
298
- isActive ? {} : functionalUpdate(inactiveProps) ?? {}
299
-
300
- return {
301
- ...resolvedActiveProps,
302
- ...resolvedInactiveProps,
303
- ...rest,
304
- href: disabled ? undefined : next.href,
305
- onClick: composeHandlers([handleClick, onClick]),
306
- onFocus: composeHandlers([handleFocus, onFocus]),
307
- onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
308
- onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
309
- target,
310
- style: {
311
- ...style,
312
- ...resolvedActiveProps.style,
313
- ...resolvedInactiveProps.style,
314
- },
315
- className:
316
- [
317
- className,
318
- resolvedActiveProps.className,
319
- resolvedInactiveProps.className,
320
- ]
321
- .filter(Boolean)
322
- .join(' ') || undefined,
323
- ...(disabled
324
- ? {
325
- role: 'link',
326
- 'aria-disabled': true,
327
- }
328
- : undefined),
329
- ['data-status']: isActive ? 'active' : undefined,
330
- }
331
- },
332
- Link: React.forwardRef((props: any, ref) => {
333
- const linkProps = route.linkProps(props)
334
-
335
- useRouterSubscription(router)
336
-
337
- return (
338
- <a
339
- {...{
340
- ref: ref as any,
341
- ...linkProps,
342
- children:
343
- typeof props.children === 'function'
344
- ? props.children({
345
- isActive:
346
- (linkProps as any)['data-status'] === 'active',
347
- })
348
- : props.children,
349
- }}
350
- />
351
- )
352
- }) as any,
353
- MatchRoute: (opts) => {
354
- const { pending, caseSensitive, children, ...rest } = opts
355
-
356
- const params = route.matchRoute(rest as any, {
357
- pending,
358
- caseSensitive,
359
- })
360
-
361
- // useRouterSubscription(router)
362
-
363
- if (!params) {
364
- return null
365
- }
366
-
367
- return typeof opts.children === 'function'
368
- ? opts.children(params as any)
369
- : (opts.children as any)
370
- },
371
- }
379
+ const routeExt = makeRouteExt(route, router)
372
380
 
373
381
  Object.assign(route, routeExt)
374
382
  },