INDIE UNPKG

21.8 kBJavaScriptView Raw
1/**
2 * react-router v8.5.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import { useIsRSCRouterContext } from "../../context.js";
12import { useDataRouterContext, useDataRouterData, useDataRouterState, useLocation } from "../../hooks.js";
13import invariant from "./invariant.js";
14import { getKeyedLinksForMatches, getKeyedPrefetchLinks, getModuleLinkHrefs, getNewMatchesForLinks, isPageLinkDescriptor } from "./links.js";
15import { escapeHtml } from "./markup.js";
16import { singleFetchUrl } from "./single-fetch.js";
17import { warnOnce } from "../../server-runtime/warnings.js";
18import { getPartialManifest, isFogOfWarEnabled } from "./fog-of-war.js";
19import * as React$1 from "react";
20//#region lib/dom/ssr/components.tsx
21const FrameworkContext = React$1.createContext(void 0);
22FrameworkContext.displayName = "FrameworkContext";
23function useFrameworkContext() {
24 let context = React$1.useContext(FrameworkContext);
25 invariant(context, "You must render this element inside a <HydratedRouter> element");
26 return context;
27}
28function usePrefetchBehavior(prefetch, theirElementProps) {
29 let frameworkContext = React$1.useContext(FrameworkContext);
30 let [maybePrefetch, setMaybePrefetch] = React$1.useState(false);
31 let [shouldPrefetch, setShouldPrefetch] = React$1.useState(false);
32 let { onFocus, onBlur, onMouseEnter, onMouseLeave, onTouchStart } = theirElementProps;
33 let ref = React$1.useRef(null);
34 React$1.useEffect(() => {
35 if (prefetch === "render") setShouldPrefetch(true);
36 if (prefetch === "viewport") {
37 let callback = (entries) => {
38 entries.forEach((entry) => {
39 setShouldPrefetch(entry.isIntersecting);
40 });
41 };
42 let observer = new IntersectionObserver(callback, { threshold: .5 });
43 if (ref.current) observer.observe(ref.current);
44 return () => {
45 observer.disconnect();
46 };
47 }
48 }, [prefetch]);
49 React$1.useEffect(() => {
50 if (maybePrefetch) {
51 let id = setTimeout(() => {
52 setShouldPrefetch(true);
53 }, 100);
54 return () => {
55 clearTimeout(id);
56 };
57 }
58 }, [maybePrefetch]);
59 let setIntent = () => {
60 setMaybePrefetch(true);
61 };
62 let cancelIntent = () => {
63 setMaybePrefetch(false);
64 setShouldPrefetch(false);
65 };
66 if (!frameworkContext) return [
67 false,
68 ref,
69 {}
70 ];
71 if (prefetch !== "intent") return [
72 shouldPrefetch,
73 ref,
74 {}
75 ];
76 return [
77 shouldPrefetch,
78 ref,
79 {
80 onFocus: composeEventHandlers(onFocus, setIntent),
81 onBlur: composeEventHandlers(onBlur, cancelIntent),
82 onMouseEnter: composeEventHandlers(onMouseEnter, setIntent),
83 onMouseLeave: composeEventHandlers(onMouseLeave, cancelIntent),
84 onTouchStart: composeEventHandlers(onTouchStart, setIntent)
85 }
86 ];
87}
88function composeEventHandlers(theirHandler, ourHandler) {
89 return (event) => {
90 theirHandler && theirHandler(event);
91 if (!event.defaultPrevented) ourHandler(event);
92 };
93}
94function getActiveMatches(matches, errors, isSpaMode) {
95 if (isSpaMode && !isHydrated) return [matches[0]];
96 if (errors) {
97 let errorIdx = matches.findIndex((m) => errors[m.route.id] !== void 0);
98 return matches.slice(0, errorIdx + 1);
99 }
100 return matches;
101}
102const CRITICAL_CSS_DATA_ATTRIBUTE = "data-react-router-critical-css";
103/**
104* Renders all the [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
105* tags created by the route module's [`links`](../../start/framework/route-module#links)
106* export. You should render it inside the [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
107* of your document.
108*
109* @example
110* import { Links } from "react-router";
111*
112* export default function Root() {
113* return (
114* <html>
115* <head>
116* <Links />
117* </head>
118* <body></body>
119* </html>
120* );
121* }
122*
123* @public
124* @category Components
125* @mode framework
126* @param props Props
127* @param {LinksProps.nonce} props.nonce n/a
128* @param {LinksProps.crossOrigin} props.crossOrigin n/a
129* @returns A collection of React elements for [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
130* tags
131*/
132function Links({ nonce, crossOrigin }) {
133 let { isSpaMode, manifest, routeModules, criticalCss, nonce: contextNonce } = useFrameworkContext();
134 let { matches: routerMatches } = useDataRouterState("Links");
135 let { errors } = useDataRouterData("Links");
136 let matches = getActiveMatches(routerMatches, errors, isSpaMode);
137 let keyedLinks = React$1.useMemo(() => getKeyedLinksForMatches(matches, routeModules, manifest), [
138 matches,
139 routeModules,
140 manifest
141 ]);
142 if (nonce == null && contextNonce) nonce = contextNonce;
143 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, typeof criticalCss === "string" ? /* @__PURE__ */ React$1.createElement("style", {
144 [CRITICAL_CSS_DATA_ATTRIBUTE]: "",
145 nonce,
146 dangerouslySetInnerHTML: { __html: criticalCss }
147 }) : null, typeof criticalCss === "object" ? /* @__PURE__ */ React$1.createElement("link", {
148 [CRITICAL_CSS_DATA_ATTRIBUTE]: "",
149 rel: "stylesheet",
150 href: criticalCss.href,
151 nonce,
152 crossOrigin
153 }) : null, keyedLinks.map(({ key, link }) => isPageLinkDescriptor(link) ? /* @__PURE__ */ React$1.createElement(PrefetchPageLinks, {
154 key,
155 nonce,
156 ...link,
157 crossOrigin: link.crossOrigin ?? crossOrigin
158 }) : /* @__PURE__ */ React$1.createElement("link", {
159 key,
160 nonce,
161 ...link,
162 crossOrigin: link.crossOrigin ?? crossOrigin
163 })));
164}
165/**
166* Renders [`<link rel=prefetch|modulepreload>`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement/rel)
167* tags for modules and data of another page to enable an instant navigation to
168* that page. [`<Link prefetch>`](./Link#prefetch) uses this internally, but you
169* can render it to prefetch a page for any other reason.
170*
171* For example, you may render one of this as the user types into a search field
172* to prefetch search results before they click through to their selection.
173*
174* @example
175* import { PrefetchPageLinks } from "react-router";
176*
177* <PrefetchPageLinks page="/absolute/path" />
178*
179* @public
180* @category Components
181* @mode framework
182* @param props Props
183* @param {PageLinkDescriptor.page} props.page n/a
184* @param props.linkProps Additional props to spread onto the [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
185* tags, such as [`crossOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement/crossOrigin),
186* [`integrity`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement/integrity),
187* [`rel`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement/rel),
188* etc.
189* @returns A collection of React elements for [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
190* tags
191*/
192function PrefetchPageLinks({ page, ...linkProps }) {
193 let rsc = useIsRSCRouterContext();
194 let { nonce: contextNonce } = useFrameworkContext();
195 let { router } = useDataRouterContext("PrefetchPageLinks");
196 let matches = React$1.useMemo(() => router.match(page), [
197 router,
198 router.routes,
199 page
200 ]);
201 if (!matches) return null;
202 if (linkProps.nonce == null && contextNonce) linkProps = {
203 ...linkProps,
204 nonce: contextNonce
205 };
206 if (rsc) return /* @__PURE__ */ React$1.createElement(RSCPrefetchPageLinksImpl, {
207 page,
208 matches,
209 ...linkProps
210 });
211 return /* @__PURE__ */ React$1.createElement(PrefetchPageLinksImpl, {
212 page,
213 matches,
214 ...linkProps
215 });
216}
217function useKeyedPrefetchLinks(matches) {
218 let { manifest, routeModules } = useFrameworkContext();
219 let [keyedPrefetchLinks, setKeyedPrefetchLinks] = React$1.useState([]);
220 React$1.useEffect(() => {
221 let interrupted = false;
222 getKeyedPrefetchLinks(matches, manifest, routeModules).then((links) => {
223 if (!interrupted) setKeyedPrefetchLinks(links);
224 });
225 return () => {
226 interrupted = true;
227 };
228 }, [
229 matches,
230 manifest,
231 routeModules
232 ]);
233 return keyedPrefetchLinks;
234}
235function RSCPrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
236 let location = useLocation();
237 let { unstable_apiServerOrigin } = useFrameworkContext();
238 let dataHrefs = React$1.useMemo(() => {
239 if (page === location.pathname + location.search + location.hash) return [];
240 let url = singleFetchUrl(page, "rsc", unstable_apiServerOrigin);
241 let hasSomeRoutesWithShouldRevalidate = false;
242 let targetRoutes = [];
243 for (let match of nextMatches) if (typeof match.route.shouldRevalidate === "function") hasSomeRoutesWithShouldRevalidate = true;
244 else targetRoutes.push(match.route.id);
245 if (hasSomeRoutesWithShouldRevalidate && targetRoutes.length > 0) url.searchParams.set("_routes", targetRoutes.join(","));
246 return [unstable_apiServerOrigin ? url.toString() : url.pathname + url.search];
247 }, [
248 page,
249 location,
250 nextMatches,
251 unstable_apiServerOrigin
252 ]);
253 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, dataHrefs.map((href) => /* @__PURE__ */ React$1.createElement("link", {
254 key: href,
255 rel: "prefetch",
256 as: "fetch",
257 href,
258 ...linkProps
259 })));
260}
261function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
262 let location = useLocation();
263 let { manifest, routeModules, unstable_apiServerOrigin } = useFrameworkContext();
264 let { matches } = useDataRouterState("PrefetchPageLinks");
265 let { loaderData } = useDataRouterData("PrefetchPageLinks");
266 let newMatchesForData = React$1.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [
267 page,
268 nextMatches,
269 matches,
270 manifest,
271 location
272 ]);
273 let newMatchesForAssets = React$1.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [
274 page,
275 nextMatches,
276 matches,
277 manifest,
278 location
279 ]);
280 let dataHrefs = React$1.useMemo(() => {
281 if (page === location.pathname + location.search + location.hash) return [];
282 let routesParams = /* @__PURE__ */ new Set();
283 let foundOptOutRoute = false;
284 nextMatches.forEach((m) => {
285 let manifestRoute = manifest.routes[m.route.id];
286 if (!manifestRoute || !manifestRoute.hasLoader) return;
287 if (!newMatchesForData.some((m2) => m2.route.id === m.route.id) && m.route.id in loaderData && routeModules[m.route.id]?.shouldRevalidate) foundOptOutRoute = true;
288 else if (manifestRoute.hasClientLoader) foundOptOutRoute = true;
289 else routesParams.add(m.route.id);
290 });
291 if (routesParams.size === 0) return [];
292 let url = singleFetchUrl(page, "data", unstable_apiServerOrigin);
293 if (foundOptOutRoute && routesParams.size > 0) url.searchParams.set("_routes", nextMatches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(","));
294 return [unstable_apiServerOrigin ? url.toString() : url.pathname + url.search];
295 }, [
296 loaderData,
297 location,
298 manifest,
299 newMatchesForData,
300 nextMatches,
301 page,
302 routeModules,
303 unstable_apiServerOrigin
304 ]);
305 let moduleHrefs = React$1.useMemo(() => getModuleLinkHrefs(newMatchesForAssets, manifest), [newMatchesForAssets, manifest]);
306 let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
307 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, dataHrefs.map((href) => /* @__PURE__ */ React$1.createElement("link", {
308 key: href,
309 rel: "prefetch",
310 as: "fetch",
311 href,
312 ...linkProps
313 })), moduleHrefs.map((href) => /* @__PURE__ */ React$1.createElement("link", {
314 key: href,
315 rel: "modulepreload",
316 href,
317 ...linkProps
318 })), keyedPrefetchLinks.map(({ key, link }) => /* @__PURE__ */ React$1.createElement("link", {
319 key,
320 nonce: linkProps.nonce,
321 ...link,
322 crossOrigin: link.crossOrigin ?? linkProps.crossOrigin
323 })));
324}
325/**
326* Renders all the [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
327* tags created by the route module's [`meta`](../../start/framework/route-module#meta)
328* export. You should render it inside the [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
329* of your document.
330*
331* @example
332* import { Meta } from "react-router";
333*
334* export default function Root() {
335* return (
336* <html>
337* <head>
338* <Meta />
339* </head>
340* </html>
341* );
342* }
343*
344* @public
345* @category Components
346* @mode framework
347* @returns A collection of React elements for [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
348* tags
349*/
350function Meta() {
351 let { isSpaMode, routeModules } = useFrameworkContext();
352 let { matches: routerMatches } = useDataRouterState("Meta");
353 let { errors, loaderData } = useDataRouterData("Meta");
354 let location = useLocation();
355 let _matches = getActiveMatches(routerMatches, errors, isSpaMode);
356 let error = null;
357 if (errors) error = errors[_matches[_matches.length - 1].route.id];
358 let meta = [];
359 let leafMeta = null;
360 let matches = [];
361 for (let i = 0; i < _matches.length; i++) {
362 let _match = _matches[i];
363 let routeId = _match.route.id;
364 let data = loaderData[routeId];
365 let params = _match.params;
366 let routeModule = routeModules[routeId];
367 let routeMeta = [];
368 let match = {
369 id: routeId,
370 loaderData: data,
371 meta: [],
372 params: _match.params,
373 pathname: _match.pathname,
374 handle: _match.route.handle,
375 error
376 };
377 matches[i] = match;
378 if (routeModule?.meta) routeMeta = typeof routeModule.meta === "function" ? routeModule.meta({
379 loaderData: data,
380 params,
381 location,
382 matches,
383 error
384 }) : Array.isArray(routeModule.meta) ? [...routeModule.meta] : routeModule.meta;
385 else if (leafMeta) routeMeta = [...leafMeta];
386 routeMeta = routeMeta || [];
387 if (!Array.isArray(routeMeta)) throw new Error("The route at " + _match.route.path + " returns an invalid value. All route meta functions must return an array of meta objects.\n\nTo reference the meta function API, see https://reactrouter.com/start/framework/route-module#meta");
388 match.meta = routeMeta;
389 matches[i] = match;
390 meta = [...routeMeta];
391 leafMeta = meta;
392 }
393 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, meta.flat().map((metaProps) => {
394 if (!metaProps) return null;
395 if ("tagName" in metaProps) {
396 let { tagName, ...rest } = metaProps;
397 if (!isValidMetaTag(tagName)) {
398 console.warn(`A meta object uses an invalid tagName: ${tagName}. Expected either 'link' or 'meta'`);
399 return null;
400 }
401 let Comp = tagName;
402 return /* @__PURE__ */ React$1.createElement(Comp, {
403 key: JSON.stringify(rest),
404 ...rest
405 });
406 }
407 if ("title" in metaProps) return /* @__PURE__ */ React$1.createElement("title", { key: "title" }, String(metaProps.title));
408 if ("charset" in metaProps) {
409 metaProps.charSet ??= metaProps.charset;
410 delete metaProps.charset;
411 }
412 if ("charSet" in metaProps && metaProps.charSet != null) return typeof metaProps.charSet === "string" ? /* @__PURE__ */ React$1.createElement("meta", {
413 key: "charSet",
414 charSet: metaProps.charSet
415 }) : null;
416 if ("script:ld+json" in metaProps) try {
417 let json = JSON.stringify(metaProps["script:ld+json"]);
418 return /* @__PURE__ */ React$1.createElement("script", {
419 key: `script:ld+json:${json}`,
420 type: "application/ld+json",
421 dangerouslySetInnerHTML: { __html: escapeHtml(json) }
422 });
423 } catch {
424 return null;
425 }
426 return /* @__PURE__ */ React$1.createElement("meta", {
427 key: JSON.stringify(metaProps),
428 ...metaProps
429 });
430 }));
431}
432function isValidMetaTag(tagName) {
433 return typeof tagName === "string" && /^(meta|link)$/.test(tagName);
434}
435/**
436* Tracks whether hydration is finished, so scripts can be skipped
437* during client-side updates.
438*/
439let isHydrated = false;
440function setIsHydrated() {
441 isHydrated = true;
442}
443/**
444* Renders the client runtime of your app. It should be rendered inside the
445* [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
446* of the document.
447*
448* If server rendering, you can omit `<Scripts/>` and the app will work as a
449* traditional web app without JavaScript, relying solely on HTML and browser
450* behaviors.
451*
452* @example
453* import { Scripts } from "react-router";
454*
455* export default function Root() {
456* return (
457* <html>
458* <head />
459* <body>
460* <Scripts />
461* </body>
462* </html>
463* );
464* }
465*
466* @public
467* @category Components
468* @mode framework
469* @param scriptProps Additional props to spread onto the [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
470* tags, such as [`crossOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement/crossOrigin),
471* [`nonce`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/nonce),
472* etc.
473* @returns A collection of React elements for [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
474* tags
475*/
476function Scripts(scriptProps) {
477 let { manifest, serverHandoffString, isSpaMode, renderMeta, routeDiscovery, ssr, nonce: contextNonce } = useFrameworkContext();
478 let { router, static: isStatic, staticContext } = useDataRouterContext("Scripts");
479 let { matches: routerMatches } = useDataRouterState("Scripts");
480 let isRSCRouterContext = useIsRSCRouterContext();
481 let enableFogOfWar = isFogOfWarEnabled(routeDiscovery, ssr);
482 if (scriptProps.nonce == null && contextNonce) scriptProps = {
483 ...scriptProps,
484 nonce: contextNonce
485 };
486 if (renderMeta) renderMeta.didRenderScripts = true;
487 let matches = getActiveMatches(routerMatches, null, isSpaMode);
488 React$1.useEffect(() => {
489 setIsHydrated();
490 }, []);
491 let initialScripts = React$1.useMemo(() => {
492 if (isRSCRouterContext) return null;
493 let contextScript = staticContext ? `window.__reactRouterContext = ${serverHandoffString};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());` : " ";
494 let routeModulesScript = !isStatic ? " " : `${manifest.hmr?.runtime ? `import ${JSON.stringify(manifest.hmr.runtime)};` : ""}${!enableFogOfWar ? `import ${JSON.stringify(manifest.url)}` : ""};
495${matches.map((match, routeIndex) => {
496 let routeVarName = `route${routeIndex}`;
497 let manifestEntry = manifest.routes[match.route.id];
498 invariant(manifestEntry, `Route ${match.route.id} not found in manifest`);
499 let { clientActionModule, clientLoaderModule, clientMiddlewareModule, hydrateFallbackModule, module } = manifestEntry;
500 let chunks = [
501 ...clientActionModule ? [{
502 module: clientActionModule,
503 varName: `${routeVarName}_clientAction`
504 }] : [],
505 ...clientLoaderModule ? [{
506 module: clientLoaderModule,
507 varName: `${routeVarName}_clientLoader`
508 }] : [],
509 ...clientMiddlewareModule ? [{
510 module: clientMiddlewareModule,
511 varName: `${routeVarName}_clientMiddleware`
512 }] : [],
513 ...hydrateFallbackModule ? [{
514 module: hydrateFallbackModule,
515 varName: `${routeVarName}_HydrateFallback`
516 }] : [],
517 {
518 module,
519 varName: `${routeVarName}_main`
520 }
521 ];
522 if (chunks.length === 1) return `import * as ${routeVarName} from ${JSON.stringify(module)};`;
523 return [chunks.map((chunk) => `import * as ${chunk.varName} from "${chunk.module}";`).join("\n"), `const ${routeVarName} = {${chunks.map((chunk) => `...${chunk.varName}`).join(",")}};`].join("\n");
524 }).join("\n")}
525 ${enableFogOfWar ? `window.__reactRouterManifest = ${JSON.stringify(getPartialManifest(manifest, router), null, 2)};` : ""}
526 window.__reactRouterRouteModules = {${matches.map((match, index) => `${JSON.stringify(match.route.id)}:route${index}`).join(",")}};
527
528import(${JSON.stringify(manifest.entry.module)});`;
529 return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement("script", {
530 ...scriptProps,
531 suppressHydrationWarning: true,
532 dangerouslySetInnerHTML: { __html: contextScript },
533 type: void 0
534 }), /* @__PURE__ */ React$1.createElement("script", {
535 ...scriptProps,
536 suppressHydrationWarning: true,
537 dangerouslySetInnerHTML: { __html: routeModulesScript },
538 type: "module",
539 async: true
540 }));
541 }, []);
542 let preloads = isHydrated || isRSCRouterContext ? [] : [...new Set(manifest.entry.imports.concat(getModuleLinkHrefs(matches, manifest, { includeHydrateFallback: true })))];
543 let sri = typeof manifest.sri === "object" ? manifest.sri : {};
544 warnOnce(!isRSCRouterContext, "The <Scripts /> element is a no-op when using RSC and can be safely removed.");
545 return isHydrated || isRSCRouterContext ? null : /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, typeof manifest.sri === "object" ? /* @__PURE__ */ React$1.createElement("script", {
546 ...scriptProps,
547 "rr-importmap": "",
548 type: "importmap",
549 suppressHydrationWarning: true,
550 dangerouslySetInnerHTML: { __html: JSON.stringify({ integrity: sri }) }
551 }) : null, !enableFogOfWar ? /* @__PURE__ */ React$1.createElement("link", {
552 rel: "modulepreload",
553 href: manifest.url,
554 crossOrigin: scriptProps.crossOrigin,
555 integrity: sri[manifest.url],
556 nonce: scriptProps.nonce,
557 suppressHydrationWarning: true
558 }) : null, /* @__PURE__ */ React$1.createElement("link", {
559 rel: "modulepreload",
560 href: manifest.entry.module,
561 crossOrigin: scriptProps.crossOrigin,
562 integrity: sri[manifest.entry.module],
563 nonce: scriptProps.nonce,
564 suppressHydrationWarning: true
565 }), preloads.map((path) => /* @__PURE__ */ React$1.createElement("link", {
566 key: path,
567 rel: "modulepreload",
568 href: path,
569 crossOrigin: scriptProps.crossOrigin,
570 integrity: sri[path],
571 nonce: scriptProps.nonce,
572 suppressHydrationWarning: true
573 })), initialScripts);
574}
575function mergeRefs(...refs) {
576 return (value) => {
577 refs.forEach((ref) => {
578 if (typeof ref === "function") ref(value);
579 else if (ref != null) ref.current = value;
580 });
581 };
582}
583//#endregion
584export { CRITICAL_CSS_DATA_ATTRIBUTE, FrameworkContext, Links, Meta, PrefetchPageLinks, Scripts, mergeRefs, setIsHydrated, useFrameworkContext, usePrefetchBehavior };