r( (m) => (m.route.loader || m.route.lazy) && (!filterMatchesToLoad || filterMatchesToLoad(m)) ); if (matchesToLoad.length === 0) { return { matches, // Add a null for all matched routes for proper revalidation on the client loaderData: matches.reduce( (acc, m) => Object.assign(acc, { [m.route.id]: null }), {} ), errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null, statusCode: 200, loaderHeaders: {} }; } let results = await callDataStrategy( "loader", request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy ); if (request.signal.aborted) { throwStaticHandlerAbortedError(request, isRouteRequest); } let handlerContext = processRouteLoaderData( matches, results, pendingActionResult, true, skipLoaderErrorBubbling ); let executedLoaders = new Set( matchesToLoad.map((match) => match.route.id) ); matches.forEach((match) => { if (!executedLoaders.has(match.route.id)) { handlerContext.loaderData[match.route.id] = null; } }); return { ...handlerContext, matches }; } async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy) { let results = await callDataStrategyImpl( dataStrategy || defaultDataStrategy, type, request, matchesToLoad, matches, null, manifest, mapRouteProperties2, requestContext, false // middleware not done via dataStrategy in the static handler ); let dataResults = {}; await Promise.all( matches.map(async (match) => { if (!(match.route.id in results)) { return; } let result = results[match.route.id]; if (isRedirectDataStrategyResult(result)) { let response = result.result; throw normalizeRelativeRoutingRedirectResponse( response, request, match.route.id, matches, basename ); } if (isResponse(result.result) && isRouteRequest) { throw result; } dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result); }) ); return dataResults; } return { dataRoutes, query, queryRoute }; } function getStaticContextFromError(routes, handlerContext, error, boundaryId) { let errorBoundaryId = boundaryId || handlerContext._deepestRenderedBoundaryId || routes[0].id; return { ...handlerContext, statusCode: isRouteErrorResponse(error) ? error.status : 500, errors: { [errorBoundaryId]: error } }; } function throwStaticHandlerAbortedError(request, isRouteRequest) { if (request.signal.reason !== void 0) { throw request.signal.reason; } let method = isRouteRequest ? "queryRoute" : "query"; throw new Error( `${method}() call aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}` ); } function isSubmissionNavigation(opts) { return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== void 0); } function normalizeTo(location, matches, basename, to, fromRouteId, relative) { let contextualMatches; let activeRouteMatch; if (fromRouteId) { contextualMatches = []; for (let match of matches) { contextualMatches.push(match); if (match.route.id === fromRouteId) { activeRouteMatch = match; break; } } } else { contextualMatches = matches; activeRouteMatch = matches[matches.length - 1]; } let path = resolveTo( to ? to : ".", getResolveToMatches(contextualMatches), stripBasename(location.pathname, basename) || location.pathname, relative === "path" ); if (to == null) { path.search = location.search; path.hash = location.hash; } if ((to == null || to === "" || to === ".") && activeRouteMatch) { let nakedIndex = hasNakedIndexQuery(path.search); if (activeRouteMatch.route.index && !nakedIndex) { path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index"; } else if (!activeRouteMatch.route.index && nakedIndex) { let params = new URLSearchParams(path.search); let indexValues = params.getAll("index"); params.delete("index"); indexValues.filter((v) => v).forEach((v) => params.append("index", v)); let qs = params.toString(); path.search = qs ? `?${qs}` : ""; } } if (basename !== "/") { path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]); } return createPath(path); } function normalizeNavigateOptions(isFetcher, path, opts) { if (!opts || !isSubmissionNavigation(opts)) { return { path }; } if (opts.formMethod && !isValidMethod(opts.formMethod)) { return { path, error: getInternalRouterError(405, { method: opts.formMethod }) }; } let getInvalidBodyError = () => ({ path, error: getInternalRouterError(400, { type: "invalid-body" }) }); let rawFormMethod = opts.formMethod || "get"; let formMethod = rawFormMethod.toUpperCase(); let formAction = stripHashFromPath(path); if (opts.body !== void 0) { if (opts.formEncType === "text/plain") { if (!isMutationMethod(formMethod)) { return getInvalidBodyError(); } let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ? ( // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data Array.from(opts.body.entries()).reduce( (acc, [name, value]) => `${acc}${name}=${value} `, "" ) ) : String(opts.body); return { path, submission: { formMethod, formAction, formEncType: opts.formEncType, formData: void 0, json: void 0, text } }; } else if (opts.formEncType === "application/json") { if (!isMutationMethod(formMethod)) { return getInvalidBodyError(); } try { let json = typeof opts.body === "string" ? JSON.parse(opts.body) : opts.body; return { path, submission: { formMethod, formAction, formEncType: opts.formEncType, formData: void 0, json, text: void 0 } }; } catch (e) { return getInvalidBodyError(); } } } invariant( typeof FormData === "function", "FormData is not available in this environment" ); let searchParams; let formData; if (opts.formData) { searchParams = convertFormDataToSearchParams(opts.formData); formData = opts.formData; } else if (opts.body instanceof FormData) { searchParams = convertFormDataToSearchParams(opts.body); formData = opts.body; } else if (opts.body instanceof URLSearchParams) { searchParams = opts.body; formData = convertSearchParamsToFormData(searchParams); } else if (opts.body == null) { searchParams = new URLSearchParams(); formData = new FormData(); } else { try { searchParams = new URLSearchParams(opts.body); formData = convertSearchParamsToFormData(searchParams); } catch (e) { return getInvalidBodyError(); } } let submission = { formMethod, formAction, formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded", formData, json: void 0, text: void 0 }; if (isMutationMethod(submission.formMethod)) { return { path, submission }; } let parsedPath = parsePath(path); if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) { searchParams.append("index", ""); } parsedPath.search = `?${searchParams}`; return { path: createPath(parsedPath), submission }; } function getLoaderMatchesUntilBoundary(matches, boundaryId, includeBoundary = false) { let index = matches.findIndex((m) => m.route.id === boundaryId); if (index >= 0) { return matches.slice(0, includeBoundary ? index + 1 : index); } return matches; } function getMatchesToLoad(history, state, matches, submission, location, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) { let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : void 0; let currentUrl = history.createURL(state.location); let nextUrl = history.createURL(location); let boundaryMatches = matches; if (initialHydration && state.errors) { boundaryMatches = getLoaderMatchesUntilBoundary( matches, Object.keys(state.errors)[0], true ); } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) { boundaryMatches = getLoaderMatchesUntilBoundary( matches, pendingActionResult[0] ); } let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : void 0; let shouldSkipRevalidation = actionStatus && actionStatus >= 400; let navigationMatches = boundaryMatches.filter((match, index) => { let { route } = match; if (route.lazy) { return true; } if (route.loader == null) { return false; } if (initialHydration) { return shouldLoadRouteOnHydration(route, state.loaderData, state.errors); } if (isNewLoader(state.loaderData, state.matches[index], match)) { return true; } let currentRouteMatch = state.matches[index]; let nextRouteMatch = match; return shouldRevalidateLoader(match, { currentUrl, currentParams: currentRouteMatch.params, nextUrl, nextParams: nextRouteMatch.params, ...submission, actionResult, actionStatus, defaultShouldRevalidate: shouldSkipRevalidation ? false : ( // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch) ) }); }); let revalidatingFetchers = []; fetchLoadMatches.forEach((f, key) => { if (initialHydration || !matches.some((m) => m.route.id === f.routeId) || fetchersQueuedForDeletion.has(key)) { return; } let fetcherMatches = matchRoutes(routesToUse, f.path, basename); if (!fetcherMatches) { revalidatingFetchers.push({ key, routeId: f.routeId, path: f.path, matches: null, match: null, controller: null }); return; } let fetcher = state.fetchers.get(key); let fetcherMatch = getTargetMatch(fetcherMatches, f.path); let shouldRevalidate = false; if (fetchRedirectIds.has(key)) { shouldRevalidate = false; } else if (cancelledFetcherLoads.has(key)) { cancelledFetcherLoads.delete(key); shouldRevalidate = true; } else if (fetcher && fetcher.state !== "idle" && fetcher.data === void 0) { shouldRevalidate = isRevalidationRequired; } else { shouldRevalidate = shouldRevalidateLoader(fetcherMatch, { currentUrl, currentParams: state.matches[state.matches.length - 1].params, nextUrl, nextParams: matches[matches.length - 1].params, ...submission, actionResult, actionStatus, defaultShouldRevalidate: shouldSkipRevalidation ? false : isRevalidationRequired }); } if (shouldRevalidate) { revalidatingFetchers.push({ key, routeId: f.routeId, path: f.path, matches: fetcherMatches, match: fetcherMatch, controller: new AbortController() }); } }); return [navigationMatches, revalidatingFetchers]; } function shouldLoadRouteOnHydration(route, loaderData, errors) { if (route.lazy) { return true; } if (!route.loader) { return false; } let hasData = loaderData != null && loaderData[route.id] !== void 0; let hasError = errors != null && errors[route.id] !== void 0; if (!hasData && hasError) { return false; } if (typeof route.loader === "function" && route.loader.hydrate === true) { return true; } return !hasData && !hasError; } function isNewLoader(currentLoaderData, currentMatch, match) { let isNew = ( // [a] -> [a, b] !currentMatch || // [a, b] -> [a, c] match.route.id !== currentMatch.route.id ); let isMissingData = !currentLoaderData.hasOwnProperty(match.route.id); return isNew || isMissingData; } function isNewRouteInstance(currentMatch, match) { let currentPath = currentMatch.route.path; return ( // param change for this match, /users/123 -> /users/456 currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path // e.g. /files/images/avatar.jpg -> files/finances.xls currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"] ); } function shouldRevalidateLoader(loaderMatch, arg) { if (loaderMatch.route.shouldRevalidate) { let routeChoice = loaderMatch.route.shouldRevalidate(arg); if (typeof routeChoice === "boolean") { return routeChoice; } } return arg.defaultShouldRevalidate; } function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties2) { let childrenToPatch; if (routeId) { let route = manifest[routeId]; invariant( route, `No route found to patch children into: routeId = ${routeId}` ); if (!route.children) { route.children = []; } childrenToPatch = route.children; } else { childrenToPatch = routesToUse; } let uniqueChildren = children.filter( (newRoute) => !childrenToPatch.some( (existingRoute) => isSameRoute(newRoute, existingRoute) ) ); let newRoutes = convertRoutesToDataRoutes( uniqueChildren, mapRouteProperties2, [routeId || "_", "patch", String(childrenToPatch?.length || "0")], manifest ); childrenToPatch.push(...newRoutes); } function isSameRoute(newRoute, existingRoute) { if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) { return true; } if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) { return false; } if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) { return true; } return newRoute.children.every( (aChild, i) => existingRoute.children?.some((bChild) => isSameRoute(aChild, bChild)) ); } async function loadLazyRouteModule(route, mapRouteProperties2, manifest) { if (!route.lazy) { return; } let lazyRoute = await route.lazy(); if (!route.lazy) { return; } let routeToUpdate = manifest[route.id]; invariant(routeToUpdate, "No route found in manifest"); let routeUpdates = {}; for (let lazyRouteProperty in lazyRoute) { let staticRouteValue = routeToUpdate[lazyRouteProperty]; let isPropertyStaticallyDefined = staticRouteValue !== void 0 && // This property isn't static since it should always be updated based // on the route updates lazyRouteProperty !== "hasErrorBoundary"; warning( !isPropertyStaticallyDefined, `Route "${routeToUpdate.id}" has a static property "${lazyRouteProperty}" defined but its lazy function is also returning a value for this property. The lazy route property "${lazyRouteProperty}" will be ignored.` ); if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) { routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty]; } } Object.assign(routeToUpdate, routeUpdates); Object.assign(routeToUpdate, { // To keep things framework agnostic, we use the provided `mapRouteProperties` // function to set the framework-aware properties (`element`/`hasErrorBoundary`) // since the logic will differ between frameworks. ...mapRouteProperties2(routeToUpdate), lazy: void 0 }); } async function defaultDataStrategy(args) { let matchesToLoad = args.matches.filter((m) => m.shouldLoad); let keyedResults = {}; let results = await Promise.all(matchesToLoad.map((m) => m.resolve())); results.forEach((result, i) => { keyedResults[matchesToLoad[i].route.id] = result; }); return keyedResults; } async function defaultDataStrategyWithMiddleware(args) { if (!args.matches.some((m) => m.route.unstable_middleware)) { return defaultDataStrategy(args); } return runMiddlewarePipeline( args, false, () => defaultDataStrategy(args), (e) => ({ [e.routeId]: { type: "error", result: e.error } }) ); } async function runMiddlewarePipeline(args, propagateResult, handler, errorHandler) { let { matches, request, params, context } = args; let middlewareState = { handlerResult: void 0, propagateResult }; try { let tuples = matches.flatMap( (m) => m.route.unstable_middleware ? m.route.unstable_middleware.map((fn) => [m.route.id, fn]) : [] ); let result = await callRouteMiddleware( { request, params, context }, tuples, middlewareState, handler ); return middlewareState.propagateResult ? result : middlewareState.handlerResult; } catch (e) { if (!(e instanceof MiddlewareError)) { throw e; } let result = await errorHandler(e); if (propagateResult || !middlewareState.handlerResult) { return result; } return Object.assign(middlewareState.handlerResult, result); } } var MiddlewareError = class { constructor(routeId, error) { this.routeId = routeId; this.error = error; } }; async function callRouteMiddleware(args, middlewares, middlewareState, handler, idx = 0) { let { request } = args; if (request.signal.aborted) { if (request.signal.reason) { throw request.signal.reason; } throw new Error( `Request aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}` ); } let tuple = middlewares[idx]; if (!tuple) { middlewareState.handlerResult = await handler(); return middlewareState.handlerResult; } let [routeId, middleware] = tuple; let nextCalled = false; let nextResult = void 0; let next = async () => { if (nextCalled) { throw new Error("You may only call `next()` once per middleware"); } nextCalled = true; let result = await callRouteMiddleware( args, middlewares, middlewareState, handler, idx + 1 ); if (middlewareState.propagateResult) { nextResult = result; return nextResult; } }; try { let result = await middleware( { request: args.request, params: args.params, context: args.context }, next ); if (nextCalled) { if (result === void 0) { return nextResult; } else { return result; } } else { return next(); } } catch (e) { if (e instanceof MiddlewareError) { throw e; } throw new MiddlewareError(routeId, e); } } async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, scopedContext, enableMiddleware) { let loadRouteDefinitionsPromises = matches.map( (m) => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties2, manifest) : void 0 ); if (enableMiddleware) { await Promise.all(loadRouteDefinitionsPromises); } let dsMatches = matches.map((match, i) => { let loadRoutePromise = loadRouteDefinitionsPromises[i]; let shouldLoad = matchesToLoad.some((m) => m.route.id === match.route.id); let resolve = async (handlerOverride) => { if (handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) { shouldLoad = true; } return shouldLoad ? callLoaderOrAction( type, request, match, loadRoutePromise, handlerOverride, scopedContext ) : Promise.resolve({ type: "data", result: void 0 }); }; return { ...match, shouldLoad, resolve }; }); let results = await dataStrategyImpl({ matches: dsMatches, request, params: matches[0].params, fetcherKey, context: scopedContext }); try { await Promise.all(loadRouteDefinitionsPromises); } catch (e) { } return results; } async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, scopedContext) { let result; let onReject; let runHandler = (handler) => { let reject; let abortPromise = new Promise((_, r) => reject = r); onReject = () => reject(); request.signal.addEventListener("abort", onReject); let actualHandler = (ctx) => { if (typeof handler !== "function") { return Promise.reject( new Error( `You cannot call the handler for a route which defines a boolean "${type}" [routeId: ${match.route.id}]` ) ); } return handler( { request, params: match.params, context: scopedContext }, ...ctx !== void 0 ? [ctx] : [] ); }; let handlerPromise = (async () => { try { let val = await (handlerOverride ? handlerOverride((ctx) => actualHandler(ctx)) : actualHandler()); return { type: "data", result: val }; } catch (e) { return { type: "error", result: e }; } })(); return Promise.race([handlerPromise, abortPromise]); }; try { let handler = match.route[type]; if (loadRoutePromise) { if (handler) { let handlerError; let [value] = await Promise.all([ // If the handler throws, don't let it immediately bubble out, // since we need to let the lazy() execution finish so we know if this // route has a boundary that can handle the error runHandler(handler).catch((e) => { handlerError = e; }), loadRoutePromise ]); if (handlerError !== void 0) { throw handlerError; } result = value; } else { await loadRoutePromise; handler = match.route[type]; if (handler) { result = await runHandler(handler); } else if (type === "action") { let url = new URL(request.url); let pathname = url.pathname + url.search; throw getInternalRouterError(405, { method: request.method, pathname, routeId: match.route.id }); } else { return { type: "data", result: void 0 }; } } } else if (!handler) { let url = new URL(request.url); let pathname = url.pathname + url.search; throw getInternalRouterError(404, { pathname }); } else { result = await runHandler(handler); } } catch (e) { return { type: "error", result: e }; } finally { if (onReject) { request.signal.removeEventListener("abort", onReject); } } return result; } async function convertDataStrategyResultToDataResult(dataStrategyResult) { let { result, type } = dataStrategyResult; if (isResponse(result)) { let data2; try { let contentType = result.headers.get("Content-Type"); if (contentType && /\bapplication\/json\b/.test(contentType)) { if (result.body == null) { data2 = null; } else { data2 = await result.json(); } } else { data2 = await result.text(); } } catch (e) { return { type: "error", error: e }; } if (type === "error") { return { type: "error", error: new ErrorResponseImpl(result.status, result.statusText, data2), statusCode: result.status, headers: result.headers }; } return { type: "data", data: data2, statusCode: result.status, headers: result.headers }; } if (type === "error") { if (isDataWithResponseInit(result)) { if (result.data instanceof Error) { return { type: "error", error: result.data, statusCode: result.init?.status, headers: result.init?.headers ? new Headers(result.init.headers) : void 0 }; } return { type: "error", error: new ErrorResponseImpl( result.init?.status || 500, void 0, result.data ), statusCode: isRouteErrorResponse(result) ? result.status : void 0, headers: result.init?.headers ? new Headers(result.init.headers) : void 0 }; } return { type: "error", error: result, statusCode: isRouteErrorResponse(result) ? result.status : void 0 }; } if (isDataWithResponseInit(result)) { return { type: "data", data: result.data, statusCode: result.init?.status, headers: result.init?.headers ? new Headers(result.init.headers) : void 0 }; } return { type: "data", data: result }; } function normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename) { let location = response.headers.get("Location"); invariant( location, "Redirects returned/thrown from loaders/actions must have a Location header" ); if (!ABSOLUTE_URL_REGEX.test(location)) { let trimmedMatches = matches.slice( 0, matches.findIndex((m) => m.route.id === routeId) + 1 ); location = normalizeTo( new URL(request.url), trimmedMatches, basename, location ); response.headers.set("Location", location); } return response; } function normalizeRedirectLocation(location, currentUrl, basename) { if (ABSOLUTE_URL_REGEX.test(location)) { let normalizedLocation = location; let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation); let isSameBasename = stripBasename(url.pathname, basename) != null; if (url.origin === currentUrl.origin && isSameBasename) { return url.pathname + url.search + url.hash; } } return location; } function createClientSideRequest(history, location, signal, submission) { let url = history.createURL(stripHashFromPath(location)).toString(); let init = { signal }; if (submission && isMutationMethod(submission.formMethod)) { let { formMethod, formEncType } = submission; init.method = formMethod.toUpperCase(); if (formEncType === "application/json") { init.headers = new Headers({ "Content-Type": formEncType }); init.body = JSON.stringify(submission.json); } else if (formEncType === "text/plain") { init.body = submission.text; } else if (formEncType === "application/x-www-form-urlencoded" && submission.formData) { init.body = convertFormDataToSearchParams(submission.formData); } else { init.body = submission.formData; } } return new Request(url, init); } function convertFormDataToSearchParams(formData) { let searchParams = new URLSearchParams(); for (let [key, value] of formData.entries()) { searchParams.append(key, typeof value === "string" ? value : value.name); } return searchParams; } function convertSearchParamsToFormData(searchParams) { let formData = new FormData(); for (let [key, value] of searchParams.entries()) { formData.append(key, value); } return formData; } function processRouteLoaderData(matches, results, pendingActionResult, isStaticHandler = false, skipLoaderErrorBubbling = false) { let loaderData = {}; let errors = null; let statusCode; let foundError = false; let loaderHeaders = {}; let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : void 0; matches.forEach((match) => { if (!(match.route.id in results)) { return; } let id = match.route.id; let result = results[id]; invariant( !isRedirectResult(result), "Cannot handle redirect results in processLoaderData" ); if (isErrorResult(result)) { let error = result.error; if (pendingError !== void 0) { error = pendingError; pendingError = void 0; } errors = errors || {}; if (skipLoaderErrorBubbling) { errors[id] = error; } else { let boundaryMatch = findNearestBoundary(matches, id); if (errors[boundaryMatch.route.id] == null) { errors[boundaryMatch.route.id] = error; } } if (!isStaticHandler) { loaderData[id] = ResetLoaderDataSymbol; } if (!foundError) { foundError = true; statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500; } if (result.headers) { loaderHeaders[id] = result.headers; } } else { loaderData[id] = result.data; if (result.statusCode && result.statusCode !== 200 && !foundError) { statusCode = result.statusCode; } if (result.headers) { loaderHeaders[id] = result.headers; } } }); if (pendingError !== void 0 && pendingActionResult) { errors = { [pendingActionResult[0]]: pendingError }; loaderData[pendingActionResult[0]] = void 0; } return { loaderData, errors, statusCode: statusCode || 200, loaderHeaders }; } function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults) { let { loaderData, errors } = processRouteLoaderData( matches, results, pendingActionResult ); revalidatingFetchers.forEach((rf) => { let { key, match, controller } = rf; let result = fetcherResults[key]; invariant(result, "Did not find corresponding fetcher result"); if (controller && controller.signal.aborted) { return; } else if (isErrorResult(result)) { let boundaryMatch = findNearestBoundary(state.matches, match?.route.id); if (!(errors && errors[boundaryMatch.route.id])) { errors = { ...errors, [boundaryMatch.route.id]: result.error }; } state.fetchers.delete(key); } else if (isRedirectResult(result)) { invariant(false, "Unhandled fetcher revalidation redirect"); } else { let doneFetcher = getDoneFetcher(result.data); state.fetchers.set(key, doneFetcher); } }); return { loaderData, errors }; } function mergeLoaderData(loaderData, newLoaderData, matches, errors) { let mergedLoaderData = Object.entries(newLoaderData).filter(([, v]) => v !== ResetLoaderDataSymbol).reduce((merged, [k, v]) => { merged[k] = v; return merged; }, {}); for (let match of matches) { let id = match.route.id; if (!newLoaderData.hasOwnProperty(id) && loaderData.hasOwnProperty(id) && match.route.loader) { mergedLoaderData[id] = loaderData[id]; } if (errors && errors.hasOwnProperty(id)) { break; } } return mergedLoaderData; } function getActionDataForCommit(pendingActionResult) { if (!pendingActionResult) { return {}; } return isErrorResult(pendingActionResult[1]) ? { // Clear out prior actionData on errors actionData: {} } : { actionData: { [pendingActionResult[0]]: pendingActionResult[1].data } }; } function findNearestBoundary(matches, routeId) { let eligibleMatches = routeId ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) : [...matches]; return eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || matches[0]; } function getShortCircuitMatches(routes) { let route = routes.length === 1 ? routes[0] : routes.find((r) => r.index || !r.path || r.path === "/") || { id: `__shim-error-route__` }; return { matches: [ { params: {}, pathname: "", pathnameBase: "", route } ], route }; } function getInternalRouterError(status, { pathname, routeId, method, type, message } = {}) { let statusText = "Unknown Server Error"; let errorMessage = "Unknown @remix-run/router error"; if (status === 400) { statusText = "Bad Request"; if (method && pathname && routeId) { errorMessage = `You made a ${method} request to "${pathname}" but did not provide a \`loader\` for route "${routeId}", so there is no way to handle the request.`; } else if (type === "invalid-body") { errorMessage = "Unable to encode submission body"; } } else if (status === 403) { statusText = "Forbidden"; errorMessage = `Route "${routeId}" does not match URL "${pathname}"`; } else if (status === 404) { statusText = "Not Found"; errorMessage = `No route matches URL "${pathname}"`; } else if (status === 405) { statusText = "Method Not Allowed"; if (method && pathname && routeId) { errorMessage = `You made a ${method.toUpperCase()} request to "${pathname}" but did not provide an \`action\` for route "${routeId}", so there is no way to handle the request.`; } else if (method) { errorMessage = `Invalid request method "${method.toUpperCase()}"`; } } return new ErrorResponseImpl( status || 500, statusText, new Error(errorMessage), true ); } function findRedirect(results) { let entries = Object.entries(results); for (let i = entries.length - 1; i >= 0; i--) { let [key, result] = entries[i]; if (isRedirectResult(result)) { return { key, result }; } } } function stripHashFromPath(path) { let parsedPath = typeof path === "string" ? parsePath(path) : path; return createPath({ ...parsedPath, hash: "" }); } function isHashChangeOnly(a, b) { if (a.pathname !== b.pathname || a.search !== b.search) { return false; } if (a.hash === "") { return b.hash !== ""; } else if (a.hash === b.hash) { return true; } else if (b.hash !== "") { return true; } return false; } function isDataStrategyResult(result) { return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === "data" || result.type === "error"); } function isRedirectDataStrategyResult(result) { return isResponse(result.result) && redirectStatusCodes.has(result.result.status); } function isErrorResult(result) { return result.type === "error"; } function isRedirectResult(result) { return (result && result.type) === "redirect"; } function isDataWithResponseInit(value) { return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit"; } function isResponse(value) { return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; } function isRedirectStatusCode(statusCode) { return redirectStatusCodes.has(statusCode); } function isRedirectResponse(result) { return isResponse(result) && isRedirectStatusCode(result.status) && result.headers.has("Location"); } function isValidMethod(method) { return validRequestMethods.has(method.toUpperCase()); } function isMutationMethod(method) { return validMutationMethods.has(method.toUpperCase()); } function hasNakedIndexQuery(search) { return new URLSearchParams(search).getAll("index").some((v) => v === ""); } function getTargetMatch(matches, location) { let search = typeof location === "string" ? parsePath(location).search : location.search; if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) { return matches[matches.length - 1]; } let pathMatches = getPathContributingMatches(matches); return pathMatches[pathMatches.length - 1]; } function getSubmissionFromNavigation(navigation) { let { formMethod, formAction, formEncType, text, formData, json } = navigation; if (!formMethod || !formAction || !formEncType) { return; } if (text != null) { return { formMethod, formAction, formEncType, formData: void 0, json: void 0, text }; } else if (formData != null) { return { formMethod, formAction, formEncType, formData, json: void 0, text: void 0 }; } else if (json !== void 0) { return { formMethod, formAction, formEncType, formData: void 0, json, text: void 0 }; } } function getLoadingNavigation(location, submission) { if (submission) { let navigation = { state: "loading", location, formMethod: submission.formMethod, formAction: submission.formAction, formEncType: submission.formEncType, formData: submission.formData, json: submission.json, text: submission.text }; return navigation; } else { let navigation = { state: "loading", location, formMethod: void 0, formAction: void 0, formEncType: void 0, formData: void 0, json: void 0, text: void 0 }; return navigation; } } function getSubmittingNavigation(location, submission) { let navigation = { state: "submitting", location, formMethod: submission.formMethod, formAction: submission.formAction, formEncType: submission.formEncType, formData: submission.formData, json: submission.json, text: submission.text }; return navigation; } function getLoadingFetcher(submission, data2) { if (submission) { let fetcher = { state: "loading", formMethod: submission.formMethod, formAction: submission.formAction, formEncType: submission.formEncType, formData: submission.formData, json: submission.json, text: submission.text, data: data2 }; return fetcher; } else { let fetcher = { state: "loading", formMethod: void 0, formAction: void 0, formEncType: void 0, formData: void 0, json: void 0, text: void 0, data: data2 }; return fetcher; } } function getSubmittingFetcher(submission, existingFetcher) { let fetcher = { state: "submitting", formMethod: submission.formMethod, formAction: submission.formAction, formEncType: submission.formEncType, formData: submission.formData, json: submission.json, text: submission.text, data: existingFetcher ? existingFetcher.data : void 0 }; return fetcher; } function getDoneFetcher(data2) { let fetcher = { state: "idle", formMethod: void 0, formAction: void 0, formEncType: void 0, formData: void 0, json: void 0, text: void 0, data: data2 }; return fetcher; } function restoreAppliedTransitions(_window, transitions) { try { let sessionPositions = _window.sessionStorage.getItem( TRANSITIONS_STORAGE_KEY ); if (sessionPositions) { let json = JSON.parse(sessionPositions); for (let [k, v] of Object.entries(json || {})) { if (v && Array.isArray(v)) { transitions.set(k, new Set(v || [])); } } } } catch (e) { } } function persistAppliedTransitions(_window, transitions) { if (transitions.size > 0) { let json = {}; for (let [k, v] of transitions) { json[k] = [...v]; } try { _window.sessionStorage.setItem( TRANSITIONS_STORAGE_KEY, JSON.stringify(json) ); } catch (error) { warning( false, `Failed to save applied view transitions in sessionStorage (${error}).` ); } } } function createDeferred() { let resolve; let reject; let promise = new Promise((res, rej) => { resolve = async (val) => { res(val); try { await promise; } catch (e) { } }; reject = async (error) => { rej(error); try { await promise; } catch (e) { } }; }); return { promise, //@ts-ignore resolve, //@ts-ignore reject }; } var DataRouterContext = React.createContext(null); DataRouterContext.displayName = "DataRouter"; var DataRouterStateContext = React.createContext(null); DataRouterStateContext.displayName = "DataRouterState"; var ViewTransitionContext = React.createContext({ isTransitioning: false }); ViewTransitionContext.displayName = "ViewTransition"; var FetchersContext = React.createContext( /* @__PURE__ */ new Map() ); FetchersContext.displayName = "Fetchers"; var AwaitContext = React.createContext(null); AwaitContext.displayName = "Await"; var NavigationContext = React.createContext( null ); NavigationContext.displayName = "Navigation"; var LocationContext = React.createContext( null ); LocationContext.displayName = "Location"; var RouteContext = React.createContext({ outlet: null, matches: [], isDataRoute: false }); RouteContext.displayName = "Route"; var RouteErrorContext = React.createContext(null); RouteErrorContext.displayName = "RouteError"; var ENABLE_DEV_WARNINGS = true; function useHref(to, { relative } = {}) { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the // router loaded. We can help them understand how to avoid that. `useHref() may be used only in the context of a component.` ); let { basename, navigator: navigator2 } = React2.useContext(NavigationContext); let { hash, pathname, search } = useResolvedPath(to, { relative }); let joinedPathname = pathname; if (basename !== "/") { joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]); } return navigator2.createHref({ pathname: joinedPathname, search, hash }); } function useInRouterContext() { return React2.useContext(LocationContext) != null; } function useLocation() { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the // router loaded. We can help them understand how to avoid that. `useLocation() may be used only in the context of a component.` ); return React2.useContext(LocationContext).location; } function useNavigationType() { return React2.useContext(LocationContext).navigationType; } function useMatch(pattern) { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the // router loaded. We can help them understand how to avoid that. `useMatch() may be used only in the context of a component.` ); let { pathname } = useLocation(); return React2.useMemo( () => matchPath(pattern, decodePath(pathname)), [pathname, pattern] ); } var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`; function useIsomorphicLayoutEffect(cb) { let isStatic = React2.useContext(NavigationContext).static; if (!isStatic) { React2.useLayoutEffect(cb); } } function useNavigate() { let { isDataRoute } = React2.useContext(RouteContext); return isDataRoute ? useNavigateStable() : useNavigateUnstable(); } function useNavigateUnstable() { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the // router loaded. We can help them understand how to avoid that. `useNavigate() may be used only in the context of a component.` ); let dataRouterContext = React2.useContext(DataRouterContext); let { basename, navigator: navigator2 } = React2.useContext(NavigationContext); let { matches } = React2.useContext(RouteContext); let { pathname: locationPathname } = useLocation(); let routePathnamesJson = JSON.stringify(getResolveToMatches(matches)); let activeRef = React2.useRef(false); useIsomorphicLayoutEffect(() => { activeRef.current = true; }); let navigate = React2.useCallback( (to, options = {}) => { warning(activeRef.current, navigateEffectWarning); if (!activeRef.current) return; if (typeof to === "number") { navigator2.go(to); return; } let path = resolveTo( to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path" ); if (dataRouterContext == null && basename !== "/") { path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]); } (!!options.replace ? navigator2.replace : navigator2.push)( path, options.state, options ); }, [ basename, navigator2, routePathnamesJson, locationPathname, dataRouterContext ] ); return navigate; } var OutletContext = React2.createContext(null); function useOutletContext() { return React2.useContext(OutletContext); } function useOutlet(context) { let outlet = React2.useContext(RouteContext).outlet; if (outlet) { return React2.createElement(OutletContext.Provider, { value: context }, outlet); } return outlet; } function useParams() { let { matches } = React2.useContext(RouteContext); let routeMatch = matches[matches.length - 1]; return routeMatch ? routeMatch.params : {}; } function useResolvedPath(to, { relative } = {}) { let { matches } = React2.useContext(RouteContext); let { pathname: locationPathname } = useLocation(); let routePathnamesJson = JSON.stringify(getResolveToMatches(matches)); return React2.useMemo( () => resolveTo( to, JSON.parse(routePathnamesJson), locationPathname, relative === "path" ), [to, routePathnamesJson, locationPathname, relative] ); } function useRoutes(routes, locationArg) { return useRoutesImpl(routes, locationArg); } function useRoutesImpl(routes, locationArg, dataRouterState, future) { invariant( useInRouterContext(), // TODO: This error is probably because they somehow have 2 versions of the // router loaded. We can help them understand how to avoid that. `useRoutes() may be used only in the context of a component.` ); let { navigator: navigator2, static: isStatic } = React2.useContext(NavigationContext); let { matches: parentMatches } = React2.useContext(RouteContext); let routeMatch = parentMatches[parentMatches.length - 1]; let parentParams = routeMatch ? routeMatch.params : {}; let parentPathname = routeMatch ? routeMatch.pathname : "/"; let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/"; let parentRoute = routeMatch && routeMatch.route; if (ENABLE_DEV_WARNINGS) { let parentPath = parentRoute && parentRoute.path || ""; warningOnce( parentPathname, !parentRoute || parentPath.endsWith("*") || parentPath.endsWith("*?"), `You rendered descendant (or called \`useRoutes()\`) at "${parentPathname}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. Please change the parent to .` ); } let locationFromContext = useLocation(); let location; if (locationArg) { let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg; invariant( parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase), `When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${parentPathnameBase}" but pathname "${parsedLocationArg.pathname}" was given in the \`location\` prop.` ); location = parsedLocationArg; } else { location = locationFromContext; } let pathname = location.pathname || "/"; let remainingPathname = pathname; if (parentPathnameBase !== "/") { let parentSegments = parentPathnameBase.replace(/^\//, "").split("/"); let segments = pathname.replace(/^\//, "").split("/"); remainingPathname = "/" + segments.slice(parentSegments.length).join("/"); } let matches = !isStatic && dataRouterState && dataRouterState.matches && dataRouterState.matches.length > 0 ? dataRouterState.matches : matchRoutes(routes, { pathname: remainingPathname }); if (ENABLE_DEV_WARNINGS) { warning( parentRoute || matches != null, `No routes matched location "${location.pathname}${location.search}${location.hash}" ` ); warning( matches == null || matches[matches.length - 1].route.element !== void 0 || matches[matches.length - 1].route.Component !== void 0 || matches[matches.length - 1].route.lazy !== void 0, `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.` ); } let renderedMatches = _renderMatches( matches && matches.map( (match) => Object.assign({}, match, { params: Object.assign({}, parentParams, match.params), pathname: joinPaths([ parentPathnameBase, // Re-encode pathnames that were decoded inside matchRoutes navigator2.encodeLocation ? navigator2.encodeLocation(match.pathname).pathname : match.pathname ]), pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([ parentPathnameBase, // Re-encode pathnames that were decoded inside matchRoutes navigator2.encodeLocation ? navigator2.encodeLocation(match.pathnameBase).pathname : match.pathnameBase ]) }) ), parentMatches, dataRouterState, future ); if (locationArg && renderedMatches) { return React2.createElement( LocationContext.Provider, { value: { location: { pathname: "/", search: "", hash: "", state: null, key: "default", ...location }, navigationType: "POP" /* Pop */ } }, renderedMatches ); } return renderedMatches; } function DefaultErrorComponent() { let error = useRouteError(); let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error); let stack = error instanceof Error ? error.stack : null; let lightgrey = "rgba(200,200,200, 0.5)"; let preStyles = { padding: "0.5rem", backgroundColor: lightgrey }; let codeStyles = { padding: "2px 4px", backgroundColor: lightgrey }; let devInfo = null; if (ENABLE_DEV_WARNINGS) { console.error( "Error handled by React Router default ErrorBoundary:", error ); devInfo = React2.createElement(React2.Fragment, null, React2.createElement("p", null, "💿 Hey developer 👋"), React2.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", React2.createElement("code", { style: codeStyles }, "ErrorBoundary"), " or", " ", React2.createElement("code", { style: codeStyles }, "errorElement"), " prop on your route.")); } return React2.createElement(React2.Fragment, null, React2.createElement("h2", null, "Unexpected Application Error!"), React2.createElement("h3", { style: { fontStyle: "italic" } }, message), stack ? React2.createElement("pre", { style: preStyles }, stack) : null, devInfo); } var defaultErrorElement = React2.createElement(DefaultErrorComponent, null); var RenderErrorBoundary = class extends React2.Component { constructor(props) { super(props); this.state = { location: props.location, revalidation: props.revalidation, error: props.error }; } static getDerivedStateFromError(error) { return { error }; } static getDerivedStateFromProps(props, state) { if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") { return { error: props.error, location: props.location, revalidation: props.revalidation }; } return { error: props.error !== void 0 ? props.error : state.error, location: state.location, revalidation: props.revalidation || state.revalidation }; } componentDidCatch(error, errorInfo) { console.error( "React Router caught the following error during render", error, errorInfo ); } render() { return this.state.error !== void 0 ? React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, React2.createElement( RouteErrorContext.Provider, { value: this.state.error, children: this.props.component } )) : this.props.children; } }; function RenderedRoute({ routeContext, match, children }) { let dataRouterContext = React2.useContext(DataRouterContext); if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) { dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id; } return React2.createElement(RouteContext.Provider, { value: routeContext }, children); } function _renderMatches(matches, parentMatches = [], dataRouterState = null, future = null) { if (matches == null) { if (!dataRouterState) { return null; } if (dataRouterState.errors) { matches = dataRouterState.matches; } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) { matches = dataRouterState.matches; } else { return null; } } let renderedMatches = matches; let errors = dataRouterState?.errors; if (errors != null) { let errorIndex = renderedMatches.findIndex( (m) => m.route.id && errors?.[m.route.id] !== void 0 ); invariant( errorIndex >= 0, `Could not find a matching route for errors on route IDs: ${Object.keys( errors ).join(",")}` ); renderedMatches = renderedMatches.slice( 0, Math.min(renderedMatches.length, errorIndex + 1) ); } let renderFallback = false; let fallbackIndex = -1; if (dataRouterState) { for (let i = 0; i < renderedMatches.length; i++) { let match = renderedMatches[i]; if (match.route.HydrateFallback || match.route.hydrateFallbackElement) { fallbackIndex = i; } if (match.route.id) { let { loaderData, errors: errors2 } = dataRouterState; let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0); if (match.route.lazy || needsToRunLoader) { renderFallback = true; if (fallbackIndex >= 0) { renderedMatches = renderedMatches.slice(0, fallbackIndex + 1); } else { renderedMatches = [renderedMatches[0]]; } break; } } } } return renderedMatches.reduceRight((outlet, match, index) => { let error; let shouldRenderHydrateFallback = false; let errorElement = null; let hydrateFallbackElement = null; if (dataRouterState) { error = errors && match.route.id ? errors[match.route.id] : void 0; errorElement = match.route.errorElement || defaultErrorElement; if (renderFallback) { if (fallbackIndex < 0 && index === 0) { warningOnce( "route-fallback", false, "No `HydrateFallback` element provided to render during initial hydration" ); shouldRenderHydrateFallback = true; hydrateFallbackElement = null; } else if (fallbackIndex === index) { shouldRenderHydrateFallback = true; hydrateFallbackElement = match.route.hydrateFallbackElement || null; } } } let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1)); let getChildren = () => { let children; if (error) { children = errorElement; } else if (shouldRenderHydrateFallback) { children = hydrateFallbackElement; } else if (match.route.Component) { children = React2.createElement(match.route.Component, null); } else if (match.route.element) { children = match.route.element; } else { children = outlet; } return React2.createElement( RenderedRoute, { match, routeContext: { outlet, matches: matches2, isDataRoute: dataRouterState != null }, children } ); }; return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? React2.createElement( RenderErrorBoundary, { location: dataRouterState.location, revalidation: dataRouterState.revalidation, component: errorElement, error, children: getChildren(), routeContext: { outlet: null, matches: matches2, isDataRoute: true } } ) : getChildren(); }, null); } function getDataRouterConsoleError(hookName) { return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`; } function useDataRouterContext(hookName) { let ctx = React2.useContext(DataRouterContext); invariant(ctx, getDataRouterConsoleError(hookName)); return ctx; } function useDataRouterState(hookName) { let state = React2.useContext(DataRouterStateContext); invariant(state, getDataRouterConsoleError(hookName)); return state; } function useRouteContext(hookName) { let route = React2.useContext(RouteContext); invariant(route, getDataRouterConsoleError(hookName)); return route; } function useCurrentRouteId(hookName) { let route = useRouteContext(hookName); let thisRoute = route.matches[route.matches.length - 1]; invariant( thisRoute.route.id, `${hookName} can only be used on routes that contain a unique "id"` ); return thisRoute.route.id; } function useRouteId() { return useCurrentRouteId( "useRouteId" /* UseRouteId */ ); } function useNavigation() { let state = useDataRouterState( "useNavigation" /* UseNavigation */ ); return state.navigation; } function useRevalidator() { let dataRouterContext = useDataRouterContext( "useRevalidator" /* UseRevalidator */ ); let state = useDataRouterState( "useRevalidator" /* UseRevalidator */ ); return React2.useMemo( () => ({ async revalidate() { await dataRouterContext.router.revalidate(); }, state: state.revalidation }), [dataRouterContext.router, state.revalidation] ); } function useMatches() { let { matches, loaderData } = useDataRouterState( "useMatches" /* UseMatches */ ); return React2.useMemo( () => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)), [matches, loaderData] ); } function useLoaderData() { let state = useDataRouterState( "useLoaderData" /* UseLoaderData */ ); let routeId = useCurrentRouteId( "useLoaderData" /* UseLoaderData */ ); return state.loaderData[routeId]; } function useRouteLoaderData(routeId) { let state = useDataRouterState( "useRouteLoaderData" /* UseRouteLoaderData */ ); return state.loaderData[routeId]; } function useActionData() { let state = useDataRouterState( "useActionData" /* UseActionData */ ); let routeId = useCurrentRouteId( "useLoaderData" /* UseLoaderData */ ); return state.actionData ? state.actionData[routeId] : void 0; } function useRouteError() { let error = React2.useContext(RouteErrorContext); let state = useDataRouterState( "useRouteError" /* UseRouteError */ ); let routeId = useCurrentRouteId( "useRouteError" /* UseRouteError */ ); if (error !== void 0) { return error; } return state.errors?.[routeId]; } function useAsyncValue() { let value = React2.useContext(AwaitContext); return value?._data; } function useAsyncError() { let value = React2.useContext(AwaitContext); return value?._error; } var blockerId = 0; function useBlocker(shouldBlock) { let { router: router2, basename } = useDataRouterContext( "useBlocker" /* UseBlocker */ ); let state = useDataRouterState( "useBlocker" /* UseBlocker */ ); let [blockerKey, setBlockerKey] = React2.useState(""); let blockerFunction = React2.useCallback( (arg) => { if (typeof shouldBlock !== "function") { return !!shouldBlock; } if (basename === "/") { return shouldBlock(arg); } let { currentLocation, nextLocation, historyAction } = arg; return shouldBlock({ currentLocation: { ...currentLocation, pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname }, nextLocation: { ...nextLocation, pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname }, historyAction }); }, [basename, shouldBlock] ); React2.useEffect(() => { let key = String(++blockerId); setBlockerKey(key); return () => router2.deleteBlocker(key); }, [router2]); React2.useEffect(() => { if (blockerKey !== "") { router2.getBlocker(blockerKey, blockerFunction); } }, [router2, blockerKey, blockerFunction]); return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER; } function useNavigateStable() { let { router: router2 } = useDataRouterContext( "useNavigate" /* UseNavigateStable */ ); let id = useCurrentRouteId( "useNavigate" /* UseNavigateStable */ ); let activeRef = React2.useRef(false); useIsomorphicLayoutEffect(() => { activeRef.current = true; }); let navigate = React2.useCallback( async (to, options = {}) => { warning(activeRef.current, navigateEffectWarning); if (!activeRef.current) return; if (typeof to === "number") { router2.navigate(to); } else { await router2.navigate(to, { fromRouteId: id, ...options }); } }, [router2, id] ); return navigate; } var alreadyWarned = {}; function warningOnce(key, cond, message) { if (!cond && !alreadyWarned[key]) { alreadyWarned[key] = true; warning(false, message); } } var alreadyWarned2 = {}; function warnOnce(condition, message) { if (!condition && !alreadyWarned2[message]) { alreadyWarned2[message] = true; console.warn(message); } } var ENABLE_DEV_WARNINGS2 = true; function mapRouteProperties(route) { let updates = { // Note: this check also occurs in createRoutesFromChildren so update // there if you change this -- please and thank you! hasErrorBoundary: route.hasErrorBoundary || route.ErrorBoundary != null || route.errorElement != null }; if (route.Component) { if (ENABLE_DEV_WARNINGS2) { if (route.element) { warning( false, "You should not include both `Component` and `element` on your route - `Component` will be used." ); } } Object.assign(updates, { element: React3.createElement(route.Component), Component: void 0 }); } if (route.HydrateFallback) { if (ENABLE_DEV_WARNINGS2) { if (route.hydrateFallbackElement) { warning( false, "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used." ); } } Object.assign(updates, { hydrateFallbackElement: React3.createElement(route.HydrateFallback), HydrateFallback: void 0 }); } if (route.ErrorBoundary) { if (ENABLE_DEV_WARNINGS2) { if (route.errorElement) { warning( false, "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used." ); } } Object.assign(updates, { errorElement: React3.createElement(route.ErrorBoundary), ErrorBoundary: void 0 }); } return updates; } function createMemoryRouter(routes, opts) { return createRouter({ basename: opts?.basename, unstable_getContext: opts?.unstable_getContext, future: opts?.future, history: createMemoryHistory({ initialEntries: opts?.initialEntries, initialIndex: opts?.initialIndex }), hydrationData: opts?.hydrationData, routes, mapRouteProperties, dataStrategy: opts?.dataStrategy, patchRoutesOnNavigation: opts?.patchRoutesOnNavigation }).initia