| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 |
|
| 11 | import { useIsRSCRouterContext } from "../../context.js";
|
| 12 | import { useDataRouterContext, useDataRouterData, useDataRouterState, useLocation } from "../../hooks.js";
|
| 13 | import { warnOnce } from "../../server-runtime/warnings.js";
|
| 14 | import invariant from "./invariant.js";
|
| 15 | import { getKeyedLinksForMatches, getKeyedPrefetchLinks, getModuleLinkHrefs, getNewMatchesForLinks, isPageLinkDescriptor } from "./links.js";
|
| 16 | import { escapeHtml } from "./markup.js";
|
| 17 | import { singleFetchUrl } from "./single-fetch.js";
|
| 18 | import { getPartialManifest, isFogOfWarEnabled } from "./fog-of-war.js";
|
| 19 | import * as React$1 from "react";
|
| 20 |
|
| 21 | const FrameworkContext = React$1.createContext(void 0);
|
| 22 | FrameworkContext.displayName = "FrameworkContext";
|
| 23 | function useFrameworkContext() {
|
| 24 | let context = React$1.useContext(FrameworkContext);
|
| 25 | invariant(context, "You must render this element inside a <HydratedRouter> element");
|
| 26 | return context;
|
| 27 | }
|
| 28 | function 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 | }
|
| 88 | function composeEventHandlers(theirHandler, ourHandler) {
|
| 89 | return (event) => {
|
| 90 | theirHandler && theirHandler(event);
|
| 91 | if (!event.defaultPrevented) ourHandler(event);
|
| 92 | };
|
| 93 | }
|
| 94 | function 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 | }
|
| 102 | const CRITICAL_CSS_DATA_ATTRIBUTE = "data-react-router-critical-css";
|
| 103 | |
| 104 | |
| 105 | |
| 106 | |
| 107 | |
| 108 | |
| 109 | |
| 110 | |
| 111 | |
| 112 | |
| 113 | |
| 114 | |
| 115 | |
| 116 | |
| 117 | |
| 118 | |
| 119 | |
| 120 | |
| 121 | |
| 122 | |
| 123 | |
| 124 | |
| 125 | |
| 126 | |
| 127 | |
| 128 | |
| 129 | |
| 130 | |
| 131 |
|
| 132 | function 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 React$1.createElement(React$1.Fragment, null, typeof criticalCss === "string" ? React$1.createElement("style", {
|
| 144 | [CRITICAL_CSS_DATA_ATTRIBUTE]: "",
|
| 145 | nonce,
|
| 146 | dangerouslySetInnerHTML: { __html: criticalCss }
|
| 147 | }) : null, typeof criticalCss === "object" ? 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) ? React$1.createElement(PrefetchPageLinks, {
|
| 154 | key,
|
| 155 | nonce,
|
| 156 | ...link,
|
| 157 | crossOrigin: link.crossOrigin ?? crossOrigin
|
| 158 | }) : React$1.createElement("link", {
|
| 159 | key,
|
| 160 | nonce,
|
| 161 | ...link,
|
| 162 | crossOrigin: link.crossOrigin ?? crossOrigin
|
| 163 | })));
|
| 164 | }
|
| 165 | |
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 174 | |
| 175 | |
| 176 | |
| 177 | |
| 178 | |
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | |
| 188 | |
| 189 | |
| 190 | |
| 191 |
|
| 192 | function 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 React$1.createElement(RSCPrefetchPageLinksImpl, {
|
| 207 | page,
|
| 208 | matches,
|
| 209 | ...linkProps
|
| 210 | });
|
| 211 | return React$1.createElement(PrefetchPageLinksImpl, {
|
| 212 | page,
|
| 213 | matches,
|
| 214 | ...linkProps
|
| 215 | });
|
| 216 | }
|
| 217 | function 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 | }
|
| 235 | function RSCPrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
|
| 236 | let location = useLocation();
|
| 237 | let dataHrefs = React$1.useMemo(() => {
|
| 238 | if (page === location.pathname + location.search + location.hash) return [];
|
| 239 | let url = singleFetchUrl(page, "rsc");
|
| 240 | let hasSomeRoutesWithShouldRevalidate = false;
|
| 241 | let targetRoutes = [];
|
| 242 | for (let match of nextMatches) if (typeof match.route.shouldRevalidate === "function") hasSomeRoutesWithShouldRevalidate = true;
|
| 243 | else targetRoutes.push(match.route.id);
|
| 244 | if (hasSomeRoutesWithShouldRevalidate && targetRoutes.length > 0) url.searchParams.set("_routes", targetRoutes.join(","));
|
| 245 | return [url.pathname + url.search];
|
| 246 | }, [
|
| 247 | page,
|
| 248 | location,
|
| 249 | nextMatches
|
| 250 | ]);
|
| 251 | return React$1.createElement(React$1.Fragment, null, dataHrefs.map((href) => React$1.createElement("link", {
|
| 252 | key: href,
|
| 253 | rel: "prefetch",
|
| 254 | as: "fetch",
|
| 255 | href,
|
| 256 | ...linkProps
|
| 257 | })));
|
| 258 | }
|
| 259 | function PrefetchPageLinksImpl({ page, matches: nextMatches, ...linkProps }) {
|
| 260 | let location = useLocation();
|
| 261 | let { manifest, routeModules } = useFrameworkContext();
|
| 262 | let { matches } = useDataRouterState("PrefetchPageLinks");
|
| 263 | let { loaderData } = useDataRouterData("PrefetchPageLinks");
|
| 264 | let newMatchesForData = React$1.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [
|
| 265 | page,
|
| 266 | nextMatches,
|
| 267 | matches,
|
| 268 | manifest,
|
| 269 | location
|
| 270 | ]);
|
| 271 | let newMatchesForAssets = React$1.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [
|
| 272 | page,
|
| 273 | nextMatches,
|
| 274 | matches,
|
| 275 | manifest,
|
| 276 | location
|
| 277 | ]);
|
| 278 | let dataHrefs = React$1.useMemo(() => {
|
| 279 | if (page === location.pathname + location.search + location.hash) return [];
|
| 280 | let routesParams = new Set();
|
| 281 | let foundOptOutRoute = false;
|
| 282 | nextMatches.forEach((m) => {
|
| 283 | let manifestRoute = manifest.routes[m.route.id];
|
| 284 | if (!manifestRoute || !manifestRoute.hasLoader) return;
|
| 285 | if (!newMatchesForData.some((m2) => m2.route.id === m.route.id) && m.route.id in loaderData && routeModules[m.route.id]?.shouldRevalidate) foundOptOutRoute = true;
|
| 286 | else if (manifestRoute.hasClientLoader) foundOptOutRoute = true;
|
| 287 | else routesParams.add(m.route.id);
|
| 288 | });
|
| 289 | if (routesParams.size === 0) return [];
|
| 290 | let url = singleFetchUrl(page, "data");
|
| 291 | if (foundOptOutRoute && routesParams.size > 0) url.searchParams.set("_routes", nextMatches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(","));
|
| 292 | return [url.pathname + url.search];
|
| 293 | }, [
|
| 294 | loaderData,
|
| 295 | location,
|
| 296 | manifest,
|
| 297 | newMatchesForData,
|
| 298 | nextMatches,
|
| 299 | page,
|
| 300 | routeModules
|
| 301 | ]);
|
| 302 | let moduleHrefs = React$1.useMemo(() => getModuleLinkHrefs(newMatchesForAssets, manifest), [newMatchesForAssets, manifest]);
|
| 303 | let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
|
| 304 | return React$1.createElement(React$1.Fragment, null, dataHrefs.map((href) => React$1.createElement("link", {
|
| 305 | key: href,
|
| 306 | rel: "prefetch",
|
| 307 | as: "fetch",
|
| 308 | href,
|
| 309 | ...linkProps
|
| 310 | })), moduleHrefs.map((href) => React$1.createElement("link", {
|
| 311 | key: href,
|
| 312 | rel: "modulepreload",
|
| 313 | href,
|
| 314 | ...linkProps
|
| 315 | })), keyedPrefetchLinks.map(({ key, link }) => React$1.createElement("link", {
|
| 316 | key,
|
| 317 | nonce: linkProps.nonce,
|
| 318 | ...link,
|
| 319 | crossOrigin: link.crossOrigin ?? linkProps.crossOrigin
|
| 320 | })));
|
| 321 | }
|
| 322 | |
| 323 | |
| 324 | |
| 325 | |
| 326 | |
| 327 | |
| 328 | |
| 329 | |
| 330 | |
| 331 | |
| 332 | |
| 333 | |
| 334 | |
| 335 | |
| 336 | |
| 337 | |
| 338 | |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 | |
| 344 | |
| 345 | |
| 346 |
|
| 347 | function Meta() {
|
| 348 | let { isSpaMode, routeModules } = useFrameworkContext();
|
| 349 | let { matches: routerMatches } = useDataRouterState("Meta");
|
| 350 | let { errors, loaderData } = useDataRouterData("Meta");
|
| 351 | let location = useLocation();
|
| 352 | let _matches = getActiveMatches(routerMatches, errors, isSpaMode);
|
| 353 | let error = null;
|
| 354 | if (errors) error = errors[_matches[_matches.length - 1].route.id];
|
| 355 | let meta = [];
|
| 356 | let leafMeta = null;
|
| 357 | let matches = [];
|
| 358 | for (let i = 0; i < _matches.length; i++) {
|
| 359 | let _match = _matches[i];
|
| 360 | let routeId = _match.route.id;
|
| 361 | let data = loaderData[routeId];
|
| 362 | let params = _match.params;
|
| 363 | let routeModule = routeModules[routeId];
|
| 364 | let routeMeta = [];
|
| 365 | let match = {
|
| 366 | id: routeId,
|
| 367 | loaderData: data,
|
| 368 | meta: [],
|
| 369 | params: _match.params,
|
| 370 | pathname: _match.pathname,
|
| 371 | handle: _match.route.handle,
|
| 372 | error
|
| 373 | };
|
| 374 | matches[i] = match;
|
| 375 | if (routeModule?.meta) routeMeta = typeof routeModule.meta === "function" ? routeModule.meta({
|
| 376 | loaderData: data,
|
| 377 | params,
|
| 378 | location,
|
| 379 | matches,
|
| 380 | error
|
| 381 | }) : Array.isArray(routeModule.meta) ? [...routeModule.meta] : routeModule.meta;
|
| 382 | else if (leafMeta) routeMeta = [...leafMeta];
|
| 383 | routeMeta = routeMeta || [];
|
| 384 | 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");
|
| 385 | match.meta = routeMeta;
|
| 386 | matches[i] = match;
|
| 387 | meta = [...routeMeta];
|
| 388 | leafMeta = meta;
|
| 389 | }
|
| 390 | return React$1.createElement(React$1.Fragment, null, meta.flat().map((metaProps) => {
|
| 391 | if (!metaProps) return null;
|
| 392 | if ("tagName" in metaProps) {
|
| 393 | let { tagName, ...rest } = metaProps;
|
| 394 | if (!isValidMetaTag(tagName)) {
|
| 395 | console.warn(`A meta object uses an invalid tagName: ${tagName}. Expected either 'link' or 'meta'`);
|
| 396 | return null;
|
| 397 | }
|
| 398 | let Comp = tagName;
|
| 399 | return React$1.createElement(Comp, {
|
| 400 | key: JSON.stringify(rest),
|
| 401 | ...rest
|
| 402 | });
|
| 403 | }
|
| 404 | if ("title" in metaProps) return React$1.createElement("title", { key: "title" }, String(metaProps.title));
|
| 405 | if ("charset" in metaProps) {
|
| 406 | metaProps.charSet ??= metaProps.charset;
|
| 407 | delete metaProps.charset;
|
| 408 | }
|
| 409 | if ("charSet" in metaProps && metaProps.charSet != null) return typeof metaProps.charSet === "string" ? React$1.createElement("meta", {
|
| 410 | key: "charSet",
|
| 411 | charSet: metaProps.charSet
|
| 412 | }) : null;
|
| 413 | if ("script:ld+json" in metaProps) try {
|
| 414 | let json = JSON.stringify(metaProps["script:ld+json"]);
|
| 415 | return React$1.createElement("script", {
|
| 416 | key: `script:ld+json:${json}`,
|
| 417 | type: "application/ld+json",
|
| 418 | dangerouslySetInnerHTML: { __html: escapeHtml(json) }
|
| 419 | });
|
| 420 | } catch {
|
| 421 | return null;
|
| 422 | }
|
| 423 | return React$1.createElement("meta", {
|
| 424 | key: JSON.stringify(metaProps),
|
| 425 | ...metaProps
|
| 426 | });
|
| 427 | }));
|
| 428 | }
|
| 429 | function isValidMetaTag(tagName) {
|
| 430 | return typeof tagName === "string" && /^(meta|link)$/.test(tagName);
|
| 431 | }
|
| 432 | |
| 433 | |
| 434 | |
| 435 |
|
| 436 | let isHydrated = false;
|
| 437 | function setIsHydrated() {
|
| 438 | isHydrated = true;
|
| 439 | }
|
| 440 | |
| 441 | |
| 442 | |
| 443 | |
| 444 | |
| 445 | |
| 446 | |
| 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 | function Scripts(scriptProps) {
|
| 474 | let { manifest, serverHandoffString, isSpaMode, renderMeta, routeDiscovery, ssr, nonce: contextNonce } = useFrameworkContext();
|
| 475 | let { router, static: isStatic, staticContext } = useDataRouterContext("Scripts");
|
| 476 | let { matches: routerMatches } = useDataRouterState("Scripts");
|
| 477 | let isRSCRouterContext = useIsRSCRouterContext();
|
| 478 | let enableFogOfWar = isFogOfWarEnabled(routeDiscovery, ssr);
|
| 479 | if (scriptProps.nonce == null && contextNonce) scriptProps = {
|
| 480 | ...scriptProps,
|
| 481 | nonce: contextNonce
|
| 482 | };
|
| 483 | if (renderMeta) renderMeta.didRenderScripts = true;
|
| 484 | let matches = getActiveMatches(routerMatches, null, isSpaMode);
|
| 485 | React$1.useEffect(() => {
|
| 486 | setIsHydrated();
|
| 487 | }, []);
|
| 488 | let initialScripts = React$1.useMemo(() => {
|
| 489 | if (isRSCRouterContext) return null;
|
| 490 | let contextScript = staticContext ? `window.__reactRouterContext = ${serverHandoffString};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());` : " ";
|
| 491 | let routeModulesScript = !isStatic ? " " : `${manifest.hmr?.runtime ? `import ${JSON.stringify(manifest.hmr.runtime)};` : ""}${!enableFogOfWar ? `import ${JSON.stringify(manifest.url)}` : ""};
|
| 492 | ${matches.map((match, routeIndex) => {
|
| 493 | let routeVarName = `route${routeIndex}`;
|
| 494 | let manifestEntry = manifest.routes[match.route.id];
|
| 495 | invariant(manifestEntry, `Route ${match.route.id} not found in manifest`);
|
| 496 | let { clientActionModule, clientLoaderModule, clientMiddlewareModule, hydrateFallbackModule, module } = manifestEntry;
|
| 497 | let chunks = [
|
| 498 | ...clientActionModule ? [{
|
| 499 | module: clientActionModule,
|
| 500 | varName: `${routeVarName}_clientAction`
|
| 501 | }] : [],
|
| 502 | ...clientLoaderModule ? [{
|
| 503 | module: clientLoaderModule,
|
| 504 | varName: `${routeVarName}_clientLoader`
|
| 505 | }] : [],
|
| 506 | ...clientMiddlewareModule ? [{
|
| 507 | module: clientMiddlewareModule,
|
| 508 | varName: `${routeVarName}_clientMiddleware`
|
| 509 | }] : [],
|
| 510 | ...hydrateFallbackModule ? [{
|
| 511 | module: hydrateFallbackModule,
|
| 512 | varName: `${routeVarName}_HydrateFallback`
|
| 513 | }] : [],
|
| 514 | {
|
| 515 | module,
|
| 516 | varName: `${routeVarName}_main`
|
| 517 | }
|
| 518 | ];
|
| 519 | if (chunks.length === 1) return `import * as ${routeVarName} from ${JSON.stringify(module)};`;
|
| 520 | return [chunks.map((chunk) => `import * as ${chunk.varName} from "${chunk.module}";`).join("\n"), `const ${routeVarName} = {${chunks.map((chunk) => `...${chunk.varName}`).join(",")}};`].join("\n");
|
| 521 | }).join("\n")}
|
| 522 | ${enableFogOfWar ? `window.__reactRouterManifest = ${JSON.stringify(getPartialManifest(manifest, router), null, 2)};` : ""}
|
| 523 | window.__reactRouterRouteModules = {${matches.map((match, index) => `${JSON.stringify(match.route.id)}:route${index}`).join(",")}};
|
| 524 |
|
| 525 | import(${JSON.stringify(manifest.entry.module)});`;
|
| 526 | return React$1.createElement(React$1.Fragment, null, React$1.createElement("script", {
|
| 527 | ...scriptProps,
|
| 528 | suppressHydrationWarning: true,
|
| 529 | dangerouslySetInnerHTML: { __html: contextScript },
|
| 530 | type: void 0
|
| 531 | }), React$1.createElement("script", {
|
| 532 | ...scriptProps,
|
| 533 | suppressHydrationWarning: true,
|
| 534 | dangerouslySetInnerHTML: { __html: routeModulesScript },
|
| 535 | type: "module",
|
| 536 | async: true
|
| 537 | }));
|
| 538 | }, []);
|
| 539 | let preloads = isHydrated || isRSCRouterContext ? [] : [...new Set(manifest.entry.imports.concat(getModuleLinkHrefs(matches, manifest, { includeHydrateFallback: true })))];
|
| 540 | let sri = typeof manifest.sri === "object" ? manifest.sri : {};
|
| 541 | warnOnce(!isRSCRouterContext, "The <Scripts /> element is a no-op when using RSC and can be safely removed.");
|
| 542 | return isHydrated || isRSCRouterContext ? null : React$1.createElement(React$1.Fragment, null, typeof manifest.sri === "object" ? React$1.createElement("script", {
|
| 543 | ...scriptProps,
|
| 544 | "rr-importmap": "",
|
| 545 | type: "importmap",
|
| 546 | suppressHydrationWarning: true,
|
| 547 | dangerouslySetInnerHTML: { __html: JSON.stringify({ integrity: sri }) }
|
| 548 | }) : null, !enableFogOfWar ? React$1.createElement("link", {
|
| 549 | rel: "modulepreload",
|
| 550 | href: manifest.url,
|
| 551 | crossOrigin: scriptProps.crossOrigin,
|
| 552 | integrity: sri[manifest.url],
|
| 553 | nonce: scriptProps.nonce,
|
| 554 | suppressHydrationWarning: true
|
| 555 | }) : null, React$1.createElement("link", {
|
| 556 | rel: "modulepreload",
|
| 557 | href: manifest.entry.module,
|
| 558 | crossOrigin: scriptProps.crossOrigin,
|
| 559 | integrity: sri[manifest.entry.module],
|
| 560 | nonce: scriptProps.nonce,
|
| 561 | suppressHydrationWarning: true
|
| 562 | }), preloads.map((path) => React$1.createElement("link", {
|
| 563 | key: path,
|
| 564 | rel: "modulepreload",
|
| 565 | href: path,
|
| 566 | crossOrigin: scriptProps.crossOrigin,
|
| 567 | integrity: sri[path],
|
| 568 | nonce: scriptProps.nonce,
|
| 569 | suppressHydrationWarning: true
|
| 570 | })), initialScripts);
|
| 571 | }
|
| 572 | function mergeRefs(...refs) {
|
| 573 | return (value) => {
|
| 574 | refs.forEach((ref) => {
|
| 575 | if (typeof ref === "function") ref(value);
|
| 576 | else if (ref != null) ref.current = value;
|
| 577 | });
|
| 578 | };
|
| 579 | }
|
| 580 |
|
| 581 | export { CRITICAL_CSS_DATA_ATTRIBUTE, FrameworkContext, Links, Meta, PrefetchPageLinks, Scripts, mergeRefs, setIsHydrated, useFrameworkContext, usePrefetchBehavior };
|