@tanstack/vue-router 0.0.1 → 1.140.0
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/LICENSE +21 -0
- package/README.md +66 -45
- package/dist/esm/Asset.d.ts +2 -0
- package/dist/esm/Asset.js +33 -0
- package/dist/esm/Asset.js.map +1 -0
- package/dist/esm/CatchBoundary.d.ts +19 -0
- package/dist/esm/CatchBoundary.js +135 -0
- package/dist/esm/CatchBoundary.js.map +1 -0
- package/dist/esm/ClientOnly.d.ts +67 -0
- package/dist/esm/HeadContent.d.ts +10 -0
- package/dist/esm/HeadContent.js +116 -0
- package/dist/esm/HeadContent.js.map +1 -0
- package/dist/esm/Match.d.ts +25 -0
- package/dist/esm/Match.js +262 -0
- package/dist/esm/Match.js.map +1 -0
- package/dist/esm/Matches.d.ts +39 -0
- package/dist/esm/Matches.js +186 -0
- package/dist/esm/Matches.js.map +1 -0
- package/dist/esm/RouterProvider.d.ts +33 -0
- package/dist/esm/RouterProvider.js +65 -0
- package/dist/esm/RouterProvider.js.map +1 -0
- package/dist/esm/SafeFragment.d.ts +4 -0
- package/dist/esm/ScriptOnce.d.ts +5 -0
- package/dist/esm/ScriptOnce.js +21 -0
- package/dist/esm/ScriptOnce.js.map +1 -0
- package/dist/esm/Scripts.d.ts +1 -0
- package/dist/esm/Scripts.js +46 -0
- package/dist/esm/Scripts.js.map +1 -0
- package/dist/esm/ScrollRestoration.d.ts +14 -0
- package/dist/esm/ScrollRestoration.js +36 -0
- package/dist/esm/ScrollRestoration.js.map +1 -0
- package/dist/esm/Transitioner.d.ts +2 -0
- package/dist/esm/Transitioner.js +154 -0
- package/dist/esm/Transitioner.js.map +1 -0
- package/dist/esm/awaited.d.ts +12 -0
- package/dist/esm/awaited.js +40 -0
- package/dist/esm/awaited.js.map +1 -0
- package/dist/esm/fileRoute.d.ts +54 -0
- package/dist/esm/fileRoute.js +103 -0
- package/dist/esm/fileRoute.js.map +1 -0
- package/dist/esm/history.d.ts +8 -0
- package/dist/esm/index.d.ts +51 -0
- package/dist/esm/index.js +138 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lazyRouteComponent.d.ts +8 -0
- package/dist/esm/lazyRouteComponent.js +106 -0
- package/dist/esm/lazyRouteComponent.js.map +1 -0
- package/dist/esm/link.d.ts +61 -0
- package/dist/esm/link.js +376 -0
- package/dist/esm/link.js.map +1 -0
- package/dist/esm/matchContext.d.ts +20 -0
- package/dist/esm/matchContext.js +16 -0
- package/dist/esm/matchContext.js.map +1 -0
- package/dist/esm/not-found.d.ts +12 -0
- package/dist/esm/not-found.js +45 -0
- package/dist/esm/not-found.js.map +1 -0
- package/dist/esm/renderRouteNotFound.d.ts +11 -0
- package/dist/esm/renderRouteNotFound.js +19 -0
- package/dist/esm/renderRouteNotFound.js.map +1 -0
- package/dist/esm/route.d.ts +96 -0
- package/dist/esm/route.js +176 -0
- package/dist/esm/route.js.map +1 -0
- package/dist/esm/router.d.ts +69 -0
- package/dist/esm/router.js +14 -0
- package/dist/esm/router.js.map +1 -0
- package/dist/esm/routerContext.d.ts +21 -0
- package/dist/esm/routerContext.js +21 -0
- package/dist/esm/routerContext.js.map +1 -0
- package/dist/esm/scroll-restoration.d.ts +1 -0
- package/dist/esm/scroll-restoration.js +21 -0
- package/dist/esm/scroll-restoration.js.map +1 -0
- package/dist/esm/typePrimitives.d.ts +10 -0
- package/dist/esm/useBlocker.d.ts +66 -0
- package/dist/esm/useBlocker.js +295 -0
- package/dist/esm/useBlocker.js.map +1 -0
- package/dist/esm/useCanGoBack.d.ts +1 -0
- package/dist/esm/useCanGoBack.js +8 -0
- package/dist/esm/useCanGoBack.js.map +1 -0
- package/dist/esm/useLoaderData.d.ts +8 -0
- package/dist/esm/useLoaderData.js +14 -0
- package/dist/esm/useLoaderData.js.map +1 -0
- package/dist/esm/useLoaderDeps.d.ts +7 -0
- package/dist/esm/useLoaderDeps.js +17 -0
- package/dist/esm/useLoaderDeps.js.map +1 -0
- package/dist/esm/useLocation.d.ts +7 -0
- package/dist/esm/useLocation.js +10 -0
- package/dist/esm/useLocation.js.map +1 -0
- package/dist/esm/useMatch.d.ts +10 -0
- package/dist/esm/useMatch.js +39 -0
- package/dist/esm/useMatch.js.map +1 -0
- package/dist/esm/useNavigate.d.ts +5 -0
- package/dist/esm/useNavigate.js +29 -0
- package/dist/esm/useNavigate.js.map +1 -0
- package/dist/esm/useParams.d.ts +9 -0
- package/dist/esm/useParams.js +15 -0
- package/dist/esm/useParams.js.map +1 -0
- package/dist/esm/useRouteContext.d.ts +4 -0
- package/dist/esm/useRouteContext.js +11 -0
- package/dist/esm/useRouteContext.js.map +1 -0
- package/dist/esm/useRouter.d.ts +4 -0
- package/dist/esm/useRouter.js +12 -0
- package/dist/esm/useRouter.js.map +1 -0
- package/dist/esm/useRouterState.d.ts +8 -0
- package/dist/esm/useRouterState.js +20 -0
- package/dist/esm/useRouterState.js.map +1 -0
- package/dist/esm/useSearch.d.ts +9 -0
- package/dist/esm/useSearch.js +15 -0
- package/dist/esm/useSearch.js.map +1 -0
- package/dist/esm/utils.d.ts +40 -0
- package/dist/esm/utils.js +44 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/source/Asset.d.ts +2 -0
- package/dist/source/Asset.jsx +22 -0
- package/dist/source/Asset.jsx.map +1 -0
- package/dist/source/CatchBoundary.d.ts +19 -0
- package/dist/source/CatchBoundary.jsx +134 -0
- package/dist/source/CatchBoundary.jsx.map +1 -0
- package/dist/source/ClientOnly.d.ts +67 -0
- package/dist/source/ClientOnly.jsx +63 -0
- package/dist/source/ClientOnly.jsx.map +1 -0
- package/dist/source/HeadContent.d.ts +10 -0
- package/dist/source/HeadContent.jsx +133 -0
- package/dist/source/HeadContent.jsx.map +1 -0
- package/dist/source/Match.d.ts +25 -0
- package/dist/source/Match.jsx +316 -0
- package/dist/source/Match.jsx.map +1 -0
- package/dist/source/Matches.d.ts +39 -0
- package/dist/source/Matches.jsx +191 -0
- package/dist/source/Matches.jsx.map +1 -0
- package/dist/source/RouterProvider.d.ts +33 -0
- package/dist/source/RouterProvider.jsx +63 -0
- package/dist/source/RouterProvider.jsx.map +1 -0
- package/dist/source/SafeFragment.d.ts +4 -0
- package/dist/source/SafeFragment.jsx +10 -0
- package/dist/source/SafeFragment.jsx.map +1 -0
- package/dist/source/ScriptOnce.d.ts +5 -0
- package/dist/source/ScriptOnce.jsx +17 -0
- package/dist/source/ScriptOnce.jsx.map +1 -0
- package/dist/source/Scripts.d.ts +1 -0
- package/dist/source/Scripts.jsx +49 -0
- package/dist/source/Scripts.jsx.map +1 -0
- package/dist/source/ScrollRestoration.d.ts +14 -0
- package/dist/source/ScrollRestoration.jsx +37 -0
- package/dist/source/ScrollRestoration.jsx.map +1 -0
- package/dist/source/Transitioner.d.ts +2 -0
- package/dist/source/Transitioner.jsx +181 -0
- package/dist/source/Transitioner.jsx.map +1 -0
- package/dist/source/awaited.d.ts +12 -0
- package/dist/source/awaited.jsx +38 -0
- package/dist/source/awaited.jsx.map +1 -0
- package/dist/source/fileRoute.d.ts +54 -0
- package/dist/source/fileRoute.js +98 -0
- package/dist/source/fileRoute.js.map +1 -0
- package/dist/source/history.d.ts +8 -0
- package/dist/source/history.js +2 -0
- package/dist/source/history.js.map +1 -0
- package/dist/source/index.d.ts +51 -0
- package/dist/source/index.jsx +40 -0
- package/dist/source/index.jsx.map +1 -0
- package/dist/source/lazyRouteComponent.d.ts +8 -0
- package/dist/source/lazyRouteComponent.jsx +135 -0
- package/dist/source/lazyRouteComponent.jsx.map +1 -0
- package/dist/source/link.d.ts +61 -0
- package/dist/source/link.jsx +495 -0
- package/dist/source/link.jsx.map +1 -0
- package/dist/source/matchContext.d.ts +20 -0
- package/dist/source/matchContext.jsx +32 -0
- package/dist/source/matchContext.jsx.map +1 -0
- package/dist/source/not-found.d.ts +12 -0
- package/dist/source/not-found.jsx +48 -0
- package/dist/source/not-found.jsx.map +1 -0
- package/dist/source/renderRouteNotFound.d.ts +11 -0
- package/dist/source/renderRouteNotFound.jsx +24 -0
- package/dist/source/renderRouteNotFound.jsx.map +1 -0
- package/dist/source/route.d.ts +97 -0
- package/dist/source/route.js +167 -0
- package/dist/source/route.js.map +1 -0
- package/dist/source/router.d.ts +70 -0
- package/dist/source/router.js +10 -0
- package/dist/source/router.js.map +1 -0
- package/dist/source/routerContext.d.ts +21 -0
- package/dist/source/routerContext.jsx +37 -0
- package/dist/source/routerContext.jsx.map +1 -0
- package/dist/source/scroll-restoration.d.ts +1 -0
- package/dist/source/scroll-restoration.jsx +16 -0
- package/dist/source/scroll-restoration.jsx.map +1 -0
- package/dist/source/typePrimitives.d.ts +10 -0
- package/dist/source/typePrimitives.js +2 -0
- package/dist/source/typePrimitives.js.map +1 -0
- package/dist/source/useBlocker.d.ts +66 -0
- package/dist/source/useBlocker.jsx +308 -0
- package/dist/source/useBlocker.jsx.map +1 -0
- package/dist/source/useCanGoBack.d.ts +1 -0
- package/dist/source/useCanGoBack.js +5 -0
- package/dist/source/useCanGoBack.js.map +1 -0
- package/dist/source/useLoaderData.d.ts +8 -0
- package/dist/source/useLoaderData.jsx +11 -0
- package/dist/source/useLoaderData.jsx.map +1 -0
- package/dist/source/useLoaderDeps.d.ts +7 -0
- package/dist/source/useLoaderDeps.jsx +11 -0
- package/dist/source/useLoaderDeps.jsx.map +1 -0
- package/dist/source/useLocation.d.ts +7 -0
- package/dist/source/useLocation.jsx +7 -0
- package/dist/source/useLocation.jsx.map +1 -0
- package/dist/source/useMatch.d.ts +10 -0
- package/dist/source/useMatch.jsx +46 -0
- package/dist/source/useMatch.jsx.map +1 -0
- package/dist/source/useNavigate.d.ts +5 -0
- package/dist/source/useNavigate.jsx +18 -0
- package/dist/source/useNavigate.jsx.map +1 -0
- package/dist/source/useParams.d.ts +9 -0
- package/dist/source/useParams.jsx +12 -0
- package/dist/source/useParams.jsx.map +1 -0
- package/dist/source/useRouteContext.d.ts +4 -0
- package/dist/source/useRouteContext.js +8 -0
- package/dist/source/useRouteContext.js.map +1 -0
- package/dist/source/useRouter.d.ts +4 -0
- package/dist/source/useRouter.jsx +9 -0
- package/dist/source/useRouter.jsx.map +1 -0
- package/dist/source/useRouterState.d.ts +8 -0
- package/dist/source/useRouterState.jsx +19 -0
- package/dist/source/useRouterState.jsx.map +1 -0
- package/dist/source/useSearch.d.ts +9 -0
- package/dist/source/useSearch.jsx +12 -0
- package/dist/source/useSearch.jsx.map +1 -0
- package/dist/source/utils.d.ts +40 -0
- package/dist/source/utils.js +78 -0
- package/dist/source/utils.js.map +1 -0
- package/package.json +77 -7
- package/src/Asset.tsx +23 -0
- package/src/CatchBoundary.tsx +186 -0
- package/src/ClientOnly.tsx +75 -0
- package/src/HeadContent.tsx +159 -0
- package/src/Match.tsx +415 -0
- package/src/Matches.tsx +349 -0
- package/src/RouterProvider.tsx +117 -0
- package/src/SafeFragment.tsx +10 -0
- package/src/ScriptOnce.tsx +30 -0
- package/src/Scripts.tsx +65 -0
- package/src/ScrollRestoration.tsx +69 -0
- package/src/Transitioner.tsx +213 -0
- package/src/awaited.tsx +54 -0
- package/src/fileRoute.ts +271 -0
- package/src/history.ts +9 -0
- package/src/index.tsx +346 -0
- package/src/lazyRouteComponent.tsx +173 -0
- package/src/link.tsx +765 -0
- package/src/matchContext.tsx +41 -0
- package/src/not-found.tsx +55 -0
- package/src/renderRouteNotFound.tsx +35 -0
- package/src/route.ts +658 -0
- package/src/router.ts +103 -0
- package/src/routerContext.tsx +53 -0
- package/src/scroll-restoration.tsx +29 -0
- package/src/typePrimitives.ts +74 -0
- package/src/useBlocker.tsx +501 -0
- package/src/useCanGoBack.ts +5 -0
- package/src/useLoaderData.tsx +50 -0
- package/src/useLoaderDeps.tsx +46 -0
- package/src/useLocation.tsx +30 -0
- package/src/useMatch.tsx +127 -0
- package/src/useNavigate.tsx +40 -0
- package/src/useParams.tsx +71 -0
- package/src/useRouteContext.ts +31 -0
- package/src/useRouter.tsx +15 -0
- package/src/useRouterState.tsx +43 -0
- package/src/useSearch.tsx +71 -0
- package/src/utils.ts +111 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import * as Vue from 'vue'
|
|
2
|
+
import {
|
|
3
|
+
getLocationChangeInfo,
|
|
4
|
+
handleHashScroll,
|
|
5
|
+
trimPathRight,
|
|
6
|
+
} from '@tanstack/router-core'
|
|
7
|
+
import { useRouter } from './useRouter'
|
|
8
|
+
import { useRouterState } from './useRouterState'
|
|
9
|
+
import { usePrevious } from './utils'
|
|
10
|
+
|
|
11
|
+
export const Transitioner = Vue.defineComponent({
|
|
12
|
+
name: 'Transitioner',
|
|
13
|
+
setup() {
|
|
14
|
+
const router = useRouter()
|
|
15
|
+
let mountLoadForRouter = { router, mounted: false }
|
|
16
|
+
|
|
17
|
+
if (router.isServer) {
|
|
18
|
+
return () => null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const isLoading = useRouterState({
|
|
22
|
+
select: ({ isLoading }) => isLoading,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// Track if we're in a transition - using a ref to track async transitions
|
|
26
|
+
const isTransitioning = Vue.ref(false)
|
|
27
|
+
|
|
28
|
+
// Track pending state changes
|
|
29
|
+
const hasPendingMatches = useRouterState({
|
|
30
|
+
select: (s) => s.matches.some((d) => d.status === 'pending'),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const previousIsLoading = usePrevious(() => isLoading.value)
|
|
34
|
+
|
|
35
|
+
const isAnyPending = Vue.computed(
|
|
36
|
+
() => isLoading.value || isTransitioning.value || hasPendingMatches.value,
|
|
37
|
+
)
|
|
38
|
+
const previousIsAnyPending = usePrevious(() => isAnyPending.value)
|
|
39
|
+
|
|
40
|
+
const isPagePending = Vue.computed(
|
|
41
|
+
() => isLoading.value || hasPendingMatches.value,
|
|
42
|
+
)
|
|
43
|
+
const previousIsPagePending = usePrevious(() => isPagePending.value)
|
|
44
|
+
|
|
45
|
+
// Implement startTransition similar to React/Solid
|
|
46
|
+
// Vue doesn't have a native useTransition like React 18, so we simulate it
|
|
47
|
+
// We also update the router state's isTransitioning flag so useMatch can check it
|
|
48
|
+
router.startTransition = (fn: () => void | Promise<void>) => {
|
|
49
|
+
isTransitioning.value = true
|
|
50
|
+
// Also update the router state so useMatch knows we're transitioning
|
|
51
|
+
try {
|
|
52
|
+
router.__store.setState((s) => ({ ...s, isTransitioning: true }))
|
|
53
|
+
} catch {
|
|
54
|
+
// Ignore errors if component is unmounted
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Helper to end the transition
|
|
58
|
+
const endTransition = () => {
|
|
59
|
+
// Use nextTick to ensure Vue has processed all reactive updates
|
|
60
|
+
Vue.nextTick(() => {
|
|
61
|
+
try {
|
|
62
|
+
isTransitioning.value = false
|
|
63
|
+
router.__store.setState((s) => ({ ...s, isTransitioning: false }))
|
|
64
|
+
} catch {
|
|
65
|
+
// Ignore errors if component is unmounted
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Execute the function synchronously
|
|
71
|
+
// The function internally may call startViewTransition which schedules async work
|
|
72
|
+
// via document.startViewTransition, but we don't need to wait for it here
|
|
73
|
+
// because Vue's reactivity will trigger re-renders when state changes
|
|
74
|
+
fn()
|
|
75
|
+
|
|
76
|
+
// End the transition on next tick to allow Vue to process reactive updates
|
|
77
|
+
endTransition()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// For Vue, we need to completely override startViewTransition because Vue's
|
|
81
|
+
// async rendering doesn't work well with the View Transitions API's requirement
|
|
82
|
+
// for synchronous DOM updates. The browser expects the DOM to be updated
|
|
83
|
+
// when the callback promise resolves, but Vue updates asynchronously.
|
|
84
|
+
//
|
|
85
|
+
// Our approach: Skip the actual view transition animation but still update state.
|
|
86
|
+
// This ensures navigation works correctly even without the visual transition.
|
|
87
|
+
// In the future, we could explore using viewTransition.captured like vue-view-transitions does.
|
|
88
|
+
router.startViewTransition = (fn: () => Promise<void>) => {
|
|
89
|
+
// Just run the callback directly without wrapping in document.startViewTransition
|
|
90
|
+
// This ensures the state updates happen and Vue can render them normally
|
|
91
|
+
fn()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Subscribe to location changes
|
|
95
|
+
// and try to load the new location
|
|
96
|
+
let unsubscribe: (() => void) | undefined
|
|
97
|
+
|
|
98
|
+
Vue.onMounted(() => {
|
|
99
|
+
unsubscribe = router.history.subscribe(router.load)
|
|
100
|
+
|
|
101
|
+
const nextLocation = router.buildLocation({
|
|
102
|
+
to: router.latestLocation.pathname,
|
|
103
|
+
search: true,
|
|
104
|
+
params: true,
|
|
105
|
+
hash: true,
|
|
106
|
+
state: true,
|
|
107
|
+
_includeValidateSearch: true,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
if (
|
|
111
|
+
trimPathRight(router.latestLocation.href) !==
|
|
112
|
+
trimPathRight(nextLocation.href)
|
|
113
|
+
) {
|
|
114
|
+
router.commitLocation({ ...nextLocation, replace: true })
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Track if component is mounted to prevent updates after unmount
|
|
119
|
+
const isMounted = Vue.ref(false)
|
|
120
|
+
|
|
121
|
+
Vue.onMounted(() => {
|
|
122
|
+
isMounted.value = true
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
Vue.onUnmounted(() => {
|
|
126
|
+
isMounted.value = false
|
|
127
|
+
if (unsubscribe) {
|
|
128
|
+
unsubscribe()
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
// Try to load the initial location
|
|
133
|
+
Vue.onMounted(() => {
|
|
134
|
+
if (
|
|
135
|
+
(typeof window !== 'undefined' && router.ssr) ||
|
|
136
|
+
(mountLoadForRouter.router === router && mountLoadForRouter.mounted)
|
|
137
|
+
) {
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
mountLoadForRouter = { router, mounted: true }
|
|
141
|
+
const tryLoad = async () => {
|
|
142
|
+
try {
|
|
143
|
+
await router.load()
|
|
144
|
+
} catch (err) {
|
|
145
|
+
console.error(err)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
tryLoad()
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// Setup watchers for emitting events
|
|
152
|
+
// All watchers check isMounted to prevent updates after unmount
|
|
153
|
+
Vue.watch(
|
|
154
|
+
() => isLoading.value,
|
|
155
|
+
(newValue) => {
|
|
156
|
+
if (!isMounted.value) return
|
|
157
|
+
try {
|
|
158
|
+
if (previousIsLoading.value.previous && !newValue) {
|
|
159
|
+
router.emit({
|
|
160
|
+
type: 'onLoad',
|
|
161
|
+
...getLocationChangeInfo(router.state),
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
} catch {
|
|
165
|
+
// Ignore errors if component is unmounted
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
Vue.watch(isPagePending, (newValue) => {
|
|
171
|
+
if (!isMounted.value) return
|
|
172
|
+
try {
|
|
173
|
+
// emit onBeforeRouteMount
|
|
174
|
+
if (previousIsPagePending.value.previous && !newValue) {
|
|
175
|
+
router.emit({
|
|
176
|
+
type: 'onBeforeRouteMount',
|
|
177
|
+
...getLocationChangeInfo(router.state),
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
// Ignore errors if component is unmounted
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
Vue.watch(isAnyPending, (newValue) => {
|
|
186
|
+
if (!isMounted.value) return
|
|
187
|
+
try {
|
|
188
|
+
// The router was pending and now it's not
|
|
189
|
+
if (previousIsAnyPending.value.previous && !newValue) {
|
|
190
|
+
const changeInfo = getLocationChangeInfo(router.state)
|
|
191
|
+
router.emit({
|
|
192
|
+
type: 'onResolved',
|
|
193
|
+
...changeInfo,
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
router.__store.setState((s) => ({
|
|
197
|
+
...s,
|
|
198
|
+
status: 'idle',
|
|
199
|
+
resolvedLocation: s.location,
|
|
200
|
+
}))
|
|
201
|
+
|
|
202
|
+
if (changeInfo.hrefChanged) {
|
|
203
|
+
handleHashScroll(router)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} catch {
|
|
207
|
+
// Ignore errors if component is unmounted
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
return () => null
|
|
212
|
+
},
|
|
213
|
+
})
|
package/src/awaited.tsx
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as Vue from 'vue'
|
|
2
|
+
|
|
3
|
+
import { TSR_DEFERRED_PROMISE, defer } from '@tanstack/router-core'
|
|
4
|
+
import type { DeferredPromise } from '@tanstack/router-core'
|
|
5
|
+
|
|
6
|
+
export type AwaitOptions<T> = {
|
|
7
|
+
promise: Promise<T>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function useAwaited<T>({
|
|
11
|
+
promise: _promise,
|
|
12
|
+
}: AwaitOptions<T>): [T, DeferredPromise<T>] {
|
|
13
|
+
const promise = defer(_promise)
|
|
14
|
+
|
|
15
|
+
if (promise[TSR_DEFERRED_PROMISE].status === 'pending') {
|
|
16
|
+
throw promise
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (promise[TSR_DEFERRED_PROMISE].status === 'error') {
|
|
20
|
+
throw promise[TSR_DEFERRED_PROMISE].error
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return [promise[TSR_DEFERRED_PROMISE].data, promise]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function Await<T>(
|
|
27
|
+
props: AwaitOptions<T> & {
|
|
28
|
+
fallback?: Vue.VNode
|
|
29
|
+
children: (result: T) => Vue.VNode
|
|
30
|
+
},
|
|
31
|
+
) {
|
|
32
|
+
const data = Vue.ref<T | null>(null)
|
|
33
|
+
const error = Vue.ref<Error | null>(null)
|
|
34
|
+
const pending = Vue.ref(true)
|
|
35
|
+
|
|
36
|
+
Vue.watchEffect(async () => {
|
|
37
|
+
pending.value = true
|
|
38
|
+
try {
|
|
39
|
+
data.value = await props.promise
|
|
40
|
+
} catch (err) {
|
|
41
|
+
error.value = err as Error
|
|
42
|
+
} finally {
|
|
43
|
+
pending.value = false
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const inner = Vue.computed(() => {
|
|
48
|
+
if (error.value) throw error.value
|
|
49
|
+
if (pending.value) return props.fallback
|
|
50
|
+
return props.children(data.value as T)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
return () => inner.value
|
|
54
|
+
}
|
package/src/fileRoute.ts
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import warning from 'tiny-warning'
|
|
2
|
+
import { createRoute } from './route'
|
|
3
|
+
|
|
4
|
+
import { useMatch } from './useMatch'
|
|
5
|
+
import { useLoaderDeps } from './useLoaderDeps'
|
|
6
|
+
import { useLoaderData } from './useLoaderData'
|
|
7
|
+
import { useSearch } from './useSearch'
|
|
8
|
+
import { useParams } from './useParams'
|
|
9
|
+
import { useNavigate } from './useNavigate'
|
|
10
|
+
import { useRouter } from './useRouter'
|
|
11
|
+
import type { UseParamsRoute } from './useParams'
|
|
12
|
+
import type { UseMatchRoute } from './useMatch'
|
|
13
|
+
import type { UseSearchRoute } from './useSearch'
|
|
14
|
+
import type {
|
|
15
|
+
AnyContext,
|
|
16
|
+
AnyRoute,
|
|
17
|
+
AnyRouter,
|
|
18
|
+
Constrain,
|
|
19
|
+
ConstrainLiteral,
|
|
20
|
+
FileBaseRouteOptions,
|
|
21
|
+
FileRoutesByPath,
|
|
22
|
+
LazyRouteOptions,
|
|
23
|
+
Register,
|
|
24
|
+
RegisteredRouter,
|
|
25
|
+
ResolveParams,
|
|
26
|
+
Route,
|
|
27
|
+
RouteById,
|
|
28
|
+
RouteConstraints,
|
|
29
|
+
RouteIds,
|
|
30
|
+
RouteLoaderFn,
|
|
31
|
+
UpdatableRouteOptions,
|
|
32
|
+
UseNavigateResult,
|
|
33
|
+
} from '@tanstack/router-core'
|
|
34
|
+
import type { UseLoaderDepsRoute } from './useLoaderDeps'
|
|
35
|
+
import type { UseLoaderDataRoute } from './useLoaderData'
|
|
36
|
+
import type { UseRouteContextRoute } from './useRouteContext'
|
|
37
|
+
|
|
38
|
+
export function createFileRoute<
|
|
39
|
+
TFilePath extends keyof FileRoutesByPath,
|
|
40
|
+
TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'],
|
|
41
|
+
TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'],
|
|
42
|
+
TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'],
|
|
43
|
+
TFullPath extends
|
|
44
|
+
RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath'],
|
|
45
|
+
>(
|
|
46
|
+
path?: TFilePath,
|
|
47
|
+
): FileRoute<TFilePath, TParentRoute, TId, TPath, TFullPath>['createRoute'] {
|
|
48
|
+
if (typeof path === 'object') {
|
|
49
|
+
return new FileRoute<TFilePath, TParentRoute, TId, TPath, TFullPath>(path, {
|
|
50
|
+
silent: true,
|
|
51
|
+
}).createRoute(path) as any
|
|
52
|
+
}
|
|
53
|
+
return new FileRoute<TFilePath, TParentRoute, TId, TPath, TFullPath>(path, {
|
|
54
|
+
silent: true,
|
|
55
|
+
}).createRoute
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
@deprecated It's no longer recommended to use the `FileRoute` class directly.
|
|
60
|
+
Instead, use `createFileRoute('/path/to/file')(options)` to create a file route.
|
|
61
|
+
*/
|
|
62
|
+
export class FileRoute<
|
|
63
|
+
TFilePath extends keyof FileRoutesByPath,
|
|
64
|
+
TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'],
|
|
65
|
+
TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'],
|
|
66
|
+
TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'],
|
|
67
|
+
TFullPath extends
|
|
68
|
+
RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath'],
|
|
69
|
+
> {
|
|
70
|
+
silent?: boolean
|
|
71
|
+
|
|
72
|
+
constructor(
|
|
73
|
+
public path?: TFilePath,
|
|
74
|
+
_opts?: { silent: boolean },
|
|
75
|
+
) {
|
|
76
|
+
this.silent = _opts?.silent
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
createRoute = <
|
|
80
|
+
TRegister = Register,
|
|
81
|
+
TSearchValidator = undefined,
|
|
82
|
+
TParams = ResolveParams<TPath>,
|
|
83
|
+
TRouteContextFn = AnyContext,
|
|
84
|
+
TBeforeLoadFn = AnyContext,
|
|
85
|
+
TLoaderDeps extends Record<string, any> = {},
|
|
86
|
+
TLoaderFn = undefined,
|
|
87
|
+
TChildren = unknown,
|
|
88
|
+
TSSR = unknown,
|
|
89
|
+
TMiddlewares = unknown,
|
|
90
|
+
THandlers = undefined,
|
|
91
|
+
>(
|
|
92
|
+
options?: FileBaseRouteOptions<
|
|
93
|
+
TRegister,
|
|
94
|
+
TParentRoute,
|
|
95
|
+
TId,
|
|
96
|
+
TPath,
|
|
97
|
+
TSearchValidator,
|
|
98
|
+
TParams,
|
|
99
|
+
TLoaderDeps,
|
|
100
|
+
TLoaderFn,
|
|
101
|
+
AnyContext,
|
|
102
|
+
TRouteContextFn,
|
|
103
|
+
TBeforeLoadFn,
|
|
104
|
+
AnyContext,
|
|
105
|
+
TSSR,
|
|
106
|
+
TMiddlewares,
|
|
107
|
+
THandlers
|
|
108
|
+
> &
|
|
109
|
+
UpdatableRouteOptions<
|
|
110
|
+
TParentRoute,
|
|
111
|
+
TId,
|
|
112
|
+
TFullPath,
|
|
113
|
+
TParams,
|
|
114
|
+
TSearchValidator,
|
|
115
|
+
TLoaderFn,
|
|
116
|
+
TLoaderDeps,
|
|
117
|
+
AnyContext,
|
|
118
|
+
TRouteContextFn,
|
|
119
|
+
TBeforeLoadFn
|
|
120
|
+
>,
|
|
121
|
+
): Route<
|
|
122
|
+
TRegister,
|
|
123
|
+
TParentRoute,
|
|
124
|
+
TPath,
|
|
125
|
+
TFullPath,
|
|
126
|
+
TFilePath,
|
|
127
|
+
TId,
|
|
128
|
+
TSearchValidator,
|
|
129
|
+
TParams,
|
|
130
|
+
AnyContext,
|
|
131
|
+
TRouteContextFn,
|
|
132
|
+
TBeforeLoadFn,
|
|
133
|
+
TLoaderDeps,
|
|
134
|
+
TLoaderFn,
|
|
135
|
+
TChildren,
|
|
136
|
+
unknown,
|
|
137
|
+
TSSR,
|
|
138
|
+
TMiddlewares,
|
|
139
|
+
THandlers
|
|
140
|
+
> => {
|
|
141
|
+
warning(
|
|
142
|
+
this.silent,
|
|
143
|
+
'FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
|
|
144
|
+
)
|
|
145
|
+
const route = createRoute(options as any)
|
|
146
|
+
;(route as any).isRoot = false
|
|
147
|
+
return route as any
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
@deprecated It's recommended not to split loaders into separate files.
|
|
153
|
+
Instead, place the loader function in the the main route file, inside the
|
|
154
|
+
`createFileRoute('/path/to/file)(options)` options.
|
|
155
|
+
*/
|
|
156
|
+
export function FileRouteLoader<
|
|
157
|
+
TFilePath extends keyof FileRoutesByPath,
|
|
158
|
+
TRoute extends FileRoutesByPath[TFilePath]['preLoaderRoute'],
|
|
159
|
+
>(
|
|
160
|
+
_path: TFilePath,
|
|
161
|
+
): <TLoaderFn>(
|
|
162
|
+
loaderFn: Constrain<
|
|
163
|
+
TLoaderFn,
|
|
164
|
+
RouteLoaderFn<
|
|
165
|
+
Register,
|
|
166
|
+
TRoute['parentRoute'],
|
|
167
|
+
TRoute['types']['id'],
|
|
168
|
+
TRoute['types']['params'],
|
|
169
|
+
TRoute['types']['loaderDeps'],
|
|
170
|
+
TRoute['types']['routerContext'],
|
|
171
|
+
TRoute['types']['routeContextFn'],
|
|
172
|
+
TRoute['types']['beforeLoadFn']
|
|
173
|
+
>
|
|
174
|
+
>,
|
|
175
|
+
) => TLoaderFn {
|
|
176
|
+
warning(
|
|
177
|
+
false,
|
|
178
|
+
`FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
|
|
179
|
+
)
|
|
180
|
+
return (loaderFn) => loaderFn as any
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
declare module '@tanstack/router-core' {
|
|
184
|
+
export interface LazyRoute<in out TRoute extends AnyRoute> {
|
|
185
|
+
useMatch: UseMatchRoute<TRoute['id']>
|
|
186
|
+
useRouteContext: UseRouteContextRoute<TRoute['id']>
|
|
187
|
+
useSearch: UseSearchRoute<TRoute['id']>
|
|
188
|
+
useParams: UseParamsRoute<TRoute['id']>
|
|
189
|
+
useLoaderDeps: UseLoaderDepsRoute<TRoute['id']>
|
|
190
|
+
useLoaderData: UseLoaderDataRoute<TRoute['id']>
|
|
191
|
+
useNavigate: () => UseNavigateResult<TRoute['fullPath']>
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export class LazyRoute<TRoute extends AnyRoute> {
|
|
196
|
+
options: {
|
|
197
|
+
id: string
|
|
198
|
+
} & LazyRouteOptions
|
|
199
|
+
|
|
200
|
+
constructor(
|
|
201
|
+
opts: {
|
|
202
|
+
id: string
|
|
203
|
+
} & LazyRouteOptions,
|
|
204
|
+
) {
|
|
205
|
+
this.options = opts
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
useMatch: UseMatchRoute<TRoute['id']> = (opts) => {
|
|
209
|
+
return useMatch({
|
|
210
|
+
select: opts?.select,
|
|
211
|
+
from: this.options.id,
|
|
212
|
+
} as any) as any
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
useRouteContext: UseRouteContextRoute<TRoute['id']> = (opts) => {
|
|
216
|
+
return useMatch({
|
|
217
|
+
from: this.options.id,
|
|
218
|
+
select: (d: any) => (opts?.select ? opts.select(d.context) : d.context),
|
|
219
|
+
}) as any
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
useSearch: UseSearchRoute<TRoute['id']> = (opts) => {
|
|
223
|
+
return useSearch({
|
|
224
|
+
select: opts?.select,
|
|
225
|
+
from: this.options.id,
|
|
226
|
+
} as any) as any
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
useParams: UseParamsRoute<TRoute['id']> = (opts) => {
|
|
230
|
+
return useParams({
|
|
231
|
+
select: opts?.select,
|
|
232
|
+
from: this.options.id,
|
|
233
|
+
} as any) as any
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
useLoaderDeps: UseLoaderDepsRoute<TRoute['id']> = (opts) => {
|
|
237
|
+
return useLoaderDeps({ ...opts, from: this.options.id } as any)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
useLoaderData: UseLoaderDataRoute<TRoute['id']> = (opts) => {
|
|
241
|
+
return useLoaderData({ ...opts, from: this.options.id } as any)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
useNavigate = (): UseNavigateResult<TRoute['fullPath']> => {
|
|
245
|
+
const router = useRouter()
|
|
246
|
+
return useNavigate({ from: router.routesById[this.options.id].fullPath })
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function createLazyRoute<
|
|
251
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
252
|
+
TId extends string = string,
|
|
253
|
+
TRoute extends AnyRoute = RouteById<TRouter['routeTree'], TId>,
|
|
254
|
+
>(id: ConstrainLiteral<TId, RouteIds<TRouter['routeTree']>>) {
|
|
255
|
+
return (opts: LazyRouteOptions) => {
|
|
256
|
+
return new LazyRoute<TRoute>({
|
|
257
|
+
id: id,
|
|
258
|
+
...opts,
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
export function createLazyFileRoute<
|
|
263
|
+
TFilePath extends keyof FileRoutesByPath,
|
|
264
|
+
TRoute extends FileRoutesByPath[TFilePath]['preLoaderRoute'],
|
|
265
|
+
>(id: TFilePath): (opts: LazyRouteOptions) => LazyRoute<TRoute> {
|
|
266
|
+
if (typeof id === 'object') {
|
|
267
|
+
return new LazyRoute<TRoute>(id) as any
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return (opts: LazyRouteOptions) => new LazyRoute<TRoute>({ id, ...opts })
|
|
271
|
+
}
|
package/src/history.ts
ADDED