@tanstack/react-router 1.147.1 → 1.147.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/HeadContent.cjs +3 -201
- package/dist/cjs/HeadContent.cjs.map +1 -1
- package/dist/cjs/HeadContent.d.cts +0 -6
- package/dist/cjs/HeadContent.dev.cjs +41 -0
- package/dist/cjs/HeadContent.dev.cjs.map +1 -0
- package/dist/cjs/HeadContent.dev.d.cts +10 -0
- package/dist/cjs/awaited.cjs +3 -2
- package/dist/cjs/awaited.cjs.map +1 -1
- package/dist/cjs/headContentUtils.cjs +185 -0
- package/dist/cjs/headContentUtils.cjs.map +1 -0
- package/dist/cjs/headContentUtils.d.cts +7 -0
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/index.dev.cjs +264 -0
- package/dist/cjs/index.dev.cjs.map +1 -0
- package/dist/cjs/index.dev.d.cts +2 -0
- package/dist/cjs/lazyRouteComponent.cjs +3 -2
- package/dist/cjs/lazyRouteComponent.cjs.map +1 -1
- package/dist/cjs/utils.cjs +3 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +5 -0
- package/dist/esm/HeadContent.d.ts +0 -6
- package/dist/esm/HeadContent.dev.d.ts +10 -0
- package/dist/esm/HeadContent.dev.js +25 -0
- package/dist/esm/HeadContent.dev.js.map +1 -0
- package/dist/esm/HeadContent.js +4 -186
- package/dist/esm/HeadContent.js.map +1 -1
- package/dist/esm/awaited.js +3 -2
- package/dist/esm/awaited.js.map +1 -1
- package/dist/esm/headContentUtils.d.ts +7 -0
- package/dist/esm/headContentUtils.js +168 -0
- package/dist/esm/headContentUtils.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.dev.d.ts +2 -0
- package/dist/esm/index.dev.js +144 -0
- package/dist/esm/index.dev.js.map +1 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lazyRouteComponent.js +3 -2
- package/dist/esm/lazyRouteComponent.js.map +1 -1
- package/dist/esm/utils.d.ts +5 -0
- package/dist/esm/utils.js +3 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -1
- package/src/HeadContent.dev.tsx +46 -0
- package/src/HeadContent.tsx +1 -245
- package/src/awaited.tsx +3 -3
- package/src/headContentUtils.tsx +217 -0
- package/src/index.dev.tsx +6 -0
- package/src/index.tsx +1 -0
- package/src/lazyRouteComponent.tsx +3 -3
- package/src/utils.ts +14 -0
package/dist/esm/awaited.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { defer, TSR_DEFERRED_PROMISE } from "@tanstack/router-core";
|
|
4
|
+
import { reactUse } from "./utils.js";
|
|
4
5
|
function useAwaited({ promise: _promise }) {
|
|
5
|
-
if (
|
|
6
|
-
const data =
|
|
6
|
+
if (reactUse) {
|
|
7
|
+
const data = reactUse(_promise);
|
|
7
8
|
return data;
|
|
8
9
|
}
|
|
9
10
|
const promise = defer(_promise);
|
package/dist/esm/awaited.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awaited.js","sources":["../../src/awaited.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { TSR_DEFERRED_PROMISE, defer } from '@tanstack/router-core'\n\nexport type AwaitOptions<T> = {\n promise: Promise<T>\n}\n\n/** Suspend until a deferred promise resolves or rejects and return its data. */\nexport function useAwaited<T>({ promise: _promise }: AwaitOptions<T>): T {\n
|
|
1
|
+
{"version":3,"file":"awaited.js","sources":["../../src/awaited.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { TSR_DEFERRED_PROMISE, defer } from '@tanstack/router-core'\nimport { reactUse } from './utils'\n\nexport type AwaitOptions<T> = {\n promise: Promise<T>\n}\n\n/** Suspend until a deferred promise resolves or rejects and return its data. */\nexport function useAwaited<T>({ promise: _promise }: AwaitOptions<T>): T {\n if (reactUse) {\n const data = reactUse(_promise)\n return data\n }\n const promise = defer(_promise)\n\n if (promise[TSR_DEFERRED_PROMISE].status === 'pending') {\n throw promise\n }\n\n if (promise[TSR_DEFERRED_PROMISE].status === 'error') {\n throw promise[TSR_DEFERRED_PROMISE].error\n }\n\n return promise[TSR_DEFERRED_PROMISE].data\n}\n\n/**\n * Component that suspends on a deferred promise and renders its child with\n * the resolved value. Optionally provides a Suspense fallback.\n */\nexport function Await<T>(\n props: AwaitOptions<T> & {\n fallback?: React.ReactNode\n children: (result: T) => React.ReactNode\n },\n) {\n const inner = <AwaitInner {...props} />\n if (props.fallback) {\n return <React.Suspense fallback={props.fallback}>{inner}</React.Suspense>\n }\n return inner\n}\n\nfunction AwaitInner<T>(\n props: AwaitOptions<T> & {\n fallback?: React.ReactNode\n children: (result: T) => React.ReactNode\n },\n): React.JSX.Element {\n const data = useAwaited(props)\n\n return props.children(data) as React.JSX.Element\n}\n"],"names":[],"mappings":";;;;AAUO,SAAS,WAAc,EAAE,SAAS,YAAgC;AACvE,MAAI,UAAU;AACZ,UAAM,OAAO,SAAS,QAAQ;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,QAAQ;AAE9B,MAAI,QAAQ,oBAAoB,EAAE,WAAW,WAAW;AACtD,UAAM;AAAA,EACR;AAEA,MAAI,QAAQ,oBAAoB,EAAE,WAAW,SAAS;AACpD,UAAM,QAAQ,oBAAoB,EAAE;AAAA,EACtC;AAEA,SAAO,QAAQ,oBAAoB,EAAE;AACvC;AAMO,SAAS,MACd,OAIA;AACA,QAAM,QAAQ,oBAAC,YAAA,EAAY,GAAG,MAAA,CAAO;AACrC,MAAI,MAAM,UAAU;AAClB,+BAAQ,MAAM,UAAN,EAAe,UAAU,MAAM,UAAW,UAAA,OAAM;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,WACP,OAImB;AACnB,QAAM,OAAO,WAAW,KAAK;AAE7B,SAAO,MAAM,SAAS,IAAI;AAC5B;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RouterManagedTag } from '@tanstack/router-core';
|
|
2
|
+
/**
|
|
3
|
+
* Build the list of head/link/meta/script tags to render for active matches.
|
|
4
|
+
* Used internally by `HeadContent`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const useTags: () => RouterManagedTag[];
|
|
7
|
+
export declare function uniqBy<T>(arr: Array<T>, fn: (item: T) => string): T[];
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { escapeHtml } from "@tanstack/router-core";
|
|
3
|
+
import { useRouter } from "./useRouter.js";
|
|
4
|
+
import { useRouterState } from "./useRouterState.js";
|
|
5
|
+
const useTags = () => {
|
|
6
|
+
const router = useRouter();
|
|
7
|
+
const nonce = router.options.ssr?.nonce;
|
|
8
|
+
const routeMeta = useRouterState({
|
|
9
|
+
select: (state) => {
|
|
10
|
+
return state.matches.map((match) => match.meta).filter(Boolean);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
const meta = React.useMemo(() => {
|
|
14
|
+
const resultMeta = [];
|
|
15
|
+
const metaByAttribute = {};
|
|
16
|
+
let title;
|
|
17
|
+
for (let i = routeMeta.length - 1; i >= 0; i--) {
|
|
18
|
+
const metas = routeMeta[i];
|
|
19
|
+
for (let j = metas.length - 1; j >= 0; j--) {
|
|
20
|
+
const m = metas[j];
|
|
21
|
+
if (!m) continue;
|
|
22
|
+
if (m.title) {
|
|
23
|
+
if (!title) {
|
|
24
|
+
title = {
|
|
25
|
+
tag: "title",
|
|
26
|
+
children: m.title
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
} else if ("script:ld+json" in m) {
|
|
30
|
+
try {
|
|
31
|
+
const json = JSON.stringify(m["script:ld+json"]);
|
|
32
|
+
resultMeta.push({
|
|
33
|
+
tag: "script",
|
|
34
|
+
attrs: {
|
|
35
|
+
type: "application/ld+json"
|
|
36
|
+
},
|
|
37
|
+
children: escapeHtml(json)
|
|
38
|
+
});
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
const attribute = m.name ?? m.property;
|
|
43
|
+
if (attribute) {
|
|
44
|
+
if (metaByAttribute[attribute]) {
|
|
45
|
+
continue;
|
|
46
|
+
} else {
|
|
47
|
+
metaByAttribute[attribute] = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
resultMeta.push({
|
|
51
|
+
tag: "meta",
|
|
52
|
+
attrs: {
|
|
53
|
+
...m,
|
|
54
|
+
nonce
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (title) {
|
|
61
|
+
resultMeta.push(title);
|
|
62
|
+
}
|
|
63
|
+
if (nonce) {
|
|
64
|
+
resultMeta.push({
|
|
65
|
+
tag: "meta",
|
|
66
|
+
attrs: {
|
|
67
|
+
property: "csp-nonce",
|
|
68
|
+
content: nonce
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
resultMeta.reverse();
|
|
73
|
+
return resultMeta;
|
|
74
|
+
}, [routeMeta, nonce]);
|
|
75
|
+
const links = useRouterState({
|
|
76
|
+
select: (state) => {
|
|
77
|
+
const constructed = state.matches.map((match) => match.links).filter(Boolean).flat(1).map((link) => ({
|
|
78
|
+
tag: "link",
|
|
79
|
+
attrs: {
|
|
80
|
+
...link,
|
|
81
|
+
nonce
|
|
82
|
+
}
|
|
83
|
+
}));
|
|
84
|
+
const manifest = router.ssr?.manifest;
|
|
85
|
+
const assets = state.matches.map((match) => manifest?.routes[match.routeId]?.assets ?? []).filter(Boolean).flat(1).filter((asset) => asset.tag === "link").map(
|
|
86
|
+
(asset) => ({
|
|
87
|
+
tag: "link",
|
|
88
|
+
attrs: {
|
|
89
|
+
...asset.attrs,
|
|
90
|
+
suppressHydrationWarning: true,
|
|
91
|
+
nonce
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
return [...constructed, ...assets];
|
|
96
|
+
},
|
|
97
|
+
structuralSharing: true
|
|
98
|
+
});
|
|
99
|
+
const preloadLinks = useRouterState({
|
|
100
|
+
select: (state) => {
|
|
101
|
+
const preloadLinks2 = [];
|
|
102
|
+
state.matches.map((match) => router.looseRoutesById[match.routeId]).forEach(
|
|
103
|
+
(route) => router.ssr?.manifest?.routes[route.id]?.preloads?.filter(Boolean).forEach((preload) => {
|
|
104
|
+
preloadLinks2.push({
|
|
105
|
+
tag: "link",
|
|
106
|
+
attrs: {
|
|
107
|
+
rel: "modulepreload",
|
|
108
|
+
href: preload,
|
|
109
|
+
nonce
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
return preloadLinks2;
|
|
115
|
+
},
|
|
116
|
+
structuralSharing: true
|
|
117
|
+
});
|
|
118
|
+
const styles = useRouterState({
|
|
119
|
+
select: (state) => state.matches.map((match) => match.styles).flat(1).filter(Boolean).map(({ children, ...attrs }) => ({
|
|
120
|
+
tag: "style",
|
|
121
|
+
attrs: {
|
|
122
|
+
...attrs,
|
|
123
|
+
nonce
|
|
124
|
+
},
|
|
125
|
+
children
|
|
126
|
+
})),
|
|
127
|
+
structuralSharing: true
|
|
128
|
+
});
|
|
129
|
+
const headScripts = useRouterState({
|
|
130
|
+
select: (state) => state.matches.map((match) => match.headScripts).flat(1).filter(Boolean).map(({ children, ...script }) => ({
|
|
131
|
+
tag: "script",
|
|
132
|
+
attrs: {
|
|
133
|
+
...script,
|
|
134
|
+
nonce
|
|
135
|
+
},
|
|
136
|
+
children
|
|
137
|
+
})),
|
|
138
|
+
structuralSharing: true
|
|
139
|
+
});
|
|
140
|
+
return uniqBy(
|
|
141
|
+
[
|
|
142
|
+
...meta,
|
|
143
|
+
...preloadLinks,
|
|
144
|
+
...links,
|
|
145
|
+
...styles,
|
|
146
|
+
...headScripts
|
|
147
|
+
],
|
|
148
|
+
(d) => {
|
|
149
|
+
return JSON.stringify(d);
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
function uniqBy(arr, fn) {
|
|
154
|
+
const seen = /* @__PURE__ */ new Set();
|
|
155
|
+
return arr.filter((item) => {
|
|
156
|
+
const key = fn(item);
|
|
157
|
+
if (seen.has(key)) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
seen.add(key);
|
|
161
|
+
return true;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
export {
|
|
165
|
+
uniqBy,
|
|
166
|
+
useTags
|
|
167
|
+
};
|
|
168
|
+
//# sourceMappingURL=headContentUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headContentUtils.js","sources":["../../src/headContentUtils.tsx"],"sourcesContent":["import * as React from 'react'\nimport { escapeHtml } from '@tanstack/router-core'\nimport { useRouter } from './useRouter'\nimport { useRouterState } from './useRouterState'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\n/**\n * Build the list of head/link/meta/script tags to render for active matches.\n * Used internally by `HeadContent`.\n */\nexport const useTags = () => {\n const router = useRouter()\n const nonce = router.options.ssr?.nonce\n const routeMeta = useRouterState({\n select: (state) => {\n return state.matches.map((match) => match.meta!).filter(Boolean)\n },\n })\n\n const meta: Array<RouterManagedTag> = React.useMemo(() => {\n const resultMeta: Array<RouterManagedTag> = []\n const metaByAttribute: Record<string, true> = {}\n let title: RouterManagedTag | undefined\n for (let i = routeMeta.length - 1; i >= 0; i--) {\n const metas = routeMeta[i]!\n for (let j = metas.length - 1; j >= 0; j--) {\n const m = metas[j]\n if (!m) continue\n\n if (m.title) {\n if (!title) {\n title = {\n tag: 'title',\n children: m.title,\n }\n }\n } else if ('script:ld+json' in m) {\n // Handle JSON-LD structured data\n // Content is HTML-escaped to prevent XSS when injected via dangerouslySetInnerHTML\n try {\n const json = JSON.stringify(m['script:ld+json'])\n resultMeta.push({\n tag: 'script',\n attrs: {\n type: 'application/ld+json',\n },\n children: escapeHtml(json),\n })\n } catch {\n // Skip invalid JSON-LD objects\n }\n } else {\n const attribute = m.name ?? m.property\n if (attribute) {\n if (metaByAttribute[attribute]) {\n continue\n } else {\n metaByAttribute[attribute] = true\n }\n }\n\n resultMeta.push({\n tag: 'meta',\n attrs: {\n ...m,\n nonce,\n },\n })\n }\n }\n }\n\n if (title) {\n resultMeta.push(title)\n }\n\n if (nonce) {\n resultMeta.push({\n tag: 'meta',\n attrs: {\n property: 'csp-nonce',\n content: nonce,\n },\n })\n }\n resultMeta.reverse()\n\n return resultMeta\n }, [routeMeta, nonce])\n\n const links = useRouterState({\n select: (state) => {\n const constructed = state.matches\n .map((match) => match.links!)\n .filter(Boolean)\n .flat(1)\n .map((link) => ({\n tag: 'link',\n attrs: {\n ...link,\n nonce,\n },\n })) satisfies Array<RouterManagedTag>\n\n const manifest = router.ssr?.manifest\n\n // These are the assets extracted from the ViteManifest\n // using the `startManifestPlugin`\n const assets = state.matches\n .map((match) => manifest?.routes[match.routeId]?.assets ?? [])\n .filter(Boolean)\n .flat(1)\n .filter((asset) => asset.tag === 'link')\n .map(\n (asset) =>\n ({\n tag: 'link',\n attrs: {\n ...asset.attrs,\n suppressHydrationWarning: true,\n nonce,\n },\n }) satisfies RouterManagedTag,\n )\n\n return [...constructed, ...assets]\n },\n structuralSharing: true as any,\n })\n\n const preloadLinks = useRouterState({\n select: (state) => {\n const preloadLinks: Array<RouterManagedTag> = []\n\n state.matches\n .map((match) => router.looseRoutesById[match.routeId]!)\n .forEach((route) =>\n router.ssr?.manifest?.routes[route.id]?.preloads\n ?.filter(Boolean)\n .forEach((preload) => {\n preloadLinks.push({\n tag: 'link',\n attrs: {\n rel: 'modulepreload',\n href: preload,\n nonce,\n },\n })\n }),\n )\n\n return preloadLinks\n },\n structuralSharing: true as any,\n })\n\n const styles = useRouterState({\n select: (state) =>\n (\n state.matches\n .map((match) => match.styles!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...attrs }) => ({\n tag: 'style',\n attrs: {\n ...attrs,\n nonce,\n },\n children,\n })),\n structuralSharing: true as any,\n })\n\n const headScripts: Array<RouterManagedTag> = useRouterState({\n select: (state) =>\n (\n state.matches\n .map((match) => match.headScripts!)\n .flat(1)\n .filter(Boolean) as Array<RouterManagedTag>\n ).map(({ children, ...script }) => ({\n tag: 'script',\n attrs: {\n ...script,\n nonce,\n },\n children,\n })),\n structuralSharing: true as any,\n })\n\n return uniqBy(\n [\n ...meta,\n ...preloadLinks,\n ...links,\n ...styles,\n ...headScripts,\n ] as Array<RouterManagedTag>,\n (d) => {\n return JSON.stringify(d)\n },\n )\n}\n\nexport function uniqBy<T>(arr: Array<T>, fn: (item: T) => string) {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = fn(item)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n"],"names":["preloadLinks"],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ export type { ValidateFromPath, ValidateToPath, ValidateSearch, ValidateParams,
|
|
|
48
48
|
export { ScriptOnce } from './ScriptOnce.js';
|
|
49
49
|
export { Asset } from './Asset.js';
|
|
50
50
|
export { HeadContent } from './HeadContent.js';
|
|
51
|
+
export { useTags } from './headContentUtils.js';
|
|
51
52
|
export { Scripts } from './Scripts.js';
|
|
52
53
|
export type * from './ssr/serializer.js';
|
|
53
54
|
export { composeRewrites } from '@tanstack/router-core';
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { PathParamError, SearchParamError, TSR_DEFERRED_PROMISE, cleanPath, componentTypes, composeRewrites, createControlledPromise, createRouterConfig, createSerializationAdapter, deepEqual, defaultParseSearch, defaultSerializeError, defaultStringifySearch, defer, functionalUpdate, getInitialRouterState, interpolatePath, isMatch, isNotFound, isPlainArray, isPlainObject, isRedirect, joinPaths, lazyFn, notFound, parseSearchWith, redirect, replaceEqualDeep, resolvePath, retainSearchParams, rootRouteId, stringifySearchWith, stripSearchParams, trimPath, trimPathLeft, trimPathRight } from "@tanstack/router-core";
|
|
2
|
+
import { createBrowserHistory, createHashHistory, createHistory, createMemoryHistory } from "@tanstack/history";
|
|
3
|
+
import { Await, useAwaited } from "./awaited.js";
|
|
4
|
+
import { CatchBoundary, ErrorComponent } from "./CatchBoundary.js";
|
|
5
|
+
import { ClientOnly, useHydrated } from "./ClientOnly.js";
|
|
6
|
+
import { FileRoute, FileRouteLoader, LazyRoute, createFileRoute, createLazyFileRoute, createLazyRoute } from "./fileRoute.js";
|
|
7
|
+
import { lazyRouteComponent } from "./lazyRouteComponent.js";
|
|
8
|
+
import { Link, createLink, linkOptions, useLinkProps } from "./link.js";
|
|
9
|
+
import { MatchRoute, Matches, useChildMatches, useMatchRoute, useMatches, useParentMatches } from "./Matches.js";
|
|
10
|
+
import { matchContext } from "./matchContext.js";
|
|
11
|
+
import { Match, Outlet } from "./Match.js";
|
|
12
|
+
import { useMatch } from "./useMatch.js";
|
|
13
|
+
import { useLoaderDeps } from "./useLoaderDeps.js";
|
|
14
|
+
import { useLoaderData } from "./useLoaderData.js";
|
|
15
|
+
import { NotFoundRoute, RootRoute, Route, RouteApi, createRootRoute, createRootRouteWithContext, createRoute, createRouteMask, getRouteApi, rootRouteWithContext } from "./route.js";
|
|
16
|
+
import { Router, createRouter } from "./router.js";
|
|
17
|
+
import { RouterContextProvider, RouterProvider } from "./RouterProvider.js";
|
|
18
|
+
import { ScrollRestoration, useElementScrollRestoration } from "./ScrollRestoration.js";
|
|
19
|
+
import { Block, useBlocker } from "./useBlocker.js";
|
|
20
|
+
import { Navigate, useNavigate } from "./useNavigate.js";
|
|
21
|
+
import { useParams } from "./useParams.js";
|
|
22
|
+
import { useSearch } from "./useSearch.js";
|
|
23
|
+
import { getRouterContext } from "./routerContext.js";
|
|
24
|
+
import { useRouteContext } from "./useRouteContext.js";
|
|
25
|
+
import { useRouter } from "./useRouter.js";
|
|
26
|
+
import { useRouterState } from "./useRouterState.js";
|
|
27
|
+
import { useLocation } from "./useLocation.js";
|
|
28
|
+
import { useCanGoBack } from "./useCanGoBack.js";
|
|
29
|
+
import { useLayoutEffect, useStableCallback } from "./utils.js";
|
|
30
|
+
import { CatchNotFound, DefaultGlobalNotFound } from "./not-found.js";
|
|
31
|
+
import { ScriptOnce } from "./ScriptOnce.js";
|
|
32
|
+
import { Asset } from "./Asset.js";
|
|
33
|
+
import { useTags } from "./headContentUtils.js";
|
|
34
|
+
import { Scripts } from "./Scripts.js";
|
|
35
|
+
import { HeadContent } from "./HeadContent.dev.js";
|
|
36
|
+
export {
|
|
37
|
+
Asset,
|
|
38
|
+
Await,
|
|
39
|
+
Block,
|
|
40
|
+
CatchBoundary,
|
|
41
|
+
CatchNotFound,
|
|
42
|
+
ClientOnly,
|
|
43
|
+
DefaultGlobalNotFound,
|
|
44
|
+
ErrorComponent,
|
|
45
|
+
FileRoute,
|
|
46
|
+
FileRouteLoader,
|
|
47
|
+
HeadContent,
|
|
48
|
+
LazyRoute,
|
|
49
|
+
Link,
|
|
50
|
+
Match,
|
|
51
|
+
MatchRoute,
|
|
52
|
+
Matches,
|
|
53
|
+
Navigate,
|
|
54
|
+
NotFoundRoute,
|
|
55
|
+
Outlet,
|
|
56
|
+
PathParamError,
|
|
57
|
+
RootRoute,
|
|
58
|
+
Route,
|
|
59
|
+
RouteApi,
|
|
60
|
+
Router,
|
|
61
|
+
RouterContextProvider,
|
|
62
|
+
RouterProvider,
|
|
63
|
+
ScriptOnce,
|
|
64
|
+
Scripts,
|
|
65
|
+
ScrollRestoration,
|
|
66
|
+
SearchParamError,
|
|
67
|
+
TSR_DEFERRED_PROMISE,
|
|
68
|
+
cleanPath,
|
|
69
|
+
componentTypes,
|
|
70
|
+
composeRewrites,
|
|
71
|
+
createBrowserHistory,
|
|
72
|
+
createControlledPromise,
|
|
73
|
+
createFileRoute,
|
|
74
|
+
createHashHistory,
|
|
75
|
+
createHistory,
|
|
76
|
+
createLazyFileRoute,
|
|
77
|
+
createLazyRoute,
|
|
78
|
+
createLink,
|
|
79
|
+
createMemoryHistory,
|
|
80
|
+
createRootRoute,
|
|
81
|
+
createRootRouteWithContext,
|
|
82
|
+
createRoute,
|
|
83
|
+
createRouteMask,
|
|
84
|
+
createRouter,
|
|
85
|
+
createRouterConfig,
|
|
86
|
+
createSerializationAdapter,
|
|
87
|
+
deepEqual,
|
|
88
|
+
defaultParseSearch,
|
|
89
|
+
defaultSerializeError,
|
|
90
|
+
defaultStringifySearch,
|
|
91
|
+
defer,
|
|
92
|
+
functionalUpdate,
|
|
93
|
+
getInitialRouterState,
|
|
94
|
+
getRouteApi,
|
|
95
|
+
getRouterContext,
|
|
96
|
+
interpolatePath,
|
|
97
|
+
isMatch,
|
|
98
|
+
isNotFound,
|
|
99
|
+
isPlainArray,
|
|
100
|
+
isPlainObject,
|
|
101
|
+
isRedirect,
|
|
102
|
+
joinPaths,
|
|
103
|
+
lazyFn,
|
|
104
|
+
lazyRouteComponent,
|
|
105
|
+
linkOptions,
|
|
106
|
+
matchContext,
|
|
107
|
+
notFound,
|
|
108
|
+
parseSearchWith,
|
|
109
|
+
redirect,
|
|
110
|
+
replaceEqualDeep,
|
|
111
|
+
resolvePath,
|
|
112
|
+
retainSearchParams,
|
|
113
|
+
rootRouteId,
|
|
114
|
+
rootRouteWithContext,
|
|
115
|
+
stringifySearchWith,
|
|
116
|
+
stripSearchParams,
|
|
117
|
+
trimPath,
|
|
118
|
+
trimPathLeft,
|
|
119
|
+
trimPathRight,
|
|
120
|
+
useAwaited,
|
|
121
|
+
useBlocker,
|
|
122
|
+
useCanGoBack,
|
|
123
|
+
useChildMatches,
|
|
124
|
+
useElementScrollRestoration,
|
|
125
|
+
useHydrated,
|
|
126
|
+
useLayoutEffect,
|
|
127
|
+
useLinkProps,
|
|
128
|
+
useLoaderData,
|
|
129
|
+
useLoaderDeps,
|
|
130
|
+
useLocation,
|
|
131
|
+
useMatch,
|
|
132
|
+
useMatchRoute,
|
|
133
|
+
useMatches,
|
|
134
|
+
useNavigate,
|
|
135
|
+
useParams,
|
|
136
|
+
useParentMatches,
|
|
137
|
+
useRouteContext,
|
|
138
|
+
useRouter,
|
|
139
|
+
useRouterState,
|
|
140
|
+
useSearch,
|
|
141
|
+
useStableCallback,
|
|
142
|
+
useTags
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=index.dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.dev.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/index.js
CHANGED
|
@@ -31,6 +31,7 @@ import { CatchNotFound, DefaultGlobalNotFound } from "./not-found.js";
|
|
|
31
31
|
import { ScriptOnce } from "./ScriptOnce.js";
|
|
32
32
|
import { Asset } from "./Asset.js";
|
|
33
33
|
import { HeadContent } from "./HeadContent.js";
|
|
34
|
+
import { useTags } from "./headContentUtils.js";
|
|
34
35
|
import { Scripts } from "./Scripts.js";
|
|
35
36
|
export {
|
|
36
37
|
Asset,
|
|
@@ -137,6 +138,7 @@ export {
|
|
|
137
138
|
useRouter,
|
|
138
139
|
useRouterState,
|
|
139
140
|
useSearch,
|
|
140
|
-
useStableCallback
|
|
141
|
+
useStableCallback,
|
|
142
|
+
useTags
|
|
141
143
|
};
|
|
142
144
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { isModuleNotFoundError } from "@tanstack/router-core";
|
|
3
|
+
import { reactUse } from "./utils.js";
|
|
3
4
|
function lazyRouteComponent(importer, exportName) {
|
|
4
5
|
let loadPromise;
|
|
5
6
|
let comp;
|
|
@@ -35,8 +36,8 @@ function lazyRouteComponent(importer, exportName) {
|
|
|
35
36
|
throw error;
|
|
36
37
|
}
|
|
37
38
|
if (!comp) {
|
|
38
|
-
if (
|
|
39
|
-
|
|
39
|
+
if (reactUse) {
|
|
40
|
+
reactUse(load());
|
|
40
41
|
} else {
|
|
41
42
|
throw load();
|
|
42
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazyRouteComponent.js","sources":["../../src/lazyRouteComponent.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isModuleNotFoundError } from '@tanstack/router-core'\nimport type { AsyncRouteComponent } from './route'\n\n/**\n * Wrap a dynamic import to create a route component that supports\n * `.preload()` and friendly reload-on-module-missing behavior.\n *\n * @param importer Function returning a module promise\n * @param exportName Named export to use (default: `default`)\n * @returns A lazy route component compatible with TanStack Router\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/lazyRouteComponentFunction\n */\nexport function lazyRouteComponent<\n T extends Record<string, any>,\n TKey extends keyof T = 'default',\n>(\n importer: () => Promise<T>,\n exportName?: TKey,\n): T[TKey] extends (props: infer TProps) => any\n ? AsyncRouteComponent<TProps>\n : never {\n let loadPromise: Promise<any> | undefined\n let comp: T[TKey] | T['default']\n let error: any\n let reload: boolean\n\n const load = () => {\n if (!loadPromise) {\n loadPromise = importer()\n .then((res) => {\n loadPromise = undefined\n comp = res[exportName ?? 'default']\n })\n .catch((err) => {\n // We don't want an error thrown from preload in this case, because\n // there's nothing we want to do about module not found during preload.\n // Record the error, the rest is handled during the render path.\n error = err\n // If the load fails due to module not found, it may mean a new version of\n // the build was deployed and the user's browser is still using an old version.\n // If this happens, the old version in the user's browser would have an outdated\n // URL to the lazy module.\n // In that case, we want to attempt one window refresh to get the latest.\n if (isModuleNotFoundError(error)) {\n if (\n error instanceof Error &&\n typeof window !== 'undefined' &&\n typeof sessionStorage !== 'undefined'\n ) {\n // Again, we want to reload one time on module not found error and not enter\n // a reload loop if there is some other issue besides an old deploy.\n // That's why we store our reload attempt in sessionStorage.\n // Use error.message as key because it contains the module path that failed.\n const storageKey = `tanstack_router_reload:${error.message}`\n if (!sessionStorage.getItem(storageKey)) {\n sessionStorage.setItem(storageKey, '1')\n reload = true\n }\n }\n }\n })\n }\n\n return loadPromise\n }\n\n const lazyComp = function Lazy(props: any) {\n // Now that we're out of preload and into actual render path,\n if (reload) {\n // If it was a module loading error,\n // throw eternal suspense while we wait for window to reload\n window.location.reload()\n throw new Promise(() => {})\n }\n if (error) {\n // Otherwise, just throw the error\n throw error\n }\n\n if (!comp) {\n
|
|
1
|
+
{"version":3,"file":"lazyRouteComponent.js","sources":["../../src/lazyRouteComponent.tsx"],"sourcesContent":["import * as React from 'react'\nimport { isModuleNotFoundError } from '@tanstack/router-core'\nimport { reactUse } from './utils'\nimport type { AsyncRouteComponent } from './route'\n\n/**\n * Wrap a dynamic import to create a route component that supports\n * `.preload()` and friendly reload-on-module-missing behavior.\n *\n * @param importer Function returning a module promise\n * @param exportName Named export to use (default: `default`)\n * @returns A lazy route component compatible with TanStack Router\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/lazyRouteComponentFunction\n */\nexport function lazyRouteComponent<\n T extends Record<string, any>,\n TKey extends keyof T = 'default',\n>(\n importer: () => Promise<T>,\n exportName?: TKey,\n): T[TKey] extends (props: infer TProps) => any\n ? AsyncRouteComponent<TProps>\n : never {\n let loadPromise: Promise<any> | undefined\n let comp: T[TKey] | T['default']\n let error: any\n let reload: boolean\n\n const load = () => {\n if (!loadPromise) {\n loadPromise = importer()\n .then((res) => {\n loadPromise = undefined\n comp = res[exportName ?? 'default']\n })\n .catch((err) => {\n // We don't want an error thrown from preload in this case, because\n // there's nothing we want to do about module not found during preload.\n // Record the error, the rest is handled during the render path.\n error = err\n // If the load fails due to module not found, it may mean a new version of\n // the build was deployed and the user's browser is still using an old version.\n // If this happens, the old version in the user's browser would have an outdated\n // URL to the lazy module.\n // In that case, we want to attempt one window refresh to get the latest.\n if (isModuleNotFoundError(error)) {\n if (\n error instanceof Error &&\n typeof window !== 'undefined' &&\n typeof sessionStorage !== 'undefined'\n ) {\n // Again, we want to reload one time on module not found error and not enter\n // a reload loop if there is some other issue besides an old deploy.\n // That's why we store our reload attempt in sessionStorage.\n // Use error.message as key because it contains the module path that failed.\n const storageKey = `tanstack_router_reload:${error.message}`\n if (!sessionStorage.getItem(storageKey)) {\n sessionStorage.setItem(storageKey, '1')\n reload = true\n }\n }\n }\n })\n }\n\n return loadPromise\n }\n\n const lazyComp = function Lazy(props: any) {\n // Now that we're out of preload and into actual render path,\n if (reload) {\n // If it was a module loading error,\n // throw eternal suspense while we wait for window to reload\n window.location.reload()\n throw new Promise(() => {})\n }\n if (error) {\n // Otherwise, just throw the error\n throw error\n }\n\n if (!comp) {\n if (reactUse) {\n reactUse(load())\n } else {\n throw load()\n }\n }\n\n return React.createElement(comp, props)\n }\n\n ;(lazyComp as any).preload = load\n\n return lazyComp as any\n}\n"],"names":[],"mappings":";;;AAcO,SAAS,mBAId,UACA,YAGQ;AACR,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC,aAAa;AAChB,oBAAc,SAAA,EACX,KAAK,CAAC,QAAQ;AACb,sBAAc;AACd,eAAO,IAAI,cAAc,SAAS;AAAA,MACpC,CAAC,EACA,MAAM,CAAC,QAAQ;AAId,gBAAQ;AAMR,YAAI,sBAAsB,KAAK,GAAG;AAChC,cACE,iBAAiB,SACjB,OAAO,WAAW,eAClB,OAAO,mBAAmB,aAC1B;AAKA,kBAAM,aAAa,0BAA0B,MAAM,OAAO;AAC1D,gBAAI,CAAC,eAAe,QAAQ,UAAU,GAAG;AACvC,6BAAe,QAAQ,YAAY,GAAG;AACtC,uBAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACL;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,SAAS,KAAK,OAAY;AAEzC,QAAI,QAAQ;AAGV,aAAO,SAAS,OAAA;AAChB,YAAM,IAAI,QAAQ,MAAM;AAAA,MAAC,CAAC;AAAA,IAC5B;AACA,QAAI,OAAO;AAET,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,MAAM;AACT,UAAI,UAAU;AACZ,iBAAS,MAAM;AAAA,MACjB,OAAO;AACL,cAAM,KAAA;AAAA,MACR;AAAA,IACF;AAEA,WAAO,MAAM,cAAc,MAAM,KAAK;AAAA,EACxC;AAEE,WAAiB,UAAU;AAE7B,SAAO;AACT;"}
|
package/dist/esm/utils.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* React.use if available (React 19+), undefined otherwise.
|
|
4
|
+
* Use dynamic lookup to avoid Webpack compilation errors with React 18.
|
|
5
|
+
*/
|
|
6
|
+
export declare const reactUse: (<T>(usable: Promise<T> | React.Context<T>) => T) | undefined;
|
|
2
7
|
export declare function useStableCallback<T extends (...args: Array<any>) => any>(fn: T): T;
|
|
3
8
|
export declare const useLayoutEffect: typeof React.useLayoutEffect;
|
|
4
9
|
/**
|
package/dist/esm/utils.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
const REACT_USE = "use";
|
|
3
|
+
const reactUse = React[REACT_USE];
|
|
2
4
|
function useStableCallback(fn) {
|
|
3
5
|
const fnRef = React.useRef(fn);
|
|
4
6
|
fnRef.current = fn;
|
|
@@ -40,6 +42,7 @@ function useForwardedRef(ref) {
|
|
|
40
42
|
return innerRef;
|
|
41
43
|
}
|
|
42
44
|
export {
|
|
45
|
+
reactUse,
|
|
43
46
|
useForwardedRef,
|
|
44
47
|
useIntersectionObserver,
|
|
45
48
|
useLayoutEffect,
|
package/dist/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import * as React from 'react'\n\nexport function useStableCallback<T extends (...args: Array<any>) => any>(\n fn: T,\n): T {\n const fnRef = React.useRef(fn)\n fnRef.current = fn\n\n const ref = React.useRef((...args: Array<any>) => fnRef.current(...args))\n return ref.current as T\n}\n\nexport const useLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3\n */\nexport function usePrevious<T>(value: T): T | null {\n // initialise the ref with previous and current values\n const ref = React.useRef<{ value: T; prev: T | null }>({\n value: value,\n prev: null,\n })\n\n const current = ref.current.value\n\n // if the value passed into hook doesn't match what we store as \"current\"\n // move the \"current\" to the \"previous\"\n // and store the passed value as \"current\"\n if (value !== current) {\n ref.current = {\n value: value,\n prev: current,\n }\n }\n\n // return the previous value only\n return ref.current.prev\n}\n\n/**\n * React hook to wrap `IntersectionObserver`.\n *\n * This hook will create an `IntersectionObserver` and observe the ref passed to it.\n *\n * When the intersection changes, the callback will be called with the `IntersectionObserverEntry`.\n *\n * @param ref - The ref to observe\n * @param intersectionObserverOptions - The options to pass to the IntersectionObserver\n * @param options - The options to pass to the hook\n * @param callback - The callback to call when the intersection changes\n * @returns The IntersectionObserver instance\n * @example\n * ```tsx\n * const MyComponent = () => {\n * const ref = React.useRef<HTMLDivElement>(null)\n * useIntersectionObserver(\n * ref,\n * (entry) => { doSomething(entry) },\n * { rootMargin: '10px' },\n * { disabled: false }\n * )\n * return <div ref={ref} />\n * ```\n */\nexport function useIntersectionObserver<T extends Element>(\n ref: React.RefObject<T | null>,\n callback: (entry: IntersectionObserverEntry | undefined) => void,\n intersectionObserverOptions: IntersectionObserverInit = {},\n options: { disabled?: boolean } = {},\n) {\n React.useEffect(() => {\n if (\n !ref.current ||\n options.disabled ||\n typeof IntersectionObserver !== 'function'\n ) {\n return\n }\n\n const observer = new IntersectionObserver(([entry]) => {\n callback(entry)\n }, intersectionObserverOptions)\n\n observer.observe(ref.current)\n\n return () => {\n observer.disconnect()\n }\n }, [callback, intersectionObserverOptions, options.disabled, ref])\n}\n\n/**\n * React hook to take a `React.ForwardedRef` and returns a `ref` that can be used on a DOM element.\n *\n * @param ref - The forwarded ref\n * @returns The inner ref returned by `useRef`\n * @example\n * ```tsx\n * const MyComponent = React.forwardRef((props, ref) => {\n * const innerRef = useForwardedRef(ref)\n * return <div ref={innerRef} />\n * })\n * ```\n */\nexport function useForwardedRef<T>(ref?: React.ForwardedRef<T>) {\n const innerRef = React.useRef<T>(null)\n React.useImperativeHandle(ref, () => innerRef.current!, [])\n return innerRef\n}\n"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import * as React from 'react'\n\n// Safe version of React.use() that will not cause compilation errors against\n// React 18 with Webpack, which statically analyzes imports and fails when it\n// sees React.use referenced (since 'use' is not exported from React 18).\n// This uses a dynamic string lookup to avoid the static analysis.\nconst REACT_USE = 'use'\n\n/**\n * React.use if available (React 19+), undefined otherwise.\n * Use dynamic lookup to avoid Webpack compilation errors with React 18.\n */\nexport const reactUse:\n | (<T>(usable: Promise<T> | React.Context<T>) => T)\n | undefined = (React as any)[REACT_USE]\n\nexport function useStableCallback<T extends (...args: Array<any>) => any>(\n fn: T,\n): T {\n const fnRef = React.useRef(fn)\n fnRef.current = fn\n\n const ref = React.useRef((...args: Array<any>) => fnRef.current(...args))\n return ref.current as T\n}\n\nexport const useLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3\n */\nexport function usePrevious<T>(value: T): T | null {\n // initialise the ref with previous and current values\n const ref = React.useRef<{ value: T; prev: T | null }>({\n value: value,\n prev: null,\n })\n\n const current = ref.current.value\n\n // if the value passed into hook doesn't match what we store as \"current\"\n // move the \"current\" to the \"previous\"\n // and store the passed value as \"current\"\n if (value !== current) {\n ref.current = {\n value: value,\n prev: current,\n }\n }\n\n // return the previous value only\n return ref.current.prev\n}\n\n/**\n * React hook to wrap `IntersectionObserver`.\n *\n * This hook will create an `IntersectionObserver` and observe the ref passed to it.\n *\n * When the intersection changes, the callback will be called with the `IntersectionObserverEntry`.\n *\n * @param ref - The ref to observe\n * @param intersectionObserverOptions - The options to pass to the IntersectionObserver\n * @param options - The options to pass to the hook\n * @param callback - The callback to call when the intersection changes\n * @returns The IntersectionObserver instance\n * @example\n * ```tsx\n * const MyComponent = () => {\n * const ref = React.useRef<HTMLDivElement>(null)\n * useIntersectionObserver(\n * ref,\n * (entry) => { doSomething(entry) },\n * { rootMargin: '10px' },\n * { disabled: false }\n * )\n * return <div ref={ref} />\n * ```\n */\nexport function useIntersectionObserver<T extends Element>(\n ref: React.RefObject<T | null>,\n callback: (entry: IntersectionObserverEntry | undefined) => void,\n intersectionObserverOptions: IntersectionObserverInit = {},\n options: { disabled?: boolean } = {},\n) {\n React.useEffect(() => {\n if (\n !ref.current ||\n options.disabled ||\n typeof IntersectionObserver !== 'function'\n ) {\n return\n }\n\n const observer = new IntersectionObserver(([entry]) => {\n callback(entry)\n }, intersectionObserverOptions)\n\n observer.observe(ref.current)\n\n return () => {\n observer.disconnect()\n }\n }, [callback, intersectionObserverOptions, options.disabled, ref])\n}\n\n/**\n * React hook to take a `React.ForwardedRef` and returns a `ref` that can be used on a DOM element.\n *\n * @param ref - The forwarded ref\n * @returns The inner ref returned by `useRef`\n * @example\n * ```tsx\n * const MyComponent = React.forwardRef((props, ref) => {\n * const innerRef = useForwardedRef(ref)\n * return <div ref={innerRef} />\n * })\n * ```\n */\nexport function useForwardedRef<T>(ref?: React.ForwardedRef<T>) {\n const innerRef = React.useRef<T>(null)\n React.useImperativeHandle(ref, () => innerRef.current!, [])\n return innerRef\n}\n"],"names":[],"mappings":";AAMA,MAAM,YAAY;AAMX,MAAM,WAEI,MAAc,SAAS;AAEjC,SAAS,kBACd,IACG;AACH,QAAM,QAAQ,MAAM,OAAO,EAAE;AAC7B,QAAM,UAAU;AAEhB,QAAM,MAAM,MAAM,OAAO,IAAI,SAAqB,MAAM,QAAQ,GAAG,IAAI,CAAC;AACxE,SAAO,IAAI;AACb;AAEO,MAAM,kBACX,OAAO,WAAW,cAAc,MAAM,kBAAkB,MAAM;AAKzD,SAAS,YAAe,OAAoB;AAEjD,QAAM,MAAM,MAAM,OAAqC;AAAA,IACrD;AAAA,IACA,MAAM;AAAA,EAAA,CACP;AAED,QAAM,UAAU,IAAI,QAAQ;AAK5B,MAAI,UAAU,SAAS;AACrB,QAAI,UAAU;AAAA,MACZ;AAAA,MACA,MAAM;AAAA,IAAA;AAAA,EAEV;AAGA,SAAO,IAAI,QAAQ;AACrB;AA2BO,SAAS,wBACd,KACA,UACA,8BAAwD,CAAA,GACxD,UAAkC,IAClC;AACA,QAAM,UAAU,MAAM;AACpB,QACE,CAAC,IAAI,WACL,QAAQ,YACR,OAAO,yBAAyB,YAChC;AACA;AAAA,IACF;AAEA,UAAM,WAAW,IAAI,qBAAqB,CAAC,CAAC,KAAK,MAAM;AACrD,eAAS,KAAK;AAAA,IAChB,GAAG,2BAA2B;AAE9B,aAAS,QAAQ,IAAI,OAAO;AAE5B,WAAO,MAAM;AACX,eAAS,WAAA;AAAA,IACX;AAAA,EACF,GAAG,CAAC,UAAU,6BAA6B,QAAQ,UAAU,GAAG,CAAC;AACnE;AAeO,SAAS,gBAAmB,KAA6B;AAC9D,QAAM,WAAW,MAAM,OAAU,IAAI;AACrC,QAAM,oBAAoB,KAAK,MAAM,SAAS,SAAU,CAAA,CAAE;AAC1D,SAAO;AACT;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
|
-
"version": "1.147.
|
|
3
|
+
"version": "1.147.3",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,10 +31,12 @@
|
|
|
31
31
|
".": {
|
|
32
32
|
"import": {
|
|
33
33
|
"types": "./dist/esm/index.d.ts",
|
|
34
|
+
"development": "./dist/esm/index.dev.js",
|
|
34
35
|
"default": "./dist/esm/index.js"
|
|
35
36
|
},
|
|
36
37
|
"require": {
|
|
37
38
|
"types": "./dist/cjs/index.d.cts",
|
|
39
|
+
"development": "./dist/cjs/index.dev.cjs",
|
|
38
40
|
"default": "./dist/cjs/index.cjs"
|
|
39
41
|
}
|
|
40
42
|
},
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { Asset } from './Asset'
|
|
3
|
+
import { useRouter } from './useRouter'
|
|
4
|
+
import { useHydrated } from './ClientOnly'
|
|
5
|
+
import { useTags } from './headContentUtils'
|
|
6
|
+
|
|
7
|
+
const DEV_STYLES_ATTR = 'data-tanstack-router-dev-styles'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Render route-managed head tags (title, meta, links, styles, head scripts).
|
|
11
|
+
* Place inside the document head of your app shell.
|
|
12
|
+
*
|
|
13
|
+
* Development version: filters out dev styles link after hydration and
|
|
14
|
+
* includes a fallback cleanup effect for hydration mismatch cases.
|
|
15
|
+
*
|
|
16
|
+
* @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management
|
|
17
|
+
*/
|
|
18
|
+
export function HeadContent() {
|
|
19
|
+
const tags = useTags()
|
|
20
|
+
const router = useRouter()
|
|
21
|
+
const nonce = router.options.ssr?.nonce
|
|
22
|
+
const hydrated = useHydrated()
|
|
23
|
+
|
|
24
|
+
// Fallback cleanup for hydration mismatch cases
|
|
25
|
+
// Runs when hydration completes to remove any orphaned dev styles links from DOM
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
if (hydrated) {
|
|
28
|
+
document
|
|
29
|
+
.querySelectorAll(`link[${DEV_STYLES_ATTR}]`)
|
|
30
|
+
.forEach((el) => el.remove())
|
|
31
|
+
}
|
|
32
|
+
}, [hydrated])
|
|
33
|
+
|
|
34
|
+
// Filter out dev styles after hydration
|
|
35
|
+
const filteredTags = hydrated
|
|
36
|
+
? tags.filter((tag) => !tag.attrs?.[DEV_STYLES_ATTR])
|
|
37
|
+
: tags
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
{filteredTags.map((tag) => (
|
|
42
|
+
<Asset {...tag} key={`tsr-meta-${JSON.stringify(tag)}`} nonce={nonce} />
|
|
43
|
+
))}
|
|
44
|
+
</>
|
|
45
|
+
)
|
|
46
|
+
}
|