@tanstack/react-router 0.0.1-beta.261 → 0.0.1-beta.262
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/build/cjs/link.js +96 -22
- package/build/cjs/link.js.map +1 -1
- package/build/cjs/router.js +0 -112
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +96 -134
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +355 -355
- package/build/types/router.d.ts +1 -2
- package/build/umd/index.development.js +96 -134
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/link.tsx +126 -19
- package/src/router.ts +0 -139
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-beta.
|
|
4
|
+
"version": "0.0.1-beta.262",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "tanstack/router",
|
|
7
7
|
"homepage": "https://tanstack.com/router",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@tanstack/store": "^0.1.3",
|
|
45
45
|
"tiny-invariant": "^1.3.1",
|
|
46
46
|
"tiny-warning": "^1.0.3",
|
|
47
|
-
"@tanstack/history": "0.0.1-beta.
|
|
47
|
+
"@tanstack/history": "0.0.1-beta.262"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rollup --config rollup.config.js"
|
package/src/link.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { useMatch } from './Matches'
|
|
3
|
-
import { useRouter } from './RouterProvider'
|
|
3
|
+
import { useRouter, useRouterState } from './RouterProvider'
|
|
4
4
|
import { Trim } from './fileRoute'
|
|
5
5
|
import { LocationState, ParsedLocation } from './location'
|
|
6
6
|
import { AnyRoute, ReactNode } from './route'
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
PickRequired,
|
|
21
21
|
UnionToIntersection,
|
|
22
22
|
Updater,
|
|
23
|
+
deepEqual,
|
|
23
24
|
functionalUpdate,
|
|
24
25
|
} from './utils'
|
|
25
26
|
|
|
@@ -352,6 +353,12 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
|
|
|
352
353
|
: never
|
|
353
354
|
: never
|
|
354
355
|
|
|
356
|
+
type LinkCurrentTargetElement = {
|
|
357
|
+
preloadTimeout?: null | ReturnType<typeof setTimeout>
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const preloadWarning = 'Error preloading route! ☝️'
|
|
361
|
+
|
|
355
362
|
export function useLinkProps<
|
|
356
363
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
357
364
|
TFrom extends RoutePaths<TRouteTree> = '/',
|
|
@@ -361,7 +368,7 @@ export function useLinkProps<
|
|
|
361
368
|
>(
|
|
362
369
|
options: MakeLinkPropsOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
|
|
363
370
|
): React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
364
|
-
const
|
|
371
|
+
const router = useRouter()
|
|
365
372
|
const matchPathname = useMatch({
|
|
366
373
|
strict: false,
|
|
367
374
|
select: (s) => s.pathname,
|
|
@@ -369,7 +376,6 @@ export function useLinkProps<
|
|
|
369
376
|
|
|
370
377
|
const {
|
|
371
378
|
// custom props
|
|
372
|
-
type,
|
|
373
379
|
children,
|
|
374
380
|
target,
|
|
375
381
|
activeProps = () => ({ className: 'active' }),
|
|
@@ -382,8 +388,8 @@ export function useLinkProps<
|
|
|
382
388
|
to,
|
|
383
389
|
state,
|
|
384
390
|
mask,
|
|
385
|
-
preload,
|
|
386
|
-
preloadDelay,
|
|
391
|
+
preload: userPreload,
|
|
392
|
+
preloadDelay: userPreloadDelay,
|
|
387
393
|
replace,
|
|
388
394
|
startTransition,
|
|
389
395
|
resetScroll,
|
|
@@ -398,25 +404,122 @@ export function useLinkProps<
|
|
|
398
404
|
...rest
|
|
399
405
|
} = options
|
|
400
406
|
|
|
401
|
-
|
|
407
|
+
// If this link simply reloads the current route,
|
|
408
|
+
// make sure it has a new key so it will trigger a data refresh
|
|
409
|
+
|
|
410
|
+
// If this `to` is a valid external URL, return
|
|
411
|
+
// null for LinkUtils
|
|
412
|
+
|
|
413
|
+
const dest = {
|
|
402
414
|
from: options.to ? matchPathname : undefined,
|
|
403
415
|
...options,
|
|
404
|
-
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
let type: 'internal' | 'external' = 'internal'
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
new URL(`${to}`)
|
|
422
|
+
type = 'external'
|
|
423
|
+
} catch {}
|
|
405
424
|
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
|
|
425
|
+
if (type === 'external') {
|
|
426
|
+
return {
|
|
427
|
+
href: to,
|
|
428
|
+
}
|
|
409
429
|
}
|
|
410
430
|
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
431
|
+
const next = router.buildLocation(dest as any)
|
|
432
|
+
|
|
433
|
+
const preload = userPreload ?? router.options.defaultPreload
|
|
434
|
+
const preloadDelay =
|
|
435
|
+
userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0
|
|
436
|
+
|
|
437
|
+
const isActive = useRouterState({
|
|
438
|
+
select: (s) => {
|
|
439
|
+
// Compare path/hash for matches
|
|
440
|
+
const currentPathSplit = s.location.pathname.split('/')
|
|
441
|
+
const nextPathSplit = next.pathname.split('/')
|
|
442
|
+
const pathIsFuzzyEqual = nextPathSplit.every(
|
|
443
|
+
(d, i) => d === currentPathSplit[i],
|
|
444
|
+
)
|
|
445
|
+
// Combine the matches based on user router.options
|
|
446
|
+
const pathTest = activeOptions?.exact
|
|
447
|
+
? s.location.pathname === next.pathname
|
|
448
|
+
: pathIsFuzzyEqual
|
|
449
|
+
const hashTest = activeOptions?.includeHash
|
|
450
|
+
? s.location.hash === next.hash
|
|
451
|
+
: true
|
|
452
|
+
const searchTest =
|
|
453
|
+
activeOptions?.includeSearch ?? true
|
|
454
|
+
? deepEqual(s.location.search, next.search, true)
|
|
455
|
+
: true
|
|
456
|
+
|
|
457
|
+
// The final "active" test
|
|
458
|
+
return pathTest && hashTest && searchTest
|
|
459
|
+
},
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
// The click handler
|
|
463
|
+
const handleClick = (e: MouseEvent) => {
|
|
464
|
+
if (
|
|
465
|
+
!disabled &&
|
|
466
|
+
!isCtrlEvent(e) &&
|
|
467
|
+
!e.defaultPrevented &&
|
|
468
|
+
(!target || target === '_self') &&
|
|
469
|
+
e.button === 0
|
|
470
|
+
) {
|
|
471
|
+
e.preventDefault()
|
|
472
|
+
|
|
473
|
+
// All is well? Navigate!
|
|
474
|
+
router.commitLocation({ ...next, replace, resetScroll, startTransition })
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// The click handler
|
|
479
|
+
const handleFocus = (e: MouseEvent) => {
|
|
480
|
+
if (preload) {
|
|
481
|
+
router.preloadRoute(dest as any).catch((err) => {
|
|
482
|
+
console.warn(err)
|
|
483
|
+
console.warn(preloadWarning)
|
|
484
|
+
})
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const handleTouchStart = (e: TouchEvent) => {
|
|
489
|
+
if (preload) {
|
|
490
|
+
router.preloadRoute(dest as any).catch((err) => {
|
|
491
|
+
console.warn(err)
|
|
492
|
+
console.warn(preloadWarning)
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const handleEnter = (e: MouseEvent) => {
|
|
498
|
+
const target = (e.target || {}) as LinkCurrentTargetElement
|
|
499
|
+
|
|
500
|
+
if (preload) {
|
|
501
|
+
if (target.preloadTimeout) {
|
|
502
|
+
return
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
target.preloadTimeout = setTimeout(() => {
|
|
506
|
+
target.preloadTimeout = null
|
|
507
|
+
router.preloadRoute(dest as any).catch((err) => {
|
|
508
|
+
console.warn(err)
|
|
509
|
+
console.warn(preloadWarning)
|
|
510
|
+
})
|
|
511
|
+
}, preloadDelay)
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const handleLeave = (e: MouseEvent) => {
|
|
516
|
+
const target = (e.target || {}) as LinkCurrentTargetElement
|
|
517
|
+
|
|
518
|
+
if (target.preloadTimeout) {
|
|
519
|
+
clearTimeout(target.preloadTimeout)
|
|
520
|
+
target.preloadTimeout = null
|
|
521
|
+
}
|
|
522
|
+
}
|
|
420
523
|
|
|
421
524
|
const composeHandlers =
|
|
422
525
|
(handlers: (undefined | ((e: any) => void))[]) =>
|
|
@@ -507,3 +610,7 @@ export const Link: LinkComponent = React.forwardRef((props: any, ref) => {
|
|
|
507
610
|
/>
|
|
508
611
|
)
|
|
509
612
|
}) as any
|
|
613
|
+
|
|
614
|
+
function isCtrlEvent(e: MouseEvent) {
|
|
615
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)
|
|
616
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -218,12 +218,6 @@ export type RouterListener<TRouterEvent extends RouterEvent> = {
|
|
|
218
218
|
fn: ListenerFn<TRouterEvent>
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
type LinkCurrentTargetElement = {
|
|
222
|
-
preloadTimeout?: null | ReturnType<typeof setTimeout>
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const preloadWarning = 'Error preloading route! ☝️'
|
|
226
|
-
|
|
227
221
|
export class Router<
|
|
228
222
|
TRouteTree extends AnyRoute = AnyRoute,
|
|
229
223
|
TDehydrated extends Record<string, any> = Record<string, any>,
|
|
@@ -1437,136 +1431,6 @@ export class Router<
|
|
|
1437
1431
|
return matches
|
|
1438
1432
|
}
|
|
1439
1433
|
|
|
1440
|
-
buildLink: BuildLinkFn<TRouteTree> = (dest) => {
|
|
1441
|
-
// If this link simply reloads the current route,
|
|
1442
|
-
// make sure it has a new key so it will trigger a data refresh
|
|
1443
|
-
|
|
1444
|
-
// If this `to` is a valid external URL, return
|
|
1445
|
-
// null for LinkUtils
|
|
1446
|
-
|
|
1447
|
-
const {
|
|
1448
|
-
to,
|
|
1449
|
-
preload: userPreload,
|
|
1450
|
-
preloadDelay: userPreloadDelay,
|
|
1451
|
-
activeOptions,
|
|
1452
|
-
disabled,
|
|
1453
|
-
target,
|
|
1454
|
-
replace,
|
|
1455
|
-
resetScroll,
|
|
1456
|
-
startTransition,
|
|
1457
|
-
} = dest
|
|
1458
|
-
|
|
1459
|
-
try {
|
|
1460
|
-
new URL(`${to}`)
|
|
1461
|
-
return {
|
|
1462
|
-
type: 'external',
|
|
1463
|
-
href: to as any,
|
|
1464
|
-
}
|
|
1465
|
-
} catch (e) {}
|
|
1466
|
-
|
|
1467
|
-
const nextOpts = dest
|
|
1468
|
-
const next = this.buildLocation(nextOpts as any)
|
|
1469
|
-
|
|
1470
|
-
const preload = userPreload ?? this.options.defaultPreload
|
|
1471
|
-
const preloadDelay =
|
|
1472
|
-
userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0
|
|
1473
|
-
|
|
1474
|
-
// Compare path/hash for matches
|
|
1475
|
-
const currentPathSplit = this.latestLocation.pathname.split('/')
|
|
1476
|
-
const nextPathSplit = next.pathname.split('/')
|
|
1477
|
-
const pathIsFuzzyEqual = nextPathSplit.every(
|
|
1478
|
-
(d, i) => d === currentPathSplit[i],
|
|
1479
|
-
)
|
|
1480
|
-
// Combine the matches based on user this.options
|
|
1481
|
-
const pathTest = activeOptions?.exact
|
|
1482
|
-
? this.latestLocation.pathname === next.pathname
|
|
1483
|
-
: pathIsFuzzyEqual
|
|
1484
|
-
const hashTest = activeOptions?.includeHash
|
|
1485
|
-
? this.latestLocation.hash === next.hash
|
|
1486
|
-
: true
|
|
1487
|
-
const searchTest =
|
|
1488
|
-
activeOptions?.includeSearch ?? true
|
|
1489
|
-
? deepEqual(this.latestLocation.search, next.search, true)
|
|
1490
|
-
: true
|
|
1491
|
-
|
|
1492
|
-
// The final "active" test
|
|
1493
|
-
const isActive = pathTest && hashTest && searchTest
|
|
1494
|
-
|
|
1495
|
-
// The click handler
|
|
1496
|
-
const handleClick = (e: MouseEvent) => {
|
|
1497
|
-
if (
|
|
1498
|
-
!disabled &&
|
|
1499
|
-
!isCtrlEvent(e) &&
|
|
1500
|
-
!e.defaultPrevented &&
|
|
1501
|
-
(!target || target === '_self') &&
|
|
1502
|
-
e.button === 0
|
|
1503
|
-
) {
|
|
1504
|
-
e.preventDefault()
|
|
1505
|
-
|
|
1506
|
-
// All is well? Navigate!
|
|
1507
|
-
this.commitLocation({ ...next, replace, resetScroll, startTransition })
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
// The click handler
|
|
1512
|
-
const handleFocus = (e: MouseEvent) => {
|
|
1513
|
-
if (preload) {
|
|
1514
|
-
this.preloadRoute(nextOpts as any).catch((err) => {
|
|
1515
|
-
console.warn(err)
|
|
1516
|
-
console.warn(preloadWarning)
|
|
1517
|
-
})
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
const handleTouchStart = (e: TouchEvent) => {
|
|
1522
|
-
if (preload) {
|
|
1523
|
-
this.preloadRoute(nextOpts as any).catch((err) => {
|
|
1524
|
-
console.warn(err)
|
|
1525
|
-
console.warn(preloadWarning)
|
|
1526
|
-
})
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
const handleEnter = (e: MouseEvent) => {
|
|
1531
|
-
const target = (e.target || {}) as LinkCurrentTargetElement
|
|
1532
|
-
|
|
1533
|
-
if (preload) {
|
|
1534
|
-
if (target.preloadTimeout) {
|
|
1535
|
-
return
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1538
|
-
target.preloadTimeout = setTimeout(() => {
|
|
1539
|
-
target.preloadTimeout = null
|
|
1540
|
-
this.preloadRoute(nextOpts as any).catch((err) => {
|
|
1541
|
-
console.warn(err)
|
|
1542
|
-
console.warn(preloadWarning)
|
|
1543
|
-
})
|
|
1544
|
-
}, preloadDelay)
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
const handleLeave = (e: MouseEvent) => {
|
|
1549
|
-
const target = (e.target || {}) as LinkCurrentTargetElement
|
|
1550
|
-
|
|
1551
|
-
if (target.preloadTimeout) {
|
|
1552
|
-
clearTimeout(target.preloadTimeout)
|
|
1553
|
-
target.preloadTimeout = null
|
|
1554
|
-
}
|
|
1555
|
-
}
|
|
1556
|
-
|
|
1557
|
-
return {
|
|
1558
|
-
type: 'internal',
|
|
1559
|
-
next,
|
|
1560
|
-
handleFocus,
|
|
1561
|
-
handleClick,
|
|
1562
|
-
handleEnter,
|
|
1563
|
-
handleLeave,
|
|
1564
|
-
handleTouchStart,
|
|
1565
|
-
isActive,
|
|
1566
|
-
disabled,
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
1434
|
matchRoute: MatchRouteFn<TRouteTree> = (location, opts) => {
|
|
1571
1435
|
location = {
|
|
1572
1436
|
...location,
|
|
@@ -1727,9 +1591,6 @@ export function lazyFn<
|
|
|
1727
1591
|
}
|
|
1728
1592
|
}
|
|
1729
1593
|
|
|
1730
|
-
function isCtrlEvent(e: MouseEvent) {
|
|
1731
|
-
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)
|
|
1732
|
-
}
|
|
1733
1594
|
export class SearchParamError extends Error {}
|
|
1734
1595
|
|
|
1735
1596
|
export class PathParamError extends Error {}
|