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