@tanstack/vue-router 0.0.1 → 1.140.1
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
package/dist/esm/link.js
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import * as Vue from "vue";
|
|
2
|
+
import { preloadWarning, exactPathTest, removeTrailingSlash, deepEqual } from "@tanstack/router-core";
|
|
3
|
+
import { useRouterState } from "./useRouterState.js";
|
|
4
|
+
import { useRouter } from "./useRouter.js";
|
|
5
|
+
import { useIntersectionObserver } from "./utils.js";
|
|
6
|
+
import { useMatches } from "./Matches.js";
|
|
7
|
+
function useLinkProps(options) {
|
|
8
|
+
const router = useRouter();
|
|
9
|
+
const isTransitioning = Vue.ref(false);
|
|
10
|
+
let hasRenderFetched = false;
|
|
11
|
+
if (!router) {
|
|
12
|
+
console.warn("useRouter must be used inside a <RouterProvider> component!");
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
const type = Vue.computed(() => {
|
|
16
|
+
try {
|
|
17
|
+
new URL(`${options.to}`);
|
|
18
|
+
return "external";
|
|
19
|
+
} catch {
|
|
20
|
+
return "internal";
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const currentSearch = useRouterState({
|
|
24
|
+
select: (s) => s.location.searchStr
|
|
25
|
+
});
|
|
26
|
+
const from = useMatches({
|
|
27
|
+
select: (matches) => options.from ?? matches[matches.length - 1]?.fullPath
|
|
28
|
+
});
|
|
29
|
+
const _options = Vue.computed(() => ({
|
|
30
|
+
...options,
|
|
31
|
+
from: from.value
|
|
32
|
+
}));
|
|
33
|
+
const next = Vue.computed(() => {
|
|
34
|
+
currentSearch.value;
|
|
35
|
+
return router.buildLocation(_options.value);
|
|
36
|
+
});
|
|
37
|
+
const preload = Vue.computed(() => {
|
|
38
|
+
if (_options.value.reloadDocument) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return options.preload ?? router.options.defaultPreload;
|
|
42
|
+
});
|
|
43
|
+
const preloadDelay = Vue.computed(() => options.preloadDelay ?? router.options.defaultPreloadDelay ?? 0);
|
|
44
|
+
const isActive = useRouterState({
|
|
45
|
+
select: (s) => {
|
|
46
|
+
const activeOptions = options.activeOptions;
|
|
47
|
+
if (activeOptions?.exact) {
|
|
48
|
+
const testExact = exactPathTest(s.location.pathname, next.value.pathname, router.basepath);
|
|
49
|
+
if (!testExact) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
const currentPathSplit = removeTrailingSlash(s.location.pathname, router.basepath).split("/");
|
|
54
|
+
const nextPathSplit = removeTrailingSlash(next.value?.pathname, router.basepath)?.split("/");
|
|
55
|
+
const pathIsFuzzyEqual = nextPathSplit?.every((d, i) => d === currentPathSplit[i]);
|
|
56
|
+
if (!pathIsFuzzyEqual) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (activeOptions?.includeSearch ?? true) {
|
|
61
|
+
const searchTest = deepEqual(s.location.search, next.value.search, {
|
|
62
|
+
partial: !activeOptions?.exact,
|
|
63
|
+
ignoreUndefined: !activeOptions?.explicitUndefined
|
|
64
|
+
});
|
|
65
|
+
if (!searchTest) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (activeOptions?.includeHash) {
|
|
70
|
+
return s.location.hash === next.value.hash;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const doPreload = () => router.preloadRoute(_options.value).catch((err) => {
|
|
76
|
+
console.warn(err);
|
|
77
|
+
console.warn(preloadWarning);
|
|
78
|
+
});
|
|
79
|
+
const preloadViewportIoCallback = (entry) => {
|
|
80
|
+
if (entry?.isIntersecting) {
|
|
81
|
+
doPreload();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const ref = Vue.ref(null);
|
|
85
|
+
useIntersectionObserver(ref, preloadViewportIoCallback, {
|
|
86
|
+
rootMargin: "100px"
|
|
87
|
+
}, {
|
|
88
|
+
disabled: () => !!options.disabled || !(preload.value === "viewport")
|
|
89
|
+
});
|
|
90
|
+
Vue.effect(() => {
|
|
91
|
+
if (hasRenderFetched) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!options.disabled && preload.value === "render") {
|
|
95
|
+
doPreload();
|
|
96
|
+
hasRenderFetched = true;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const getPropsSafeToSpread = () => {
|
|
100
|
+
const result = {};
|
|
101
|
+
for (const key in options) {
|
|
102
|
+
if (!["activeProps", "inactiveProps", "activeOptions", "to", "preload", "preloadDelay", "hashScrollIntoView", "replace", "startTransition", "resetScroll", "viewTransition", "children", "target", "disabled", "style", "class", "onClick", "onFocus", "onMouseEnter", "onMouseLeave", "onMouseOver", "onMouseOut", "onTouchStart", "ignoreBlocker", "params", "search", "hash", "state", "mask", "reloadDocument", "_asChild", "from", "additionalProps"].includes(key)) {
|
|
103
|
+
result[key] = options[key];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return result;
|
|
107
|
+
};
|
|
108
|
+
if (type.value === "external") {
|
|
109
|
+
const externalProps = {
|
|
110
|
+
...getPropsSafeToSpread(),
|
|
111
|
+
ref,
|
|
112
|
+
href: options.to,
|
|
113
|
+
target: options.target,
|
|
114
|
+
disabled: options.disabled,
|
|
115
|
+
style: options.style,
|
|
116
|
+
class: options.class,
|
|
117
|
+
onClick: options.onClick,
|
|
118
|
+
onFocus: options.onFocus,
|
|
119
|
+
onMouseEnter: options.onMouseEnter,
|
|
120
|
+
onMouseLeave: options.onMouseLeave,
|
|
121
|
+
onMouseOver: options.onMouseOver,
|
|
122
|
+
onMouseOut: options.onMouseOut,
|
|
123
|
+
onTouchStart: options.onTouchStart
|
|
124
|
+
};
|
|
125
|
+
Object.keys(externalProps).forEach((key) => {
|
|
126
|
+
if (externalProps[key] === void 0) {
|
|
127
|
+
delete externalProps[key];
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return externalProps;
|
|
131
|
+
}
|
|
132
|
+
const handleClick = (e) => {
|
|
133
|
+
const elementTarget = e.currentTarget?.getAttribute("target");
|
|
134
|
+
const effectiveTarget = options.target !== void 0 ? options.target : elementTarget;
|
|
135
|
+
if (!options.disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!effectiveTarget || effectiveTarget === "_self") && e.button === 0) {
|
|
136
|
+
if (_options.value.reloadDocument) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
isTransitioning.value = true;
|
|
141
|
+
const unsub = router.subscribe("onResolved", () => {
|
|
142
|
+
unsub();
|
|
143
|
+
isTransitioning.value = false;
|
|
144
|
+
});
|
|
145
|
+
router.navigate({
|
|
146
|
+
..._options.value,
|
|
147
|
+
replace: options.replace,
|
|
148
|
+
resetScroll: options.resetScroll,
|
|
149
|
+
hashScrollIntoView: options.hashScrollIntoView,
|
|
150
|
+
startTransition: options.startTransition,
|
|
151
|
+
viewTransition: options.viewTransition,
|
|
152
|
+
ignoreBlocker: options.ignoreBlocker
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const handleFocus = (_) => {
|
|
157
|
+
if (options.disabled) return;
|
|
158
|
+
if (preload.value) {
|
|
159
|
+
doPreload();
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const handleTouchStart = (_) => {
|
|
163
|
+
if (options.disabled) return;
|
|
164
|
+
if (preload.value) {
|
|
165
|
+
doPreload();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const handleEnter = (e) => {
|
|
169
|
+
if (options.disabled) return;
|
|
170
|
+
const eventTarget = e.currentTarget || e.target || {};
|
|
171
|
+
if (preload.value) {
|
|
172
|
+
if (eventTarget.preloadTimeout) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
eventTarget.preloadTimeout = setTimeout(() => {
|
|
176
|
+
eventTarget.preloadTimeout = null;
|
|
177
|
+
doPreload();
|
|
178
|
+
}, preloadDelay.value);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const handleLeave = (e) => {
|
|
182
|
+
if (options.disabled) return;
|
|
183
|
+
const eventTarget = e.currentTarget || e.target || {};
|
|
184
|
+
if (eventTarget.preloadTimeout) {
|
|
185
|
+
clearTimeout(eventTarget.preloadTimeout);
|
|
186
|
+
eventTarget.preloadTimeout = null;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
function composeEventHandlers(handlers) {
|
|
190
|
+
return (event) => {
|
|
191
|
+
for (const handler of handlers) {
|
|
192
|
+
if (handler) {
|
|
193
|
+
handler(event);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const resolvedActiveProps = Vue.computed(() => {
|
|
199
|
+
const activeProps = options.activeProps || (() => ({
|
|
200
|
+
class: "active"
|
|
201
|
+
}));
|
|
202
|
+
const props = isActive.value ? typeof activeProps === "function" ? activeProps() : activeProps : {};
|
|
203
|
+
return props || {
|
|
204
|
+
class: void 0,
|
|
205
|
+
style: void 0
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
const resolvedInactiveProps = Vue.computed(() => {
|
|
209
|
+
const inactiveProps = options.inactiveProps || (() => ({}));
|
|
210
|
+
const props = isActive.value ? {} : typeof inactiveProps === "function" ? inactiveProps() : inactiveProps;
|
|
211
|
+
return props || {
|
|
212
|
+
class: void 0,
|
|
213
|
+
style: void 0
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
const resolvedClassName = Vue.computed(() => {
|
|
217
|
+
const classes = [options.class, resolvedActiveProps.value?.class, resolvedInactiveProps.value?.class].filter(Boolean);
|
|
218
|
+
return classes.length ? classes.join(" ") : void 0;
|
|
219
|
+
});
|
|
220
|
+
const resolvedStyle = Vue.computed(() => {
|
|
221
|
+
const result = {};
|
|
222
|
+
if (options.style) {
|
|
223
|
+
Object.assign(result, options.style);
|
|
224
|
+
}
|
|
225
|
+
if (resolvedActiveProps.value?.style) {
|
|
226
|
+
Object.assign(result, resolvedActiveProps.value.style);
|
|
227
|
+
}
|
|
228
|
+
if (resolvedInactiveProps.value?.style) {
|
|
229
|
+
Object.assign(result, resolvedInactiveProps.value.style);
|
|
230
|
+
}
|
|
231
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
232
|
+
});
|
|
233
|
+
const href = Vue.computed(() => {
|
|
234
|
+
if (options.disabled) {
|
|
235
|
+
return void 0;
|
|
236
|
+
}
|
|
237
|
+
const nextLocation = next.value;
|
|
238
|
+
const maskedLocation = nextLocation?.maskedLocation;
|
|
239
|
+
let hrefValue;
|
|
240
|
+
if (maskedLocation) {
|
|
241
|
+
hrefValue = maskedLocation.url;
|
|
242
|
+
} else {
|
|
243
|
+
hrefValue = nextLocation?.url;
|
|
244
|
+
}
|
|
245
|
+
if (router.origin && hrefValue?.startsWith(router.origin)) {
|
|
246
|
+
hrefValue = router.history.createHref(hrefValue.replace(router.origin, ""));
|
|
247
|
+
}
|
|
248
|
+
return hrefValue;
|
|
249
|
+
});
|
|
250
|
+
const reactiveProps = Vue.shallowReactive({
|
|
251
|
+
...getPropsSafeToSpread(),
|
|
252
|
+
href: void 0,
|
|
253
|
+
ref,
|
|
254
|
+
onClick: composeEventHandlers([options.onClick, handleClick]),
|
|
255
|
+
onFocus: composeEventHandlers([options.onFocus, handleFocus]),
|
|
256
|
+
onMouseenter: composeEventHandlers([options.onMouseEnter, handleEnter]),
|
|
257
|
+
onMouseover: composeEventHandlers([options.onMouseOver, handleEnter]),
|
|
258
|
+
onMouseleave: composeEventHandlers([options.onMouseLeave, handleLeave]),
|
|
259
|
+
onMouseout: composeEventHandlers([options.onMouseOut, handleLeave]),
|
|
260
|
+
onTouchstart: composeEventHandlers([options.onTouchStart, handleTouchStart]),
|
|
261
|
+
disabled: !!options.disabled,
|
|
262
|
+
target: options.target
|
|
263
|
+
});
|
|
264
|
+
Vue.watchEffect(() => {
|
|
265
|
+
const activeP = resolvedActiveProps.value;
|
|
266
|
+
const inactiveP = resolvedInactiveProps.value;
|
|
267
|
+
reactiveProps.href = href.value;
|
|
268
|
+
if (resolvedStyle.value) {
|
|
269
|
+
reactiveProps.style = resolvedStyle.value;
|
|
270
|
+
} else {
|
|
271
|
+
delete reactiveProps.style;
|
|
272
|
+
}
|
|
273
|
+
if (resolvedClassName.value) {
|
|
274
|
+
reactiveProps.class = resolvedClassName.value;
|
|
275
|
+
} else {
|
|
276
|
+
delete reactiveProps.class;
|
|
277
|
+
}
|
|
278
|
+
if (options.disabled) {
|
|
279
|
+
reactiveProps.role = "link";
|
|
280
|
+
reactiveProps["aria-disabled"] = true;
|
|
281
|
+
} else {
|
|
282
|
+
delete reactiveProps.role;
|
|
283
|
+
delete reactiveProps["aria-disabled"];
|
|
284
|
+
}
|
|
285
|
+
if (isActive.value) {
|
|
286
|
+
reactiveProps["data-status"] = "active";
|
|
287
|
+
reactiveProps["aria-current"] = "page";
|
|
288
|
+
} else {
|
|
289
|
+
delete reactiveProps["data-status"];
|
|
290
|
+
delete reactiveProps["aria-current"];
|
|
291
|
+
}
|
|
292
|
+
if (isTransitioning.value) {
|
|
293
|
+
reactiveProps["data-transitioning"] = "transitioning";
|
|
294
|
+
} else {
|
|
295
|
+
delete reactiveProps["data-transitioning"];
|
|
296
|
+
}
|
|
297
|
+
for (const key of Object.keys(activeP)) {
|
|
298
|
+
if (key !== "class" && key !== "style") {
|
|
299
|
+
reactiveProps[key] = activeP[key];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
for (const key of Object.keys(inactiveP)) {
|
|
303
|
+
if (key !== "class" && key !== "style") {
|
|
304
|
+
reactiveProps[key] = inactiveP[key];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
return reactiveProps;
|
|
309
|
+
}
|
|
310
|
+
function createLink(Comp) {
|
|
311
|
+
return Vue.defineComponent({
|
|
312
|
+
name: "CreatedLink",
|
|
313
|
+
inheritAttrs: false,
|
|
314
|
+
setup(_, {
|
|
315
|
+
attrs,
|
|
316
|
+
slots
|
|
317
|
+
}) {
|
|
318
|
+
return () => Vue.h(Link, {
|
|
319
|
+
...attrs,
|
|
320
|
+
_asChild: Comp
|
|
321
|
+
}, slots);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
const LinkImpl = Vue.defineComponent({
|
|
326
|
+
name: "Link",
|
|
327
|
+
inheritAttrs: false,
|
|
328
|
+
props: ["_asChild", "to", "preload", "preloadDelay", "activeProps", "inactiveProps", "activeOptions", "from", "search", "params", "hash", "state", "mask", "reloadDocument", "disabled", "additionalProps", "viewTransition", "resetScroll", "startTransition", "hashScrollIntoView", "replace", "ignoreBlocker", "target"],
|
|
329
|
+
setup(props, {
|
|
330
|
+
attrs,
|
|
331
|
+
slots
|
|
332
|
+
}) {
|
|
333
|
+
const allProps = {
|
|
334
|
+
...props,
|
|
335
|
+
...attrs
|
|
336
|
+
};
|
|
337
|
+
const linkProps = useLinkProps(allProps);
|
|
338
|
+
return () => {
|
|
339
|
+
const Component = props._asChild || "a";
|
|
340
|
+
const isActive = linkProps["data-status"] === "active";
|
|
341
|
+
const isTransitioning = linkProps["data-transitioning"] === "transitioning";
|
|
342
|
+
const slotContent = slots.default ? slots.default({
|
|
343
|
+
isActive,
|
|
344
|
+
isTransitioning
|
|
345
|
+
}) : [];
|
|
346
|
+
if (Component === "svg") {
|
|
347
|
+
const svgLinkProps = {
|
|
348
|
+
...linkProps
|
|
349
|
+
};
|
|
350
|
+
delete svgLinkProps.class;
|
|
351
|
+
return Vue.h("svg", {}, [Vue.h("a", svgLinkProps, slotContent)]);
|
|
352
|
+
}
|
|
353
|
+
if (typeof Component !== "string") {
|
|
354
|
+
return Vue.h(Component, {
|
|
355
|
+
...linkProps,
|
|
356
|
+
children: slotContent
|
|
357
|
+
}, slotContent);
|
|
358
|
+
}
|
|
359
|
+
return Vue.h(Component, linkProps, slotContent);
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
const Link = LinkImpl;
|
|
364
|
+
function isCtrlEvent(e) {
|
|
365
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
366
|
+
}
|
|
367
|
+
const linkOptions = (options) => {
|
|
368
|
+
return options;
|
|
369
|
+
};
|
|
370
|
+
export {
|
|
371
|
+
Link,
|
|
372
|
+
createLink,
|
|
373
|
+
linkOptions,
|
|
374
|
+
useLinkProps
|
|
375
|
+
};
|
|
376
|
+
//# sourceMappingURL=link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.js","sources":["../../src/link.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport {\n deepEqual,\n exactPathTest,\n preloadWarning,\n removeTrailingSlash,\n} from '@tanstack/router-core'\n\nimport { useRouterState } from './useRouterState'\nimport { useRouter } from './useRouter'\nimport { useIntersectionObserver } from './utils'\nimport { useMatches } from './Matches'\n\nimport type {\n AnyRouter,\n Constrain,\n LinkCurrentTargetElement,\n LinkOptions,\n RegisteredRouter,\n RoutePaths,\n} from '@tanstack/router-core'\nimport type {\n ValidateLinkOptions,\n ValidateLinkOptionsArray,\n} from './typePrimitives'\n\n// Type definitions to replace missing Vue JSX types\ntype EventHandler<TEvent = Event> = (e: TEvent) => void\ninterface HTMLAttributes {\n class?: string\n style?: Record<string, string | number>\n onClick?: EventHandler<MouseEvent>\n onFocus?: EventHandler<FocusEvent>\n // Vue 3's h() function expects lowercase event names after 'on' prefix\n onMouseenter?: EventHandler<MouseEvent>\n onMouseleave?: EventHandler<MouseEvent>\n onMouseover?: EventHandler<MouseEvent>\n onMouseout?: EventHandler<MouseEvent>\n onTouchstart?: EventHandler<TouchEvent>\n // Also accept the camelCase versions for external API compatibility\n onMouseEnter?: EventHandler<MouseEvent>\n onMouseLeave?: EventHandler<MouseEvent>\n onMouseOver?: EventHandler<MouseEvent>\n onMouseOut?: EventHandler<MouseEvent>\n onTouchStart?: EventHandler<TouchEvent>\n [key: string]: any\n}\n\ninterface StyledProps {\n class?: string\n style?: Record<string, string | number>\n [key: string]: any\n}\n\nexport function useLinkProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string = '',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '',\n>(\n options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n): HTMLAttributes {\n const router = useRouter()\n const isTransitioning = Vue.ref(false)\n let hasRenderFetched = false\n\n // Ensure router is defined before proceeding\n if (!router) {\n console.warn('useRouter must be used inside a <RouterProvider> component!')\n return {}\n }\n\n // Determine if the link is external or internal\n const type = Vue.computed(() => {\n try {\n new URL(`${options.to}`)\n return 'external'\n } catch {\n return 'internal'\n }\n })\n\n const currentSearch = useRouterState({\n select: (s) => s.location.searchStr,\n })\n\n // when `from` is not supplied, use the leaf route of the current matches as the `from` location\n const from = useMatches({\n select: (matches) => options.from ?? matches[matches.length - 1]?.fullPath,\n })\n\n const _options = Vue.computed(() => ({\n ...options,\n from: from.value,\n }))\n\n const next = Vue.computed(() => {\n // Depend on search to rebuild when search changes\n currentSearch.value\n return router.buildLocation(_options.value as any)\n })\n\n const preload = Vue.computed(() => {\n if (_options.value.reloadDocument) {\n return false\n }\n return options.preload ?? router.options.defaultPreload\n })\n\n const preloadDelay = Vue.computed(\n () => options.preloadDelay ?? router.options.defaultPreloadDelay ?? 0,\n )\n\n const isActive = useRouterState({\n select: (s) => {\n const activeOptions = options.activeOptions\n if (activeOptions?.exact) {\n const testExact = exactPathTest(\n s.location.pathname,\n next.value.pathname,\n router.basepath,\n )\n if (!testExact) {\n return false\n }\n } else {\n const currentPathSplit = removeTrailingSlash(\n s.location.pathname,\n router.basepath,\n ).split('/')\n const nextPathSplit = removeTrailingSlash(\n next.value?.pathname,\n router.basepath,\n )?.split('/')\n\n const pathIsFuzzyEqual = nextPathSplit?.every(\n (d, i) => d === currentPathSplit[i],\n )\n if (!pathIsFuzzyEqual) {\n return false\n }\n }\n\n if (activeOptions?.includeSearch ?? true) {\n const searchTest = deepEqual(s.location.search, next.value.search, {\n partial: !activeOptions?.exact,\n ignoreUndefined: !activeOptions?.explicitUndefined,\n })\n if (!searchTest) {\n return false\n }\n }\n\n if (activeOptions?.includeHash) {\n return s.location.hash === next.value.hash\n }\n return true\n },\n })\n\n const doPreload = () =>\n router.preloadRoute(_options.value as any).catch((err: any) => {\n console.warn(err)\n console.warn(preloadWarning)\n })\n\n const preloadViewportIoCallback = (\n entry: IntersectionObserverEntry | undefined,\n ) => {\n if (entry?.isIntersecting) {\n doPreload()\n }\n }\n\n const ref = Vue.ref<Element | null>(null)\n\n useIntersectionObserver(\n ref,\n preloadViewportIoCallback,\n { rootMargin: '100px' },\n { disabled: () => !!options.disabled || !(preload.value === 'viewport') },\n )\n\n Vue.effect(() => {\n if (hasRenderFetched) {\n return\n }\n if (!options.disabled && preload.value === 'render') {\n doPreload()\n hasRenderFetched = true\n }\n })\n\n // Create safe props that can be spread\n const getPropsSafeToSpread = () => {\n const result: Record<string, any> = {}\n for (const key in options) {\n if (\n ![\n 'activeProps',\n 'inactiveProps',\n 'activeOptions',\n 'to',\n 'preload',\n 'preloadDelay',\n 'hashScrollIntoView',\n 'replace',\n 'startTransition',\n 'resetScroll',\n 'viewTransition',\n 'children',\n 'target',\n 'disabled',\n 'style',\n 'class',\n 'onClick',\n 'onFocus',\n 'onMouseEnter',\n 'onMouseLeave',\n 'onMouseOver',\n 'onMouseOut',\n 'onTouchStart',\n 'ignoreBlocker',\n 'params',\n 'search',\n 'hash',\n 'state',\n 'mask',\n 'reloadDocument',\n '_asChild',\n 'from',\n 'additionalProps',\n ].includes(key)\n ) {\n result[key] = options[key]\n }\n }\n return result\n }\n\n if (type.value === 'external') {\n // External links just have simple props\n const externalProps: HTMLAttributes = {\n ...getPropsSafeToSpread(),\n ref,\n href: options.to,\n target: options.target,\n disabled: options.disabled,\n style: options.style,\n class: options.class,\n onClick: options.onClick,\n onFocus: options.onFocus,\n onMouseEnter: options.onMouseEnter,\n onMouseLeave: options.onMouseLeave,\n onMouseOver: options.onMouseOver,\n onMouseOut: options.onMouseOut,\n onTouchStart: options.onTouchStart,\n }\n\n // Remove undefined values\n Object.keys(externalProps).forEach((key) => {\n if (externalProps[key] === undefined) {\n delete externalProps[key]\n }\n })\n\n return externalProps\n }\n\n // The click handler\n const handleClick = (e: MouseEvent): void => {\n // Check actual element's target attribute as fallback\n const elementTarget = (\n e.currentTarget as HTMLAnchorElement | SVGAElement\n )?.getAttribute('target')\n const effectiveTarget =\n options.target !== undefined ? options.target : elementTarget\n\n if (\n !options.disabled &&\n !isCtrlEvent(e) &&\n !e.defaultPrevented &&\n (!effectiveTarget || effectiveTarget === '_self') &&\n e.button === 0\n ) {\n // Don't prevent default or handle navigation if reloadDocument is true\n if (_options.value.reloadDocument) {\n return\n }\n\n e.preventDefault()\n\n isTransitioning.value = true\n\n const unsub = router.subscribe('onResolved', () => {\n unsub()\n isTransitioning.value = false\n })\n\n // All is well? Navigate!\n router.navigate({\n ..._options.value,\n replace: options.replace,\n resetScroll: options.resetScroll,\n hashScrollIntoView: options.hashScrollIntoView,\n startTransition: options.startTransition,\n viewTransition: options.viewTransition,\n ignoreBlocker: options.ignoreBlocker,\n } as any)\n }\n }\n\n // The focus handler\n const handleFocus = (_: FocusEvent) => {\n if (options.disabled) return\n if (preload.value) {\n doPreload()\n }\n }\n\n const handleTouchStart = (_: TouchEvent) => {\n if (options.disabled) return\n if (preload.value) {\n doPreload()\n }\n }\n\n const handleEnter = (e: MouseEvent) => {\n if (options.disabled) return\n // Use currentTarget (the element with the handler) instead of target (which may be a child)\n const eventTarget = (e.currentTarget ||\n e.target ||\n {}) as LinkCurrentTargetElement\n\n if (preload.value) {\n if (eventTarget.preloadTimeout) {\n return\n }\n\n eventTarget.preloadTimeout = setTimeout(() => {\n eventTarget.preloadTimeout = null\n doPreload()\n }, preloadDelay.value)\n }\n }\n\n const handleLeave = (e: MouseEvent) => {\n if (options.disabled) return\n // Use currentTarget (the element with the handler) instead of target (which may be a child)\n const eventTarget = (e.currentTarget ||\n e.target ||\n {}) as LinkCurrentTargetElement\n\n if (eventTarget.preloadTimeout) {\n clearTimeout(eventTarget.preloadTimeout)\n eventTarget.preloadTimeout = null\n }\n }\n\n // Helper to compose event handlers - with explicit return type and better type handling\n function composeEventHandlers<T extends Event>(\n handlers: Array<EventHandler<T> | undefined>,\n ): (e: T) => void {\n return (event: T) => {\n for (const handler of handlers) {\n if (handler) {\n handler(event)\n }\n }\n }\n }\n\n // Get the active and inactive props\n const resolvedActiveProps = Vue.computed<StyledProps>(() => {\n const activeProps = options.activeProps || (() => ({ class: 'active' }))\n const props = isActive.value\n ? typeof activeProps === 'function'\n ? activeProps()\n : activeProps\n : {}\n\n return props || { class: undefined, style: undefined }\n })\n\n const resolvedInactiveProps = Vue.computed<StyledProps>(() => {\n const inactiveProps = options.inactiveProps || (() => ({}))\n const props = isActive.value\n ? {}\n : typeof inactiveProps === 'function'\n ? inactiveProps()\n : inactiveProps\n\n return props || { class: undefined, style: undefined }\n })\n\n const resolvedClassName = Vue.computed(() => {\n const classes = [\n options.class,\n resolvedActiveProps.value?.class,\n resolvedInactiveProps.value?.class,\n ].filter(Boolean)\n return classes.length ? classes.join(' ') : undefined\n })\n\n const resolvedStyle = Vue.computed(() => {\n const result: Record<string, string | number> = {}\n\n // Merge styles from all sources\n if (options.style) {\n Object.assign(result, options.style)\n }\n\n if (resolvedActiveProps.value?.style) {\n Object.assign(result, resolvedActiveProps.value.style)\n }\n\n if (resolvedInactiveProps.value?.style) {\n Object.assign(result, resolvedInactiveProps.value.style)\n }\n\n return Object.keys(result).length > 0 ? result : undefined\n })\n\n const href = Vue.computed(() => {\n if (options.disabled) {\n return undefined\n }\n const nextLocation = next.value\n const maskedLocation = nextLocation?.maskedLocation\n\n let hrefValue: string\n if (maskedLocation) {\n hrefValue = maskedLocation.url\n } else {\n hrefValue = nextLocation?.url\n }\n\n // Handle origin stripping like Solid does\n if (router.origin && hrefValue?.startsWith(router.origin)) {\n hrefValue = router.history.createHref(\n hrefValue.replace(router.origin, ''),\n )\n }\n\n return hrefValue\n })\n\n // Create a reactive proxy that reads computed values on access\n // This allows the returned object to stay reactive when used in templates\n // Use shallowReactive to preserve the ref object without unwrapping it\n const reactiveProps: HTMLAttributes = Vue.shallowReactive({\n ...getPropsSafeToSpread(),\n href: undefined as string | undefined,\n ref,\n onClick: composeEventHandlers<MouseEvent>([\n options.onClick,\n handleClick,\n ]) as any,\n onFocus: composeEventHandlers<FocusEvent>([\n options.onFocus,\n handleFocus,\n ]) as any,\n onMouseenter: composeEventHandlers<MouseEvent>([\n options.onMouseEnter,\n handleEnter,\n ]) as any,\n onMouseover: composeEventHandlers<MouseEvent>([\n options.onMouseOver,\n handleEnter,\n ]) as any,\n onMouseleave: composeEventHandlers<MouseEvent>([\n options.onMouseLeave,\n handleLeave,\n ]) as any,\n onMouseout: composeEventHandlers<MouseEvent>([\n options.onMouseOut,\n handleLeave,\n ]) as any,\n onTouchstart: composeEventHandlers<TouchEvent>([\n options.onTouchStart,\n handleTouchStart,\n ]) as any,\n disabled: !!options.disabled,\n target: options.target,\n })\n\n // Watch computed values and update reactive props\n Vue.watchEffect(() => {\n // Update from resolved active/inactive props\n const activeP = resolvedActiveProps.value\n const inactiveP = resolvedInactiveProps.value\n\n // Update href\n reactiveProps.href = href.value\n\n // Update style\n if (resolvedStyle.value) {\n reactiveProps.style = resolvedStyle.value\n } else {\n delete reactiveProps.style\n }\n\n // Update class\n if (resolvedClassName.value) {\n reactiveProps.class = resolvedClassName.value\n } else {\n delete reactiveProps.class\n }\n\n // Update disabled props\n if (options.disabled) {\n reactiveProps.role = 'link'\n reactiveProps['aria-disabled'] = true\n } else {\n delete reactiveProps.role\n delete reactiveProps['aria-disabled']\n }\n\n // Update active status\n if (isActive.value) {\n reactiveProps['data-status'] = 'active'\n reactiveProps['aria-current'] = 'page'\n } else {\n delete reactiveProps['data-status']\n delete reactiveProps['aria-current']\n }\n\n // Update transitioning status\n if (isTransitioning.value) {\n reactiveProps['data-transitioning'] = 'transitioning'\n } else {\n delete reactiveProps['data-transitioning']\n }\n\n // Merge active/inactive props (excluding class and style which are handled above)\n for (const key of Object.keys(activeP)) {\n if (key !== 'class' && key !== 'style') {\n reactiveProps[key] = activeP[key]\n }\n }\n for (const key of Object.keys(inactiveP)) {\n if (key !== 'class' && key !== 'style') {\n reactiveProps[key] = inactiveP[key]\n }\n }\n })\n\n return reactiveProps\n}\n\n// Type definitions\nexport type UseLinkPropsOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '.',\n> = ActiveLinkOptions<'a', TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n HTMLAttributes\n\nexport type ActiveLinkOptions<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n ActiveLinkOptionProps<TComp>\n\ntype ActiveLinkProps<TComp> = Partial<\n HTMLAttributes & {\n [key: `data-${string}`]: unknown\n }\n>\n\nexport interface ActiveLinkOptionProps<TComp = 'a'> {\n /**\n * A function that returns additional props for the `active` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `class`'s are concatenated)\n */\n activeProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>)\n /**\n * A function that returns additional props for the `inactive` state of this link.\n * These props override other props passed to the link (`style`'s are merged, `class`'s are concatenated)\n */\n inactiveProps?: ActiveLinkProps<TComp> | (() => ActiveLinkProps<TComp>)\n}\n\nexport type LinkProps<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = ActiveLinkOptions<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo> &\n LinkPropsChildren\n\nexport interface LinkPropsChildren {\n // 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\n children?:\n | Vue.VNode\n | ((state: { isActive: boolean; isTransitioning: boolean }) => Vue.VNode)\n}\n\ntype LinkComponentVueProps<TComp> = TComp extends keyof HTMLElementTagNameMap\n ? Omit<HTMLAttributes, keyof CreateLinkProps>\n : TComp extends Vue.Component\n ? Record<string, any>\n : Record<string, any>\n\nexport type LinkComponentProps<\n TComp = 'a',\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = LinkComponentVueProps<TComp> &\n LinkProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type CreateLinkProps = LinkProps<\n any,\n any,\n string,\n string,\n string,\n string\n>\n\nexport type LinkComponent<TComp> = <\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n props: LinkComponentProps<TComp, TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => Vue.VNode\n\nexport function createLink<const TComp>(\n Comp: Constrain<TComp, any, (props: CreateLinkProps) => Vue.VNode>,\n): LinkComponent<TComp> {\n return Vue.defineComponent({\n name: 'CreatedLink',\n inheritAttrs: false,\n setup(_, { attrs, slots }) {\n return () => Vue.h(Link, { ...attrs, _asChild: Comp }, slots)\n },\n }) as any\n}\n\nconst LinkImpl = Vue.defineComponent({\n name: 'Link',\n inheritAttrs: false,\n props: [\n '_asChild',\n 'to',\n 'preload',\n 'preloadDelay',\n 'activeProps',\n 'inactiveProps',\n 'activeOptions',\n 'from',\n 'search',\n 'params',\n 'hash',\n 'state',\n 'mask',\n 'reloadDocument',\n 'disabled',\n 'additionalProps',\n 'viewTransition',\n 'resetScroll',\n 'startTransition',\n 'hashScrollIntoView',\n 'replace',\n 'ignoreBlocker',\n 'target',\n ],\n setup(props, { attrs, slots }) {\n // Call useLinkProps ONCE during setup with combined props and attrs\n // The returned object includes computed values that update reactively\n const allProps = { ...props, ...attrs }\n const linkProps = useLinkProps(allProps as any)\n\n return () => {\n const Component = props._asChild || 'a'\n\n const isActive = linkProps['data-status'] === 'active'\n const isTransitioning =\n linkProps['data-transitioning'] === 'transitioning'\n\n // Create the slot content or empty array if no default slot\n const slotContent = slots.default\n ? slots.default({\n isActive,\n isTransitioning,\n })\n : []\n\n // Special handling for SVG links - wrap an <a> inside the SVG\n if (Component === 'svg') {\n // Create props without class for svg link\n const svgLinkProps = { ...linkProps }\n delete (svgLinkProps as any).class\n return Vue.h('svg', {}, [Vue.h('a', svgLinkProps, slotContent)])\n }\n\n // For custom functional components (non-string), pass children as a prop\n // since they may expect children as a prop like in Solid\n if (typeof Component !== 'string') {\n return Vue.h(\n Component,\n { ...linkProps, children: slotContent },\n slotContent,\n )\n }\n\n // Return the component with props and children\n return Vue.h(Component, linkProps, slotContent)\n }\n },\n})\n\n/**\n * Link component with proper TypeScript generics support\n */\nexport const Link = LinkImpl as unknown as {\n <\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends RoutePaths<TRouter['routeTree']> | string = string,\n TTo extends string | undefined = '.',\n TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom,\n TMaskTo extends string = '.',\n >(\n props: LinkComponentProps<'a', TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n ): Vue.VNode\n}\n\nfunction isCtrlEvent(e: MouseEvent) {\n return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)\n}\n\nexport type LinkOptionsFnOptions<\n TOptions,\n TComp,\n TRouter extends AnyRouter = RegisteredRouter,\n> =\n TOptions extends ReadonlyArray<any>\n ? ValidateLinkOptionsArray<TRouter, TOptions, string, TComp>\n : ValidateLinkOptions<TRouter, TOptions, string, TComp>\n\nexport type LinkOptionsFn<TComp> = <\n const TOptions,\n TRouter extends AnyRouter = RegisteredRouter,\n>(\n options: LinkOptionsFnOptions<TOptions, TComp, TRouter>,\n) => TOptions\n\nexport const linkOptions: LinkOptionsFn<'a'> = (options) => {\n return options as any\n}\n"],"names":["useLinkProps","options","router","useRouter","isTransitioning","Vue","ref","hasRenderFetched","console","warn","type","computed","URL","to","currentSearch","useRouterState","select","s","location","searchStr","from","useMatches","matches","length","fullPath","_options","value","next","buildLocation","preload","reloadDocument","defaultPreload","preloadDelay","defaultPreloadDelay","isActive","activeOptions","exact","testExact","exactPathTest","pathname","basepath","currentPathSplit","removeTrailingSlash","split","nextPathSplit","pathIsFuzzyEqual","every","d","i","includeSearch","searchTest","deepEqual","search","partial","ignoreUndefined","explicitUndefined","includeHash","hash","doPreload","preloadRoute","catch","err","preloadWarning","preloadViewportIoCallback","entry","isIntersecting","useIntersectionObserver","rootMargin","disabled","effect","getPropsSafeToSpread","result","key","includes","externalProps","href","target","style","class","onClick","onFocus","onMouseEnter","onMouseLeave","onMouseOver","onMouseOut","onTouchStart","Object","keys","forEach","undefined","handleClick","e","elementTarget","currentTarget","getAttribute","effectiveTarget","isCtrlEvent","defaultPrevented","button","preventDefault","unsub","subscribe","navigate","replace","resetScroll","hashScrollIntoView","startTransition","viewTransition","ignoreBlocker","handleFocus","_","handleTouchStart","handleEnter","eventTarget","preloadTimeout","setTimeout","handleLeave","clearTimeout","composeEventHandlers","handlers","event","handler","resolvedActiveProps","activeProps","props","resolvedInactiveProps","inactiveProps","resolvedClassName","classes","filter","Boolean","join","resolvedStyle","assign","nextLocation","maskedLocation","hrefValue","url","origin","startsWith","history","createHref","reactiveProps","shallowReactive","onMouseenter","onMouseover","onMouseleave","onMouseout","onTouchstart","watchEffect","activeP","inactiveP","role","createLink","Comp","defineComponent","name","inheritAttrs","setup","attrs","slots","h","Link","_asChild","LinkImpl","allProps","linkProps","Component","slotContent","default","svgLinkProps","children","metaKey","altKey","ctrlKey","shiftKey","linkOptions"],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Vue from 'vue';
|
|
2
|
+
export declare const matchContext: Vue.InjectionKey<Vue.Ref<string | undefined>>;
|
|
3
|
+
export declare const dummyMatchContext: Vue.InjectionKey<Vue.Ref<string | undefined>>;
|
|
4
|
+
/**
|
|
5
|
+
* Provides a match ID to child components
|
|
6
|
+
*/
|
|
7
|
+
export declare function provideMatch(matchId: string | undefined): void;
|
|
8
|
+
/**
|
|
9
|
+
* Retrieves the match ID from the component tree
|
|
10
|
+
*/
|
|
11
|
+
export declare function injectMatch(): Vue.Ref<string | undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* Provides a dummy match ID to child components
|
|
14
|
+
*/
|
|
15
|
+
export declare function provideDummyMatch(matchId: string | undefined): void;
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves the dummy match ID from the component tree
|
|
18
|
+
* This only exists so we can conditionally inject a value when we are not interested in the nearest match
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectDummyMatch(): Vue.Ref<string | undefined>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Vue from "vue";
|
|
2
|
+
const matchContext = Symbol("TanStackRouterMatch");
|
|
3
|
+
const dummyMatchContext = Symbol("TanStackRouterDummyMatch");
|
|
4
|
+
function injectMatch() {
|
|
5
|
+
return Vue.inject(matchContext, Vue.ref(void 0));
|
|
6
|
+
}
|
|
7
|
+
function injectDummyMatch() {
|
|
8
|
+
return Vue.inject(dummyMatchContext, Vue.ref(void 0));
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
dummyMatchContext,
|
|
12
|
+
injectDummyMatch,
|
|
13
|
+
injectMatch,
|
|
14
|
+
matchContext
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=matchContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchContext.js","sources":["../../src/matchContext.tsx"],"sourcesContent":["import * as Vue from 'vue'\n\n// Create a typed injection key with support for undefined values\n// This is the primary match context used throughout the router\nexport const matchContext = Symbol('TanStackRouterMatch') as Vue.InjectionKey<\n Vue.Ref<string | undefined>\n>\n\n// Dummy match context for when we want to look up by explicit 'from' route\nexport const dummyMatchContext = Symbol(\n 'TanStackRouterDummyMatch',\n) as Vue.InjectionKey<Vue.Ref<string | undefined>>\n\n/**\n * Provides a match ID to child components\n */\nexport function provideMatch(matchId: string | undefined) {\n Vue.provide(matchContext, Vue.ref(matchId))\n}\n\n/**\n * Retrieves the match ID from the component tree\n */\nexport function injectMatch(): Vue.Ref<string | undefined> {\n return Vue.inject(matchContext, Vue.ref(undefined))\n}\n\n/**\n * Provides a dummy match ID to child components\n */\nexport function provideDummyMatch(matchId: string | undefined) {\n Vue.provide(dummyMatchContext, Vue.ref(matchId))\n}\n\n/**\n * Retrieves the dummy match ID from the component tree\n * This only exists so we can conditionally inject a value when we are not interested in the nearest match\n */\nexport function injectDummyMatch(): Vue.Ref<string | undefined> {\n return Vue.inject(dummyMatchContext, Vue.ref(undefined))\n}\n"],"names":["matchContext","Symbol","dummyMatchContext","injectMatch","Vue","inject","ref","undefined","injectDummyMatch"],"mappings":";MAIaA,eAAeC,OAAO,qBAAqB;MAK3CC,oBAAoBD,OAC/B,0BACF;AAYO,SAASE,cAA2C;AACzD,SAAOC,IAAIC,OAAOL,cAAcI,IAAIE,IAAIC,MAAS,CAAC;AACpD;AAaO,SAASC,mBAAgD;AAC9D,SAAOJ,IAAIC,OAAOH,mBAAmBE,IAAIE,IAAIC,MAAS,CAAC;AACzD;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NotFoundError } from '@tanstack/router-core';
|
|
2
|
+
import * as Vue from 'vue';
|
|
3
|
+
export declare function CatchNotFound(props: {
|
|
4
|
+
fallback?: (error: NotFoundError) => Vue.VNode;
|
|
5
|
+
onCatch?: (error: Error) => void;
|
|
6
|
+
children: Vue.VNode;
|
|
7
|
+
}): Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const DefaultGlobalNotFound: Vue.DefineComponent<{}, () => Vue.VNode<Vue.RendererNode, Vue.RendererElement, {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}>, {}, {}, {}, Vue.ComponentOptionsMixin, Vue.ComponentOptionsMixin, {}, string, Vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, Vue.ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as Vue from "vue";
|
|
2
|
+
import { isNotFound } from "@tanstack/router-core";
|
|
3
|
+
import { CatchBoundary } from "./CatchBoundary.js";
|
|
4
|
+
import { useRouterState } from "./useRouterState.js";
|
|
5
|
+
function CatchNotFound(props) {
|
|
6
|
+
const resetKey = useRouterState({
|
|
7
|
+
select: (s) => `not-found-${s.location.pathname}-${s.status}`
|
|
8
|
+
});
|
|
9
|
+
const errorComponentFn = (componentProps) => {
|
|
10
|
+
const error = componentProps.error;
|
|
11
|
+
if (isNotFound(error)) {
|
|
12
|
+
if (props.fallback) {
|
|
13
|
+
return props.fallback(error);
|
|
14
|
+
}
|
|
15
|
+
return Vue.h("p", null, "Not Found");
|
|
16
|
+
} else {
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
return Vue.h(CatchBoundary, {
|
|
21
|
+
getResetKey: () => resetKey.value,
|
|
22
|
+
onCatch: (error) => {
|
|
23
|
+
if (isNotFound(error)) {
|
|
24
|
+
if (props.onCatch) {
|
|
25
|
+
props.onCatch(error);
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
errorComponent: errorComponentFn,
|
|
32
|
+
children: props.children
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const DefaultGlobalNotFound = Vue.defineComponent({
|
|
36
|
+
name: "DefaultGlobalNotFound",
|
|
37
|
+
setup() {
|
|
38
|
+
return () => Vue.h("p", null, "Not Found");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
export {
|
|
42
|
+
CatchNotFound,
|
|
43
|
+
DefaultGlobalNotFound
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=not-found.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found.js","sources":["../../src/not-found.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport { isNotFound } from '@tanstack/router-core'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouterState } from './useRouterState'\nimport type { ErrorComponentProps, NotFoundError } from '@tanstack/router-core'\n\nexport function CatchNotFound(props: {\n fallback?: (error: NotFoundError) => Vue.VNode\n onCatch?: (error: Error) => void\n children: Vue.VNode\n}) {\n // TODO: Some way for the user to programmatically reset the not-found boundary?\n const resetKey = useRouterState({\n select: (s) => `not-found-${s.location.pathname}-${s.status}`,\n })\n\n // Create a function that returns a VNode to match the SyncRouteComponent signature\n const errorComponentFn = (componentProps: ErrorComponentProps) => {\n const error = componentProps.error\n\n if (isNotFound(error)) {\n // If a fallback is provided, use it\n if (props.fallback) {\n return props.fallback(error as NotFoundError)\n }\n // Otherwise return a default not found message\n return Vue.h('p', null, 'Not Found')\n } else {\n // Re-throw non-NotFound errors\n throw error\n }\n }\n\n return Vue.h(CatchBoundary, {\n getResetKey: () => resetKey.value,\n onCatch: (error: Error) => {\n if (isNotFound(error)) {\n if (props.onCatch) {\n props.onCatch(error)\n }\n } else {\n throw error\n }\n },\n errorComponent: errorComponentFn,\n children: props.children,\n })\n}\n\nexport const DefaultGlobalNotFound = Vue.defineComponent({\n name: 'DefaultGlobalNotFound',\n setup() {\n return () => Vue.h('p', null, 'Not Found')\n },\n})\n"],"names":["CatchNotFound","props","resetKey","useRouterState","select","s","location","pathname","status","errorComponentFn","componentProps","error","isNotFound","fallback","Vue","h","CatchBoundary","getResetKey","value","onCatch","errorComponent","children","DefaultGlobalNotFound","defineComponent","name","setup"],"mappings":";;;;AAMO,SAASA,cAAcC,OAI3B;AAED,QAAMC,WAAWC,eAAe;AAAA,IAC9BC,QAASC,OAAM,aAAaA,EAAEC,SAASC,QAAQ,IAAIF,EAAEG,MAAM;AAAA,EAC7D,CAAC;AAGD,QAAMC,mBAAoBC,oBAAwC;AAChE,UAAMC,QAAQD,eAAeC;AAE7B,QAAIC,WAAWD,KAAK,GAAG;AAErB,UAAIV,MAAMY,UAAU;AAClB,eAAOZ,MAAMY,SAASF,KAAsB;AAAA,MAC9C;AAEA,aAAOG,IAAIC,EAAE,KAAK,MAAM,WAAW;AAAA,IACrC,OAAO;AAEL,YAAMJ;AAAAA,IACR;AAAA,EACF;AAEA,SAAOG,IAAIC,EAAEC,eAAe;AAAA,IAC1BC,aAAaA,MAAMf,SAASgB;AAAAA,IAC5BC,SAAUR,WAAiB;AACzB,UAAIC,WAAWD,KAAK,GAAG;AACrB,YAAIV,MAAMkB,SAAS;AACjBlB,gBAAMkB,QAAQR,KAAK;AAAA,QACrB;AAAA,MACF,OAAO;AACL,cAAMA;AAAAA,MACR;AAAA,IACF;AAAA,IACAS,gBAAgBX;AAAAA,IAChBY,UAAUpB,MAAMoB;AAAAA,EAClB,CAAC;AACH;MAEaC,wBAAwBR,IAAIS,gBAAgB;AAAA,EACvDC,MAAM;AAAA,EACNC,QAAQ;AACN,WAAO,MAAMX,IAAIC,EAAE,KAAK,MAAM,WAAW;AAAA,EAC3C;AACF,CAAC;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnyRoute, AnyRouter } from '@tanstack/router-core';
|
|
2
|
+
import * as Vue from 'vue';
|
|
3
|
+
/**
|
|
4
|
+
* Renders a not found component for a route when no matching route is found.
|
|
5
|
+
*
|
|
6
|
+
* @param router - The router instance containing the route configuration
|
|
7
|
+
* @param route - The route that triggered the not found state
|
|
8
|
+
* @param data - Additional data to pass to the not found component
|
|
9
|
+
* @returns The rendered not found component or a default fallback component
|
|
10
|
+
*/
|
|
11
|
+
export declare function renderRouteNotFound(router: AnyRouter, route: AnyRoute, data: any): Vue.VNode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as Vue from "vue";
|
|
2
|
+
import warning from "tiny-warning";
|
|
3
|
+
import { DefaultGlobalNotFound } from "./not-found.js";
|
|
4
|
+
function renderRouteNotFound(router, route, data) {
|
|
5
|
+
if (!route.options.notFoundComponent) {
|
|
6
|
+
if (router.options.defaultNotFoundComponent) {
|
|
7
|
+
return Vue.h(router.options.defaultNotFoundComponent, data);
|
|
8
|
+
}
|
|
9
|
+
if (process.env.NODE_ENV === "development") {
|
|
10
|
+
warning(route.options.notFoundComponent, `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<p>Not Found</p>)`);
|
|
11
|
+
}
|
|
12
|
+
return Vue.h(DefaultGlobalNotFound);
|
|
13
|
+
}
|
|
14
|
+
return Vue.h(route.options.notFoundComponent, data);
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
renderRouteNotFound
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=renderRouteNotFound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderRouteNotFound.js","sources":["../../src/renderRouteNotFound.tsx"],"sourcesContent":["import * as Vue from 'vue'\nimport warning from 'tiny-warning'\nimport { DefaultGlobalNotFound } from './not-found'\nimport type { AnyRoute, AnyRouter } from '@tanstack/router-core'\n\n/**\n * Renders a not found component for a route when no matching route is found.\n *\n * @param router - The router instance containing the route configuration\n * @param route - The route that triggered the not found state\n * @param data - Additional data to pass to the not found component\n * @returns The rendered not found component or a default fallback component\n */\nexport function renderRouteNotFound(\n router: AnyRouter,\n route: AnyRoute,\n data: any,\n): Vue.VNode {\n if (!route.options.notFoundComponent) {\n if (router.options.defaultNotFoundComponent) {\n return Vue.h(router.options.defaultNotFoundComponent as any, data)\n }\n\n if (process.env.NODE_ENV === 'development') {\n warning(\n route.options.notFoundComponent,\n `A notFoundError was encountered on the route with ID \"${route.id}\", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<p>Not Found</p>)`,\n )\n }\n\n return Vue.h(DefaultGlobalNotFound)\n }\n\n return Vue.h(route.options.notFoundComponent as any, data)\n}\n"],"names":["renderRouteNotFound","router","route","data","options","notFoundComponent","defaultNotFoundComponent","Vue","h","process","env","NODE_ENV","warning","id","DefaultGlobalNotFound"],"mappings":";;;AAaO,SAASA,oBACdC,QACAC,OACAC,MACW;AACX,MAAI,CAACD,MAAME,QAAQC,mBAAmB;AACpC,QAAIJ,OAAOG,QAAQE,0BAA0B;AAC3C,aAAOC,IAAIC,EAAEP,OAAOG,QAAQE,0BAAiCH,IAAI;AAAA,IACnE;AAEA,QAAIM,QAAQC,IAAIC,aAAa,eAAe;AAC1CC,cACEV,MAAME,QAAQC,mBACd,yDAAyDH,MAAMW,EAAE,oPACnE;AAAA,IACF;AAEA,WAAON,IAAIC,EAAEM,qBAAqB;AAAA,EACpC;AAEA,SAAOP,IAAIC,EAAEN,MAAME,QAAQC,mBAA0BF,IAAI;AAC3D;"}
|