2026-02-04 00:11:19 +05:00
import {
require _react _dom
} from "./chunk-BCXODTBQ.js" ;
import {
_ _toESM ,
require _react
} from "./chunk-2YIMICFJ.js" ;
2026-02-10 13:03:46 +05:00
// node_modules/react-router-dom/dist/index.js
var React2 = _ _toESM ( require _react ( ) ) ;
var ReactDOM = _ _toESM ( require _react _dom ( ) ) ;
2026-02-04 00:11:19 +05:00
2026-02-10 13:03:46 +05:00
// node_modules/react-router/dist/index.js
var React = _ _toESM ( require _react ( ) ) ;
// node_modules/@remix-run/router/dist/router.js
function _extends ( ) {
_extends = Object . assign ? Object . assign . bind ( ) : function ( target ) {
for ( var i = 1 ; i < arguments . length ; i ++ ) {
var source = arguments [ i ] ;
for ( var key in source ) {
if ( Object . prototype . hasOwnProperty . call ( source , key ) ) {
target [ key ] = source [ key ] ;
2026-02-04 00:11:19 +05:00
}
}
}
2026-02-10 13:03:46 +05:00
return target ;
} ;
return _extends . apply ( this , arguments ) ;
}
var Action ;
( function ( Action2 ) {
2026-02-04 00:11:19 +05:00
Action2 [ "Pop" ] = "POP" ;
Action2 [ "Push" ] = "PUSH" ;
Action2 [ "Replace" ] = "REPLACE" ;
2026-02-10 13:03:46 +05:00
} ) ( Action || ( Action = { } ) ) ;
2026-02-04 00:11:19 +05:00
var PopStateEventType = "popstate" ;
2026-02-10 13:03:46 +05:00
function createMemoryHistory ( options ) {
if ( options === void 0 ) {
options = { } ;
}
let {
initialEntries = [ "/" ] ,
initialIndex ,
v5Compat = false
} = options ;
2026-02-04 00:11:19 +05:00
let entries ;
2026-02-10 13:03:46 +05:00
entries = initialEntries . map ( ( entry , index2 ) => createMemoryLocation ( entry , typeof entry === "string" ? null : entry . state , index2 === 0 ? "default" : void 0 ) ) ;
let index = clampIndex ( initialIndex == null ? entries . length - 1 : initialIndex ) ;
let action = Action . Pop ;
2026-02-04 00:11:19 +05:00
let listener = null ;
function clampIndex ( n ) {
return Math . min ( Math . max ( n , 0 ) , entries . length - 1 ) ;
}
function getCurrentLocation ( ) {
return entries [ index ] ;
}
2026-02-10 13:03:46 +05:00
function createMemoryLocation ( to , state , key ) {
if ( state === void 0 ) {
state = null ;
}
let location = createLocation ( entries ? getCurrentLocation ( ) . pathname : "/" , to , state , key ) ;
warning ( location . pathname . charAt ( 0 ) === "/" , "relative pathnames are not supported in memory history: " + JSON . stringify ( to ) ) ;
return location ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function createHref ( to ) {
2026-02-04 00:11:19 +05:00
return typeof to === "string" ? to : createPath ( to ) ;
}
let history = {
get index ( ) {
return index ;
} ,
get action ( ) {
return action ;
} ,
get location ( ) {
return getCurrentLocation ( ) ;
} ,
2026-02-10 13:03:46 +05:00
createHref ,
2026-02-04 00:11:19 +05:00
createURL ( to ) {
2026-02-10 13:03:46 +05:00
return new URL ( createHref ( to ) , "http://localhost" ) ;
2026-02-04 00:11:19 +05:00
} ,
encodeLocation ( to ) {
let path = typeof to === "string" ? parsePath ( to ) : to ;
return {
pathname : path . pathname || "" ,
search : path . search || "" ,
hash : path . hash || ""
} ;
} ,
push ( to , state ) {
2026-02-10 13:03:46 +05:00
action = Action . Push ;
2026-02-04 00:11:19 +05:00
let nextLocation = createMemoryLocation ( to , state ) ;
index += 1 ;
entries . splice ( index , entries . length , nextLocation ) ;
if ( v5Compat && listener ) {
2026-02-10 13:03:46 +05:00
listener ( {
action ,
location : nextLocation ,
delta : 1
} ) ;
2026-02-04 00:11:19 +05:00
}
} ,
replace ( to , state ) {
2026-02-10 13:03:46 +05:00
action = Action . Replace ;
2026-02-04 00:11:19 +05:00
let nextLocation = createMemoryLocation ( to , state ) ;
entries [ index ] = nextLocation ;
if ( v5Compat && listener ) {
2026-02-10 13:03:46 +05:00
listener ( {
action ,
location : nextLocation ,
delta : 0
} ) ;
2026-02-04 00:11:19 +05:00
}
} ,
go ( delta ) {
2026-02-10 13:03:46 +05:00
action = Action . Pop ;
2026-02-04 00:11:19 +05:00
let nextIndex = clampIndex ( index + delta ) ;
let nextLocation = entries [ nextIndex ] ;
index = nextIndex ;
if ( listener ) {
2026-02-10 13:03:46 +05:00
listener ( {
action ,
location : nextLocation ,
delta
} ) ;
2026-02-04 00:11:19 +05:00
}
} ,
listen ( fn ) {
listener = fn ;
return ( ) => {
listener = null ;
} ;
}
} ;
return history ;
}
2026-02-10 13:03:46 +05:00
function createBrowserHistory ( options ) {
if ( options === void 0 ) {
options = { } ;
}
2026-02-04 00:11:19 +05:00
function createBrowserLocation ( window2 , globalHistory ) {
2026-02-10 13:03:46 +05:00
let {
pathname ,
search ,
hash
} = window2 . location ;
2026-02-04 00:11:19 +05:00
return createLocation (
"" ,
2026-02-10 13:03:46 +05:00
{
pathname ,
search ,
hash
} ,
2026-02-04 00:11:19 +05:00
// state defaults to `null` because `window.history.state` does
globalHistory . state && globalHistory . state . usr || null ,
globalHistory . state && globalHistory . state . key || "default"
) ;
}
function createBrowserHref ( window2 , to ) {
return typeof to === "string" ? to : createPath ( to ) ;
}
2026-02-10 13:03:46 +05:00
return getUrlBasedHistory ( createBrowserLocation , createBrowserHref , null , options ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function createHashHistory ( options ) {
if ( options === void 0 ) {
options = { } ;
}
2026-02-04 00:11:19 +05:00
function createHashLocation ( window2 , globalHistory ) {
let {
pathname = "/" ,
search = "" ,
hash = ""
2026-02-10 13:03:46 +05:00
} = parsePath ( window2 . location . hash . substr ( 1 ) ) ;
2026-02-04 00:11:19 +05:00
if ( ! pathname . startsWith ( "/" ) && ! pathname . startsWith ( "." ) ) {
pathname = "/" + pathname ;
}
return createLocation (
"" ,
2026-02-10 13:03:46 +05:00
{
pathname ,
search ,
hash
} ,
2026-02-04 00:11:19 +05:00
// state defaults to `null` because `window.history.state` does
globalHistory . state && globalHistory . state . usr || null ,
globalHistory . state && globalHistory . state . key || "default"
) ;
}
function createHashHref ( window2 , to ) {
let base = window2 . document . querySelector ( "base" ) ;
2026-02-10 13:03:46 +05:00
let href = "" ;
2026-02-04 00:11:19 +05:00
if ( base && base . getAttribute ( "href" ) ) {
let url = window2 . location . href ;
let hashIndex = url . indexOf ( "#" ) ;
2026-02-10 13:03:46 +05:00
href = hashIndex === - 1 ? url : url . slice ( 0 , hashIndex ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return href + "#" + ( typeof to === "string" ? to : createPath ( to ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function validateHashLocation ( location , to ) {
warning ( location . pathname . charAt ( 0 ) === "/" , "relative pathnames are not supported in hash history.push(" + JSON . stringify ( to ) + ")" ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return getUrlBasedHistory ( createHashLocation , createHashHref , validateHashLocation , options ) ;
2026-02-04 00:11:19 +05:00
}
function invariant ( value , message ) {
if ( value === false || value === null || typeof value === "undefined" ) {
throw new Error ( message ) ;
}
}
function warning ( cond , message ) {
if ( ! cond ) {
if ( typeof console !== "undefined" ) console . warn ( message ) ;
try {
throw new Error ( message ) ;
} catch ( e ) {
}
}
}
function createKey ( ) {
2026-02-10 13:03:46 +05:00
return Math . random ( ) . toString ( 36 ) . substr ( 2 , 8 ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function getHistoryState ( location , index ) {
2026-02-04 00:11:19 +05:00
return {
2026-02-10 13:03:46 +05:00
usr : location . state ,
key : location . key ,
2026-02-04 00:11:19 +05:00
idx : index
} ;
}
2026-02-10 13:03:46 +05:00
function createLocation ( current , to , state , key ) {
if ( state === void 0 ) {
state = null ;
}
let location = _extends ( {
2026-02-04 00:11:19 +05:00
pathname : typeof current === "string" ? current : current . pathname ,
search : "" ,
2026-02-10 13:03:46 +05:00
hash : ""
} , typeof to === "string" ? parsePath ( to ) : to , {
2026-02-04 00:11:19 +05:00
state ,
// TODO: This could be cleaned up. push/replace should probably just take
// full Locations now and avoid the need to run through this flow at all
// But that's a pretty big refactor to the current test suite so going to
// keep as is for the time being and just let any incoming keys take precedence
key : to && to . key || key || createKey ( )
2026-02-10 13:03:46 +05:00
} ) ;
return location ;
}
function createPath ( _ref ) {
let {
pathname = "/" ,
search = "" ,
hash = ""
} = _ref ;
if ( search && search !== "?" ) pathname += search . charAt ( 0 ) === "?" ? search : "?" + search ;
if ( hash && hash !== "#" ) pathname += hash . charAt ( 0 ) === "#" ? hash : "#" + hash ;
2026-02-04 00:11:19 +05:00
return pathname ;
}
function parsePath ( path ) {
let parsedPath = { } ;
if ( path ) {
let hashIndex = path . indexOf ( "#" ) ;
if ( hashIndex >= 0 ) {
2026-02-10 13:03:46 +05:00
parsedPath . hash = path . substr ( hashIndex ) ;
path = path . substr ( 0 , hashIndex ) ;
2026-02-04 00:11:19 +05:00
}
let searchIndex = path . indexOf ( "?" ) ;
if ( searchIndex >= 0 ) {
2026-02-10 13:03:46 +05:00
parsedPath . search = path . substr ( searchIndex ) ;
path = path . substr ( 0 , searchIndex ) ;
2026-02-04 00:11:19 +05:00
}
if ( path ) {
parsedPath . pathname = path ;
}
}
return parsedPath ;
}
2026-02-10 13:03:46 +05:00
function getUrlBasedHistory ( getLocation , createHref , validateLocation , options ) {
if ( options === void 0 ) {
options = { } ;
}
let {
window : window2 = document . defaultView ,
v5Compat = false
} = options ;
2026-02-04 00:11:19 +05:00
let globalHistory = window2 . history ;
2026-02-10 13:03:46 +05:00
let action = Action . Pop ;
2026-02-04 00:11:19 +05:00
let listener = null ;
let index = getIndex ( ) ;
if ( index == null ) {
index = 0 ;
2026-02-10 13:03:46 +05:00
globalHistory . replaceState ( _extends ( { } , globalHistory . state , {
idx : index
} ) , "" ) ;
2026-02-04 00:11:19 +05:00
}
function getIndex ( ) {
2026-02-10 13:03:46 +05:00
let state = globalHistory . state || {
idx : null
} ;
2026-02-04 00:11:19 +05:00
return state . idx ;
}
function handlePop ( ) {
2026-02-10 13:03:46 +05:00
action = Action . Pop ;
2026-02-04 00:11:19 +05:00
let nextIndex = getIndex ( ) ;
let delta = nextIndex == null ? null : nextIndex - index ;
index = nextIndex ;
if ( listener ) {
2026-02-10 13:03:46 +05:00
listener ( {
action ,
location : history . location ,
delta
} ) ;
2026-02-04 00:11:19 +05:00
}
}
function push ( to , state ) {
2026-02-10 13:03:46 +05:00
action = Action . Push ;
let location = createLocation ( history . location , to , state ) ;
if ( validateLocation ) validateLocation ( location , to ) ;
2026-02-04 00:11:19 +05:00
index = getIndex ( ) + 1 ;
2026-02-10 13:03:46 +05:00
let historyState = getHistoryState ( location , index ) ;
let url = history . createHref ( location ) ;
2026-02-04 00:11:19 +05:00
try {
globalHistory . pushState ( historyState , "" , url ) ;
} catch ( error ) {
if ( error instanceof DOMException && error . name === "DataCloneError" ) {
throw error ;
}
window2 . location . assign ( url ) ;
}
if ( v5Compat && listener ) {
2026-02-10 13:03:46 +05:00
listener ( {
action ,
location : history . location ,
delta : 1
} ) ;
2026-02-04 00:11:19 +05:00
}
}
function replace2 ( to , state ) {
2026-02-10 13:03:46 +05:00
action = Action . Replace ;
let location = createLocation ( history . location , to , state ) ;
if ( validateLocation ) validateLocation ( location , to ) ;
2026-02-04 00:11:19 +05:00
index = getIndex ( ) ;
2026-02-10 13:03:46 +05:00
let historyState = getHistoryState ( location , index ) ;
let url = history . createHref ( location ) ;
2026-02-04 00:11:19 +05:00
globalHistory . replaceState ( historyState , "" , url ) ;
if ( v5Compat && listener ) {
2026-02-10 13:03:46 +05:00
listener ( {
action ,
location : history . location ,
delta : 0
} ) ;
2026-02-04 00:11:19 +05:00
}
}
function createURL ( to ) {
2026-02-10 13:03:46 +05:00
let base = window2 . location . origin !== "null" ? window2 . location . origin : window2 . location . href ;
let href = typeof to === "string" ? to : createPath ( to ) ;
href = href . replace ( / $/ , "%20" ) ;
invariant ( base , "No window.location.(origin|href) available to create URL for href: " + href ) ;
return new URL ( href , base ) ;
2026-02-04 00:11:19 +05:00
}
let history = {
get action ( ) {
return action ;
} ,
get location ( ) {
return getLocation ( window2 , globalHistory ) ;
} ,
listen ( fn ) {
if ( listener ) {
throw new Error ( "A history only accepts one active listener" ) ;
}
window2 . addEventListener ( PopStateEventType , handlePop ) ;
listener = fn ;
return ( ) => {
window2 . removeEventListener ( PopStateEventType , handlePop ) ;
listener = null ;
} ;
} ,
createHref ( to ) {
2026-02-10 13:03:46 +05:00
return createHref ( window2 , to ) ;
2026-02-04 00:11:19 +05:00
} ,
createURL ,
encodeLocation ( to ) {
let url = createURL ( to ) ;
return {
pathname : url . pathname ,
search : url . search ,
hash : url . hash
} ;
} ,
push ,
replace : replace2 ,
go ( n ) {
return globalHistory . go ( n ) ;
}
} ;
return history ;
}
2026-02-10 13:03:46 +05:00
var ResultType ;
( function ( ResultType2 ) {
ResultType2 [ "data" ] = "data" ;
ResultType2 [ "deferred" ] = "deferred" ;
ResultType2 [ "redirect" ] = "redirect" ;
ResultType2 [ "error" ] = "error" ;
} ) ( ResultType || ( ResultType = { } ) ) ;
var immutableRouteKeys = /* @__PURE__ */ new Set ( [ "lazy" , "caseSensitive" , "path" , "id" , "index" , "children" ] ) ;
2026-02-04 00:11:19 +05:00
function isIndexRoute ( route ) {
return route . index === true ;
}
2026-02-10 13:03:46 +05:00
function convertRoutesToDataRoutes ( routes , mapRouteProperties2 , parentPath , manifest ) {
if ( parentPath === void 0 ) {
parentPath = [ ] ;
}
if ( manifest === void 0 ) {
manifest = { } ;
}
2026-02-04 00:11:19 +05:00
return routes . map ( ( route , index ) => {
let treePath = [ ... parentPath , String ( index ) ] ;
let id = typeof route . id === "string" ? route . id : treePath . join ( "-" ) ;
2026-02-10 13:03:46 +05:00
invariant ( route . index !== true || ! route . children , "Cannot specify children on an index route" ) ;
invariant ( ! manifest [ id ] , 'Found a route id collision on id "' + id + ` ". Route id's must be globally unique within Data Router usages ` ) ;
2026-02-04 00:11:19 +05:00
if ( isIndexRoute ( route ) ) {
2026-02-10 13:03:46 +05:00
let indexRoute = _extends ( { } , route , mapRouteProperties2 ( route ) , {
2026-02-04 00:11:19 +05:00
id
2026-02-10 13:03:46 +05:00
} ) ;
manifest [ id ] = indexRoute ;
2026-02-04 00:11:19 +05:00
return indexRoute ;
} else {
2026-02-10 13:03:46 +05:00
let pathOrLayoutRoute = _extends ( { } , route , mapRouteProperties2 ( route ) , {
2026-02-04 00:11:19 +05:00
id ,
children : void 0
2026-02-10 13:03:46 +05:00
} ) ;
manifest [ id ] = pathOrLayoutRoute ;
2026-02-04 00:11:19 +05:00
if ( route . children ) {
2026-02-10 13:03:46 +05:00
pathOrLayoutRoute . children = convertRoutesToDataRoutes ( route . children , mapRouteProperties2 , treePath , manifest ) ;
2026-02-04 00:11:19 +05:00
}
return pathOrLayoutRoute ;
}
} ) ;
}
2026-02-10 13:03:46 +05:00
function matchRoutes ( routes , locationArg , basename ) {
if ( basename === void 0 ) {
basename = "/" ;
}
2026-02-04 00:11:19 +05:00
return matchRoutesImpl ( routes , locationArg , basename , false ) ;
}
function matchRoutesImpl ( routes , locationArg , basename , allowPartial ) {
2026-02-10 13:03:46 +05:00
let location = typeof locationArg === "string" ? parsePath ( locationArg ) : locationArg ;
let pathname = stripBasename ( location . pathname || "/" , basename ) ;
2026-02-04 00:11:19 +05:00
if ( pathname == null ) {
return null ;
}
let branches = flattenRoutes ( routes ) ;
rankRouteBranches ( branches ) ;
let matches = null ;
for ( let i = 0 ; matches == null && i < branches . length ; ++ i ) {
let decoded = decodePath ( pathname ) ;
2026-02-10 13:03:46 +05:00
matches = matchRouteBranch ( branches [ i ] , decoded , allowPartial ) ;
2026-02-04 00:11:19 +05:00
}
return matches ;
}
function convertRouteMatchToUiMatch ( match , loaderData ) {
2026-02-10 13:03:46 +05:00
let {
route ,
pathname ,
params
} = match ;
2026-02-04 00:11:19 +05:00
return {
id : route . id ,
pathname ,
params ,
data : loaderData [ route . id ] ,
handle : route . handle
} ;
}
2026-02-10 13:03:46 +05:00
function flattenRoutes ( routes , branches , parentsMeta , parentPath ) {
if ( branches === void 0 ) {
branches = [ ] ;
}
if ( parentsMeta === void 0 ) {
parentsMeta = [ ] ;
}
if ( parentPath === void 0 ) {
parentPath = "" ;
}
let flattenRoute = ( route , index , relativePath ) => {
2026-02-04 00:11:19 +05:00
let meta = {
relativePath : relativePath === void 0 ? route . path || "" : relativePath ,
caseSensitive : route . caseSensitive === true ,
childrenIndex : index ,
route
} ;
if ( meta . relativePath . startsWith ( "/" ) ) {
2026-02-10 13:03:46 +05:00
invariant ( meta . relativePath . startsWith ( parentPath ) , 'Absolute route path "' + meta . relativePath + '" nested under path ' + ( '"' + parentPath + '" is not valid. An absolute child route path ' ) + "must start with the combined path of all its parent routes." ) ;
2026-02-04 00:11:19 +05:00
meta . relativePath = meta . relativePath . slice ( parentPath . length ) ;
}
let path = joinPaths ( [ parentPath , meta . relativePath ] ) ;
let routesMeta = parentsMeta . concat ( meta ) ;
if ( route . children && route . children . length > 0 ) {
invariant (
// Our types know better, but runtime JS may not!
// @ts-expect-error
route . index !== true ,
2026-02-10 13:03:46 +05:00
"Index routes must not have child routes. Please remove " + ( 'all child routes from route path "' + path + '".' )
2026-02-04 00:11:19 +05:00
) ;
2026-02-10 13:03:46 +05:00
flattenRoutes ( route . children , branches , routesMeta , path ) ;
2026-02-04 00:11:19 +05:00
}
if ( route . path == null && ! route . index ) {
return ;
}
branches . push ( {
path ,
score : computeScore ( path , route . index ) ,
routesMeta
} ) ;
} ;
routes . forEach ( ( route , index ) => {
2026-02-10 13:03:46 +05:00
var _route$path ;
if ( route . path === "" || ! ( ( _route$path = route . path ) != null && _route$path . includes ( "?" ) ) ) {
2026-02-04 00:11:19 +05:00
flattenRoute ( route , index ) ;
} else {
for ( let exploded of explodeOptionalSegments ( route . path ) ) {
2026-02-10 13:03:46 +05:00
flattenRoute ( route , index , exploded ) ;
2026-02-04 00:11:19 +05:00
}
}
} ) ;
return branches ;
}
function explodeOptionalSegments ( path ) {
let segments = path . split ( "/" ) ;
if ( segments . length === 0 ) return [ ] ;
let [ first , ... rest ] = segments ;
let isOptional = first . endsWith ( "?" ) ;
let required = first . replace ( /\?$/ , "" ) ;
if ( rest . length === 0 ) {
return isOptional ? [ required , "" ] : [ required ] ;
}
let restExploded = explodeOptionalSegments ( rest . join ( "/" ) ) ;
let result = [ ] ;
2026-02-10 13:03:46 +05:00
result . push ( ... restExploded . map ( ( subpath ) => subpath === "" ? required : [ required , subpath ] . join ( "/" ) ) ) ;
2026-02-04 00:11:19 +05:00
if ( isOptional ) {
result . push ( ... restExploded ) ;
}
2026-02-10 13:03:46 +05:00
return result . map ( ( exploded ) => path . startsWith ( "/" ) && exploded === "" ? "/" : exploded ) ;
2026-02-04 00:11:19 +05:00
}
function rankRouteBranches ( branches ) {
2026-02-10 13:03:46 +05:00
branches . sort ( ( a , b ) => a . score !== b . score ? b . score - a . score : compareIndexes ( a . routesMeta . map ( ( meta ) => meta . childrenIndex ) , b . routesMeta . map ( ( meta ) => meta . childrenIndex ) ) ) ;
2026-02-04 00:11:19 +05:00
}
var paramRe = /^:[\w-]+$/ ;
var dynamicSegmentValue = 3 ;
var indexRouteValue = 2 ;
var emptySegmentValue = 1 ;
var staticSegmentValue = 10 ;
var splatPenalty = - 2 ;
var isSplat = ( s ) => s === "*" ;
function computeScore ( path , index ) {
let segments = path . split ( "/" ) ;
let initialScore = segments . length ;
if ( segments . some ( isSplat ) ) {
initialScore += splatPenalty ;
}
if ( index ) {
initialScore += indexRouteValue ;
}
2026-02-10 13:03:46 +05:00
return segments . filter ( ( s ) => ! isSplat ( s ) ) . reduce ( ( score , segment ) => score + ( paramRe . test ( segment ) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue ) , initialScore ) ;
2026-02-04 00:11:19 +05:00
}
function compareIndexes ( a , b ) {
let siblings = a . length === b . length && a . slice ( 0 , - 1 ) . every ( ( n , i ) => n === b [ i ] ) ;
return siblings ? (
// If two routes are siblings, we should try to match the earlier sibling
// first. This allows people to have fine-grained control over the matching
// behavior by simply putting routes with identical paths in the order they
// want them tried.
a [ a . length - 1 ] - b [ b . length - 1 ]
) : (
// Otherwise, it doesn't really make sense to rank non-siblings by index,
// so they sort equally.
0
) ;
}
2026-02-10 13:03:46 +05:00
function matchRouteBranch ( branch , pathname , allowPartial ) {
if ( allowPartial === void 0 ) {
allowPartial = false ;
}
let {
routesMeta
} = branch ;
2026-02-04 00:11:19 +05:00
let matchedParams = { } ;
let matchedPathname = "/" ;
let matches = [ ] ;
for ( let i = 0 ; i < routesMeta . length ; ++ i ) {
let meta = routesMeta [ i ] ;
let end = i === routesMeta . length - 1 ;
let remainingPathname = matchedPathname === "/" ? pathname : pathname . slice ( matchedPathname . length ) || "/" ;
2026-02-10 13:03:46 +05:00
let match = matchPath ( {
path : meta . relativePath ,
caseSensitive : meta . caseSensitive ,
end
} , remainingPathname ) ;
2026-02-04 00:11:19 +05:00
let route = meta . route ;
if ( ! match && end && allowPartial && ! routesMeta [ routesMeta . length - 1 ] . route . index ) {
2026-02-10 13:03:46 +05:00
match = matchPath ( {
path : meta . relativePath ,
caseSensitive : meta . caseSensitive ,
end : false
} , remainingPathname ) ;
2026-02-04 00:11:19 +05:00
}
if ( ! match ) {
return null ;
}
Object . assign ( matchedParams , match . params ) ;
matches . push ( {
// TODO: Can this as be avoided?
params : matchedParams ,
pathname : joinPaths ( [ matchedPathname , match . pathname ] ) ,
2026-02-10 13:03:46 +05:00
pathnameBase : normalizePathname ( joinPaths ( [ matchedPathname , match . pathnameBase ] ) ) ,
2026-02-04 00:11:19 +05:00
route
} ) ;
if ( match . pathnameBase !== "/" ) {
matchedPathname = joinPaths ( [ matchedPathname , match . pathnameBase ] ) ;
}
}
return matches ;
}
2026-02-10 13:03:46 +05:00
function generatePath ( originalPath , params ) {
if ( params === void 0 ) {
params = { } ;
}
2026-02-04 00:11:19 +05:00
let path = originalPath ;
if ( path . endsWith ( "*" ) && path !== "*" && ! path . endsWith ( "/*" ) ) {
2026-02-10 13:03:46 +05:00
warning ( false , 'Route path "' + path + '" will be treated as if it were ' + ( '"' + path . replace ( /\*$/ , "/*" ) + '" because the `*` character must ' ) + "always follow a `/` in the pattern. To get rid of this warning, " + ( 'please change the route path to "' + path . replace ( /\*$/ , "/*" ) + '".' ) ) ;
2026-02-04 00:11:19 +05:00
path = path . replace ( /\*$/ , "/*" ) ;
}
const prefix = path . startsWith ( "/" ) ? "/" : "" ;
2026-02-10 13:03:46 +05:00
const stringify = ( p ) => p == null ? "" : typeof p === "string" ? p : String ( p ) ;
2026-02-04 00:11:19 +05:00
const segments = path . split ( /\/+/ ) . map ( ( segment , index , array ) => {
const isLastSegment = index === array . length - 1 ;
if ( isLastSegment && segment === "*" ) {
const star = "*" ;
2026-02-10 13:03:46 +05:00
return stringify ( params [ star ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
const keyMatch = segment . match ( /^:([\w-]+)(\??)$/ ) ;
2026-02-04 00:11:19 +05:00
if ( keyMatch ) {
2026-02-10 13:03:46 +05:00
const [ , key , optional ] = keyMatch ;
2026-02-04 00:11:19 +05:00
let param = params [ key ] ;
2026-02-10 13:03:46 +05:00
invariant ( optional === "?" || param != null , 'Missing ":' + key + '" param' ) ;
return stringify ( param ) ;
2026-02-04 00:11:19 +05:00
}
return segment . replace ( /\?$/g , "" ) ;
} ) . filter ( ( segment ) => ! ! segment ) ;
return prefix + segments . join ( "/" ) ;
}
function matchPath ( pattern , pathname ) {
if ( typeof pattern === "string" ) {
2026-02-10 13:03:46 +05:00
pattern = {
path : pattern ,
caseSensitive : false ,
end : true
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let [ matcher , compiledParams ] = compilePath ( pattern . path , pattern . caseSensitive , pattern . end ) ;
2026-02-04 00:11:19 +05:00
let match = pathname . match ( matcher ) ;
if ( ! match ) return null ;
let matchedPathname = match [ 0 ] ;
let pathnameBase = matchedPathname . replace ( /(.)\/+$/ , "$1" ) ;
let captureGroups = match . slice ( 1 ) ;
2026-02-10 13:03:46 +05:00
let params = compiledParams . reduce ( ( memo2 , _ref , index ) => {
let {
paramName ,
isOptional
} = _ref ;
if ( paramName === "*" ) {
let splatValue = captureGroups [ index ] || "" ;
pathnameBase = matchedPathname . slice ( 0 , matchedPathname . length - splatValue . length ) . replace ( /(.)\/+$/ , "$1" ) ;
}
const value = captureGroups [ index ] ;
if ( isOptional && ! value ) {
memo2 [ paramName ] = void 0 ;
} else {
memo2 [ paramName ] = ( value || "" ) . replace ( /%2F/g , "/" ) ;
}
return memo2 ;
} , { } ) ;
2026-02-04 00:11:19 +05:00
return {
params ,
pathname : matchedPathname ,
pathnameBase ,
pattern
} ;
}
2026-02-10 13:03:46 +05:00
function compilePath ( path , caseSensitive , end ) {
if ( caseSensitive === void 0 ) {
caseSensitive = false ;
}
if ( end === void 0 ) {
end = true ;
}
warning ( path === "*" || ! path . endsWith ( "*" ) || path . endsWith ( "/*" ) , 'Route path "' + path + '" will be treated as if it were ' + ( '"' + path . replace ( /\*$/ , "/*" ) + '" because the `*` character must ' ) + "always follow a `/` in the pattern. To get rid of this warning, " + ( 'please change the route path to "' + path . replace ( /\*$/ , "/*" ) + '".' ) ) ;
2026-02-04 00:11:19 +05:00
let params = [ ] ;
2026-02-10 13:03:46 +05:00
let regexpSource = "^" + path . replace ( /\/*\*?$/ , "" ) . replace ( /^\/*/ , "/" ) . replace ( /[\\.*+^${}|()[\]]/g , "\\$&" ) . replace ( /\/:([\w-]+)(\?)?/g , ( _ , paramName , isOptional ) => {
params . push ( {
paramName ,
isOptional : isOptional != null
} ) ;
return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)" ;
} ) ;
2026-02-04 00:11:19 +05:00
if ( path . endsWith ( "*" ) ) {
2026-02-10 13:03:46 +05:00
params . push ( {
paramName : "*"
} ) ;
2026-02-04 00:11:19 +05:00
regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$" ;
} else if ( end ) {
regexpSource += "\\/*$" ;
} else if ( path !== "" && path !== "/" ) {
regexpSource += "(?:(?=\\/|$))" ;
2026-02-10 13:03:46 +05:00
} else ;
2026-02-04 00:11:19 +05:00
let matcher = new RegExp ( regexpSource , caseSensitive ? void 0 : "i" ) ;
return [ matcher , params ] ;
}
function decodePath ( value ) {
try {
return value . split ( "/" ) . map ( ( v ) => decodeURIComponent ( v ) . replace ( /\//g , "%2F" ) ) . join ( "/" ) ;
} catch ( error ) {
2026-02-10 13:03:46 +05:00
warning ( false , 'The URL path "' + value + '" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent ' + ( "encoding (" + error + ")." ) ) ;
2026-02-04 00:11:19 +05:00
return value ;
}
}
function stripBasename ( pathname , basename ) {
if ( basename === "/" ) return pathname ;
if ( ! pathname . toLowerCase ( ) . startsWith ( basename . toLowerCase ( ) ) ) {
return null ;
}
let startIndex = basename . endsWith ( "/" ) ? basename . length - 1 : basename . length ;
let nextChar = pathname . charAt ( startIndex ) ;
if ( nextChar && nextChar !== "/" ) {
return null ;
}
return pathname . slice ( startIndex ) || "/" ;
}
2026-02-10 13:03:46 +05:00
var ABSOLUTE _URL _REGEX$1 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i ;
var isAbsoluteUrl = ( url ) => ABSOLUTE _URL _REGEX$1 . test ( url ) ;
function resolvePath ( to , fromPathname ) {
if ( fromPathname === void 0 ) {
fromPathname = "/" ;
}
2026-02-04 00:11:19 +05:00
let {
pathname : toPathname ,
search = "" ,
hash = ""
} = typeof to === "string" ? parsePath ( to ) : to ;
let pathname ;
if ( toPathname ) {
2026-02-10 13:03:46 +05:00
if ( isAbsoluteUrl ( toPathname ) ) {
pathname = toPathname ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
if ( toPathname . includes ( "//" ) ) {
let oldPathname = toPathname ;
toPathname = toPathname . replace ( /\/\/+/g , "/" ) ;
warning ( false , "Pathnames cannot have embedded double slashes - normalizing " + ( oldPathname + " -> " + toPathname ) ) ;
}
if ( toPathname . startsWith ( "/" ) ) {
pathname = resolvePathname ( toPathname . substring ( 1 ) , "/" ) ;
} else {
pathname = resolvePathname ( toPathname , fromPathname ) ;
}
2026-02-04 00:11:19 +05:00
}
} else {
pathname = fromPathname ;
}
return {
pathname ,
search : normalizeSearch ( search ) ,
hash : normalizeHash ( hash )
} ;
}
function resolvePathname ( relativePath , fromPathname ) {
let segments = fromPathname . replace ( /\/+$/ , "" ) . split ( "/" ) ;
let relativeSegments = relativePath . split ( "/" ) ;
relativeSegments . forEach ( ( segment ) => {
if ( segment === ".." ) {
if ( segments . length > 1 ) segments . pop ( ) ;
} else if ( segment !== "." ) {
segments . push ( segment ) ;
}
} ) ;
return segments . length > 1 ? segments . join ( "/" ) : "/" ;
}
function getInvalidPathError ( char , field , dest , path ) {
2026-02-10 13:03:46 +05:00
return "Cannot include a '" + char + "' character in a manually specified " + ( "`to." + field + "` field [" + JSON . stringify ( path ) + "]. Please separate it out to the " ) + ( "`to." + dest + "` field. Alternatively you may provide the full path as " ) + 'a string in <Link to="..."> and the router will parse it for you.' ;
2026-02-04 00:11:19 +05:00
}
function getPathContributingMatches ( matches ) {
2026-02-10 13:03:46 +05:00
return matches . filter ( ( match , index ) => index === 0 || match . route . path && match . route . path . length > 0 ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function getResolveToMatches ( matches , v7 _relativeSplatPath ) {
2026-02-04 00:11:19 +05:00
let pathMatches = getPathContributingMatches ( matches ) ;
2026-02-10 13:03:46 +05:00
if ( v7 _relativeSplatPath ) {
return pathMatches . map ( ( match , idx ) => idx === pathMatches . length - 1 ? match . pathname : match . pathnameBase ) ;
}
return pathMatches . map ( ( match ) => match . pathnameBase ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function resolveTo ( toArg , routePathnames , locationPathname , isPathRelative ) {
if ( isPathRelative === void 0 ) {
isPathRelative = false ;
}
2026-02-04 00:11:19 +05:00
let to ;
if ( typeof toArg === "string" ) {
to = parsePath ( toArg ) ;
} else {
2026-02-10 13:03:46 +05:00
to = _extends ( { } , toArg ) ;
invariant ( ! to . pathname || ! to . pathname . includes ( "?" ) , getInvalidPathError ( "?" , "pathname" , "search" , to ) ) ;
invariant ( ! to . pathname || ! to . pathname . includes ( "#" ) , getInvalidPathError ( "#" , "pathname" , "hash" , to ) ) ;
invariant ( ! to . search || ! to . search . includes ( "#" ) , getInvalidPathError ( "#" , "search" , "hash" , to ) ) ;
2026-02-04 00:11:19 +05:00
}
let isEmptyPath = toArg === "" || to . pathname === "" ;
let toPathname = isEmptyPath ? "/" : to . pathname ;
let from ;
if ( toPathname == null ) {
from = locationPathname ;
} else {
let routePathnameIndex = routePathnames . length - 1 ;
if ( ! isPathRelative && toPathname . startsWith ( ".." ) ) {
let toSegments = toPathname . split ( "/" ) ;
while ( toSegments [ 0 ] === ".." ) {
toSegments . shift ( ) ;
routePathnameIndex -= 1 ;
}
to . pathname = toSegments . join ( "/" ) ;
}
from = routePathnameIndex >= 0 ? routePathnames [ routePathnameIndex ] : "/" ;
}
let path = resolvePath ( to , from ) ;
let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname . endsWith ( "/" ) ;
let hasCurrentTrailingSlash = ( isEmptyPath || toPathname === "." ) && locationPathname . endsWith ( "/" ) ;
if ( ! path . pathname . endsWith ( "/" ) && ( hasExplicitTrailingSlash || hasCurrentTrailingSlash ) ) {
path . pathname += "/" ;
}
return path ;
}
var joinPaths = ( paths ) => paths . join ( "/" ) . replace ( /\/\/+/g , "/" ) ;
var normalizePathname = ( pathname ) => pathname . replace ( /\/+$/ , "" ) . replace ( /^\/*/ , "/" ) ;
var normalizeSearch = ( search ) => ! search || search === "?" ? "" : search . startsWith ( "?" ) ? search : "?" + search ;
var normalizeHash = ( hash ) => ! hash || hash === "#" ? "" : hash . startsWith ( "#" ) ? hash : "#" + hash ;
2026-02-10 13:03:46 +05:00
var json = function json2 ( data , init ) {
if ( init === void 0 ) {
init = { } ;
}
let responseInit = typeof init === "number" ? {
status : init
} : init ;
let headers = new Headers ( responseInit . headers ) ;
if ( ! headers . has ( "Content-Type" ) ) {
headers . set ( "Content-Type" , "application/json; charset=utf-8" ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return new Response ( JSON . stringify ( data ) , _extends ( { } , responseInit , {
headers
} ) ) ;
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
var AbortedDeferredError = class extends Error {
} ;
var DeferredData = class {
constructor ( data , responseInit ) {
this . pendingKeysSet = /* @__PURE__ */ new Set ( ) ;
this . subscribers = /* @__PURE__ */ new Set ( ) ;
this . deferredKeys = [ ] ;
invariant ( data && typeof data === "object" && ! Array . isArray ( data ) , "defer() only accepts plain objects" ) ;
let reject ;
this . abortPromise = new Promise ( ( _ , r ) => reject = r ) ;
this . controller = new AbortController ( ) ;
let onAbort = ( ) => reject ( new AbortedDeferredError ( "Deferred data aborted" ) ) ;
this . unlistenAbortSignal = ( ) => this . controller . signal . removeEventListener ( "abort" , onAbort ) ;
this . controller . signal . addEventListener ( "abort" , onAbort ) ;
this . data = Object . entries ( data ) . reduce ( ( acc , _ref2 ) => {
let [ key , value ] = _ref2 ;
return Object . assign ( acc , {
[ key ] : this . trackPromise ( key , value )
} ) ;
} , { } ) ;
if ( this . done ) {
this . unlistenAbortSignal ( ) ;
}
this . init = responseInit ;
}
trackPromise ( key , value ) {
if ( ! ( value instanceof Promise ) ) {
return value ;
}
this . deferredKeys . push ( key ) ;
this . pendingKeysSet . add ( key ) ;
let promise = Promise . race ( [ value , this . abortPromise ] ) . then ( ( data ) => this . onSettle ( promise , key , void 0 , data ) , ( error ) => this . onSettle ( promise , key , error ) ) ;
promise . catch ( ( ) => {
} ) ;
Object . defineProperty ( promise , "_tracked" , {
get : ( ) => true
} ) ;
return promise ;
}
onSettle ( promise , key , error , data ) {
if ( this . controller . signal . aborted && error instanceof AbortedDeferredError ) {
this . unlistenAbortSignal ( ) ;
Object . defineProperty ( promise , "_error" , {
get : ( ) => error
} ) ;
return Promise . reject ( error ) ;
}
this . pendingKeysSet . delete ( key ) ;
if ( this . done ) {
this . unlistenAbortSignal ( ) ;
}
if ( error === void 0 && data === void 0 ) {
let undefinedError = new Error ( 'Deferred data for key "' + key + '" resolved/rejected with `undefined`, you must resolve/reject with a value or `null`.' ) ;
Object . defineProperty ( promise , "_error" , {
get : ( ) => undefinedError
} ) ;
this . emit ( false , key ) ;
return Promise . reject ( undefinedError ) ;
}
if ( data === void 0 ) {
Object . defineProperty ( promise , "_error" , {
get : ( ) => error
} ) ;
this . emit ( false , key ) ;
return Promise . reject ( error ) ;
}
Object . defineProperty ( promise , "_data" , {
get : ( ) => data
} ) ;
this . emit ( false , key ) ;
return data ;
}
emit ( aborted , settledKey ) {
this . subscribers . forEach ( ( subscriber ) => subscriber ( aborted , settledKey ) ) ;
}
subscribe ( fn ) {
this . subscribers . add ( fn ) ;
return ( ) => this . subscribers . delete ( fn ) ;
}
cancel ( ) {
this . controller . abort ( ) ;
this . pendingKeysSet . forEach ( ( v , k ) => this . pendingKeysSet . delete ( k ) ) ;
this . emit ( true ) ;
}
async resolveData ( signal ) {
let aborted = false ;
if ( ! this . done ) {
let onAbort = ( ) => this . cancel ( ) ;
signal . addEventListener ( "abort" , onAbort ) ;
aborted = await new Promise ( ( resolve ) => {
this . subscribe ( ( aborted2 ) => {
signal . removeEventListener ( "abort" , onAbort ) ;
if ( aborted2 || this . done ) {
resolve ( aborted2 ) ;
}
} ) ;
} ) ;
}
return aborted ;
}
get done ( ) {
return this . pendingKeysSet . size === 0 ;
}
get unwrappedData ( ) {
invariant ( this . data !== null && this . done , "Can only unwrap data on initialized and settled deferreds" ) ;
return Object . entries ( this . data ) . reduce ( ( acc , _ref3 ) => {
let [ key , value ] = _ref3 ;
return Object . assign ( acc , {
[ key ] : unwrapTrackedPromise ( value )
} ) ;
} , { } ) ;
}
get pendingKeys ( ) {
return Array . from ( this . pendingKeysSet ) ;
}
} ;
function isTrackedPromise ( value ) {
return value instanceof Promise && value . _tracked === true ;
}
function unwrapTrackedPromise ( value ) {
if ( ! isTrackedPromise ( value ) ) {
return value ;
}
if ( value . _error ) {
throw value . _error ;
}
return value . _data ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var defer = function defer2 ( data , init ) {
if ( init === void 0 ) {
init = { } ;
}
let responseInit = typeof init === "number" ? {
status : init
} : init ;
return new DeferredData ( data , responseInit ) ;
} ;
var redirect = function redirect2 ( url , init ) {
if ( init === void 0 ) {
init = 302 ;
}
2026-02-04 00:11:19 +05:00
let responseInit = init ;
if ( typeof responseInit === "number" ) {
2026-02-10 13:03:46 +05:00
responseInit = {
status : responseInit
} ;
2026-02-04 00:11:19 +05:00
} else if ( typeof responseInit . status === "undefined" ) {
responseInit . status = 302 ;
}
let headers = new Headers ( responseInit . headers ) ;
headers . set ( "Location" , url ) ;
2026-02-10 13:03:46 +05:00
return new Response ( null , _extends ( { } , responseInit , {
headers
} ) ) ;
2026-02-04 00:11:19 +05:00
} ;
var redirectDocument = ( url , init ) => {
let response = redirect ( url , init ) ;
response . headers . set ( "X-Remix-Reload-Document" , "true" ) ;
return response ;
} ;
var replace = ( url , init ) => {
let response = redirect ( url , init ) ;
response . headers . set ( "X-Remix-Replace" , "true" ) ;
return response ;
} ;
var ErrorResponseImpl = class {
2026-02-10 13:03:46 +05:00
constructor ( status , statusText , data , internal ) {
if ( internal === void 0 ) {
internal = false ;
}
2026-02-04 00:11:19 +05:00
this . status = status ;
this . statusText = statusText || "" ;
this . internal = internal ;
2026-02-10 13:03:46 +05:00
if ( data instanceof Error ) {
this . data = data . toString ( ) ;
this . error = data ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
this . data = data ;
2026-02-04 00:11:19 +05:00
}
}
} ;
function isRouteErrorResponse ( error ) {
return error != null && typeof error . status === "number" && typeof error . statusText === "string" && typeof error . internal === "boolean" && "data" in error ;
}
2026-02-10 13:03:46 +05:00
var validMutationMethodsArr = [ "post" , "put" , "patch" , "delete" ] ;
var validMutationMethods = new Set ( validMutationMethodsArr ) ;
var validRequestMethodsArr = [ "get" , ... validMutationMethodsArr ] ;
2026-02-04 00:11:19 +05:00
var validRequestMethods = new Set ( validRequestMethodsArr ) ;
var redirectStatusCodes = /* @__PURE__ */ new Set ( [ 301 , 302 , 303 , 307 , 308 ] ) ;
var redirectPreserveMethodStatusCodes = /* @__PURE__ */ new Set ( [ 307 , 308 ] ) ;
var IDLE _NAVIGATION = {
state : "idle" ,
location : void 0 ,
formMethod : void 0 ,
formAction : void 0 ,
formEncType : void 0 ,
formData : void 0 ,
json : void 0 ,
text : void 0
} ;
var IDLE _FETCHER = {
state : "idle" ,
data : void 0 ,
formMethod : void 0 ,
formAction : void 0 ,
formEncType : void 0 ,
formData : void 0 ,
json : void 0 ,
text : void 0
} ;
var IDLE _BLOCKER = {
state : "unblocked" ,
proceed : void 0 ,
reset : void 0 ,
location : void 0
} ;
2026-02-10 13:03:46 +05:00
var ABSOLUTE _URL _REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i ;
2026-02-04 00:11:19 +05:00
var defaultMapRouteProperties = ( route ) => ( {
hasErrorBoundary : Boolean ( route . hasErrorBoundary )
} ) ;
var TRANSITIONS _STORAGE _KEY = "remix-router-transitions" ;
function createRouter ( init ) {
const routerWindow = init . window ? init . window : typeof window !== "undefined" ? window : void 0 ;
2026-02-10 13:03:46 +05:00
const isBrowser2 = typeof routerWindow !== "undefined" && typeof routerWindow . document !== "undefined" && typeof routerWindow . document . createElement !== "undefined" ;
const isServer = ! isBrowser2 ;
invariant ( init . routes . length > 0 , "You must provide a non-empty routes array to createRouter" ) ;
let mapRouteProperties2 ;
if ( init . mapRouteProperties ) {
mapRouteProperties2 = init . mapRouteProperties ;
} else if ( init . detectErrorBoundary ) {
let detectErrorBoundary = init . detectErrorBoundary ;
mapRouteProperties2 = ( route ) => ( {
hasErrorBoundary : detectErrorBoundary ( route )
} ) ;
} else {
mapRouteProperties2 = defaultMapRouteProperties ;
2026-02-04 00:11:19 +05:00
}
let manifest = { } ;
2026-02-10 13:03:46 +05:00
let dataRoutes = convertRoutesToDataRoutes ( init . routes , mapRouteProperties2 , void 0 , manifest ) ;
2026-02-04 00:11:19 +05:00
let inFlightDataRoutes ;
let basename = init . basename || "/" ;
2026-02-10 13:03:46 +05:00
let dataStrategyImpl = init . dataStrategy || defaultDataStrategy ;
let patchRoutesOnNavigationImpl = init . patchRoutesOnNavigation ;
let future = _extends ( {
v7 _fetcherPersist : false ,
v7 _normalizeFormMethod : false ,
v7 _partialHydration : false ,
v7 _prependBasename : false ,
v7 _relativeSplatPath : false ,
v7 _skipActionErrorRevalidation : false
} , init . future ) ;
2026-02-04 00:11:19 +05:00
let unlistenHistory = null ;
let subscribers = /* @__PURE__ */ new Set ( ) ;
let savedScrollPositions2 = null ;
2026-02-10 13:03:46 +05:00
let getScrollRestorationKey = null ;
2026-02-04 00:11:19 +05:00
let getScrollPosition = null ;
let initialScrollRestored = init . hydrationData != null ;
let initialMatches = matchRoutes ( dataRoutes , init . history . location , basename ) ;
let initialMatchesIsFOW = false ;
let initialErrors = null ;
2026-02-10 13:03:46 +05:00
if ( initialMatches == null && ! patchRoutesOnNavigationImpl ) {
2026-02-04 00:11:19 +05:00
let error = getInternalRouterError ( 404 , {
pathname : init . history . location . pathname
} ) ;
2026-02-10 13:03:46 +05:00
let {
matches ,
route
} = getShortCircuitMatches ( dataRoutes ) ;
2026-02-04 00:11:19 +05:00
initialMatches = matches ;
2026-02-10 13:03:46 +05:00
initialErrors = {
[ route . id ] : error
} ;
}
if ( initialMatches && ! init . hydrationData ) {
let fogOfWar = checkFogOfWar ( initialMatches , dataRoutes , init . history . location . pathname ) ;
if ( fogOfWar . active ) {
initialMatches = null ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
}
let initialized ;
if ( ! initialMatches ) {
initialized = false ;
initialMatches = [ ] ;
if ( future . v7 _partialHydration ) {
let fogOfWar = checkFogOfWar ( null , dataRoutes , init . history . location . pathname ) ;
2026-02-04 00:11:19 +05:00
if ( fogOfWar . active && fogOfWar . matches ) {
initialMatchesIsFOW = true ;
initialMatches = fogOfWar . matches ;
}
2026-02-10 13:03:46 +05:00
}
} else if ( initialMatches . some ( ( m ) => m . route . lazy ) ) {
initialized = false ;
} else if ( ! initialMatches . some ( ( m ) => m . route . loader ) ) {
initialized = true ;
} else if ( future . v7 _partialHydration ) {
let loaderData = init . hydrationData ? init . hydrationData . loaderData : null ;
let errors = init . hydrationData ? init . hydrationData . errors : null ;
if ( errors ) {
let idx = initialMatches . findIndex ( ( m ) => errors [ m . route . id ] !== void 0 ) ;
initialized = initialMatches . slice ( 0 , idx + 1 ) . every ( ( m ) => ! shouldLoadRouteOnHydration ( m . route , loaderData , errors ) ) ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
initialized = initialMatches . every ( ( m ) => ! shouldLoadRouteOnHydration ( m . route , loaderData , errors ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} else {
initialized = init . hydrationData != null ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let router ;
2026-02-04 00:11:19 +05:00
let state = {
historyAction : init . history . action ,
location : init . history . location ,
matches : initialMatches ,
initialized ,
navigation : IDLE _NAVIGATION ,
// Don't restore on initial updateState() if we were SSR'd
restoreScrollPosition : init . hydrationData != null ? false : null ,
preventScrollReset : false ,
revalidation : "idle" ,
loaderData : init . hydrationData && init . hydrationData . loaderData || { } ,
actionData : init . hydrationData && init . hydrationData . actionData || null ,
errors : init . hydrationData && init . hydrationData . errors || initialErrors ,
fetchers : /* @__PURE__ */ new Map ( ) ,
blockers : /* @__PURE__ */ new Map ( )
} ;
2026-02-10 13:03:46 +05:00
let pendingAction = Action . Pop ;
2026-02-04 00:11:19 +05:00
let pendingPreventScrollReset = false ;
let pendingNavigationController ;
let pendingViewTransitionEnabled = false ;
let appliedViewTransitions = /* @__PURE__ */ new Map ( ) ;
let removePageHideEventListener = null ;
let isUninterruptedRevalidation = false ;
let isRevalidationRequired = false ;
2026-02-10 13:03:46 +05:00
let cancelledDeferredRoutes = [ ] ;
2026-02-04 00:11:19 +05:00
let cancelledFetcherLoads = /* @__PURE__ */ new Set ( ) ;
let fetchControllers = /* @__PURE__ */ new Map ( ) ;
let incrementingLoadId = 0 ;
let pendingNavigationLoadId = - 1 ;
let fetchReloadIds = /* @__PURE__ */ new Map ( ) ;
let fetchRedirectIds = /* @__PURE__ */ new Set ( ) ;
let fetchLoadMatches = /* @__PURE__ */ new Map ( ) ;
let activeFetchers = /* @__PURE__ */ new Map ( ) ;
2026-02-10 13:03:46 +05:00
let deletedFetchers = /* @__PURE__ */ new Set ( ) ;
let activeDeferreds = /* @__PURE__ */ new Map ( ) ;
2026-02-04 00:11:19 +05:00
let blockerFunctions = /* @__PURE__ */ new Map ( ) ;
let unblockBlockerHistoryUpdate = void 0 ;
function initialize ( ) {
2026-02-10 13:03:46 +05:00
unlistenHistory = init . history . listen ( ( _ref ) => {
let {
action : historyAction ,
location ,
delta
} = _ref ;
if ( unblockBlockerHistoryUpdate ) {
unblockBlockerHistoryUpdate ( ) ;
unblockBlockerHistoryUpdate = void 0 ;
return ;
}
warning ( blockerFunctions . size === 0 || delta != null , "You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL." ) ;
let blockerKey = shouldBlockNavigation ( {
currentLocation : state . location ,
nextLocation : location ,
historyAction
} ) ;
if ( blockerKey && delta != null ) {
let nextHistoryUpdatePromise = new Promise ( ( resolve ) => {
unblockBlockerHistoryUpdate = resolve ;
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
init . history . go ( delta * - 1 ) ;
updateBlocker ( blockerKey , {
state : "blocked" ,
location ,
proceed ( ) {
updateBlocker ( blockerKey , {
state : "proceeding" ,
proceed : void 0 ,
reset : void 0 ,
location
} ) ;
nextHistoryUpdatePromise . then ( ( ) => init . history . go ( delta ) ) ;
} ,
reset ( ) {
let blockers = new Map ( state . blockers ) ;
blockers . set ( blockerKey , IDLE _BLOCKER ) ;
updateState ( {
blockers
} ) ;
}
} ) ;
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return startNavigation ( historyAction , location ) ;
} ) ;
if ( isBrowser2 ) {
2026-02-04 00:11:19 +05:00
restoreAppliedTransitions ( routerWindow , appliedViewTransitions ) ;
let _saveAppliedTransitions = ( ) => persistAppliedTransitions ( routerWindow , appliedViewTransitions ) ;
routerWindow . addEventListener ( "pagehide" , _saveAppliedTransitions ) ;
removePageHideEventListener = ( ) => routerWindow . removeEventListener ( "pagehide" , _saveAppliedTransitions ) ;
}
if ( ! state . initialized ) {
2026-02-10 13:03:46 +05:00
startNavigation ( Action . Pop , state . location , {
2026-02-04 00:11:19 +05:00
initialHydration : true
} ) ;
}
2026-02-10 13:03:46 +05:00
return router ;
2026-02-04 00:11:19 +05:00
}
function dispose ( ) {
if ( unlistenHistory ) {
unlistenHistory ( ) ;
}
if ( removePageHideEventListener ) {
removePageHideEventListener ( ) ;
}
subscribers . clear ( ) ;
pendingNavigationController && pendingNavigationController . abort ( ) ;
state . fetchers . forEach ( ( _ , key ) => deleteFetcher ( key ) ) ;
state . blockers . forEach ( ( _ , key ) => deleteBlocker ( key ) ) ;
}
function subscribe ( fn ) {
subscribers . add ( fn ) ;
return ( ) => subscribers . delete ( fn ) ;
}
2026-02-10 13:03:46 +05:00
function updateState ( newState , opts ) {
if ( opts === void 0 ) {
opts = { } ;
}
state = _extends ( { } , state , newState ) ;
let completedFetchers = [ ] ;
let deletedFetchersKeys = [ ] ;
if ( future . v7 _fetcherPersist ) {
state . fetchers . forEach ( ( fetcher , key ) => {
if ( fetcher . state === "idle" ) {
if ( deletedFetchers . has ( key ) ) {
deletedFetchersKeys . push ( key ) ;
} else {
completedFetchers . push ( key ) ;
}
2026-02-04 00:11:19 +05:00
}
} ) ;
}
2026-02-10 13:03:46 +05:00
deletedFetchers . forEach ( ( key ) => {
2026-02-04 00:11:19 +05:00
if ( ! state . fetchers . has ( key ) && ! fetchControllers . has ( key ) ) {
2026-02-10 13:03:46 +05:00
deletedFetchersKeys . push ( key ) ;
2026-02-04 00:11:19 +05:00
}
} ) ;
2026-02-10 13:03:46 +05:00
[ ... subscribers ] . forEach ( ( subscriber ) => subscriber ( state , {
deletedFetchers : deletedFetchersKeys ,
viewTransitionOpts : opts . viewTransitionOpts ,
flushSync : opts . flushSync === true
} ) ) ;
if ( future . v7 _fetcherPersist ) {
completedFetchers . forEach ( ( key ) => state . fetchers . delete ( key ) ) ;
deletedFetchersKeys . forEach ( ( key ) => deleteFetcher ( key ) ) ;
} else {
deletedFetchersKeys . forEach ( ( key ) => deletedFetchers . delete ( key ) ) ;
}
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function completeNavigation ( location , newState , _temp ) {
var _location$state , _location$state2 ;
let {
flushSync
} = _temp === void 0 ? { } : _temp ;
let isActionReload = state . actionData != null && state . navigation . formMethod != null && isMutationMethod ( state . navigation . formMethod ) && state . navigation . state === "loading" && ( ( _location$state = location . state ) == null ? void 0 : _location$state . _isRedirect ) !== true ;
2026-02-04 00:11:19 +05:00
let actionData ;
if ( newState . actionData ) {
if ( Object . keys ( newState . actionData ) . length > 0 ) {
actionData = newState . actionData ;
} else {
actionData = null ;
}
} else if ( isActionReload ) {
actionData = state . actionData ;
} else {
actionData = null ;
}
2026-02-10 13:03:46 +05:00
let loaderData = newState . loaderData ? mergeLoaderData ( state . loaderData , newState . loaderData , newState . matches || [ ] , newState . errors ) : state . loaderData ;
2026-02-04 00:11:19 +05:00
let blockers = state . blockers ;
if ( blockers . size > 0 ) {
blockers = new Map ( blockers ) ;
blockers . forEach ( ( _ , k ) => blockers . set ( k , IDLE _BLOCKER ) ) ;
}
2026-02-10 13:03:46 +05:00
let preventScrollReset = pendingPreventScrollReset === true || state . navigation . formMethod != null && isMutationMethod ( state . navigation . formMethod ) && ( ( _location$state2 = location . state ) == null ? void 0 : _location$state2 . _isRedirect ) !== true ;
2026-02-04 00:11:19 +05:00
if ( inFlightDataRoutes ) {
dataRoutes = inFlightDataRoutes ;
inFlightDataRoutes = void 0 ;
}
2026-02-10 13:03:46 +05:00
if ( isUninterruptedRevalidation ) ;
else if ( pendingAction === Action . Pop ) ;
else if ( pendingAction === Action . Push ) {
init . history . push ( location , location . state ) ;
} else if ( pendingAction === Action . Replace ) {
init . history . replace ( location , location . state ) ;
2026-02-04 00:11:19 +05:00
}
let viewTransitionOpts ;
2026-02-10 13:03:46 +05:00
if ( pendingAction === Action . Pop ) {
2026-02-04 00:11:19 +05:00
let priorPaths = appliedViewTransitions . get ( state . location . pathname ) ;
2026-02-10 13:03:46 +05:00
if ( priorPaths && priorPaths . has ( location . pathname ) ) {
2026-02-04 00:11:19 +05:00
viewTransitionOpts = {
currentLocation : state . location ,
2026-02-10 13:03:46 +05:00
nextLocation : location
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
} else if ( appliedViewTransitions . has ( location . pathname ) ) {
2026-02-04 00:11:19 +05:00
viewTransitionOpts = {
2026-02-10 13:03:46 +05:00
currentLocation : location ,
2026-02-04 00:11:19 +05:00
nextLocation : state . location
} ;
}
} else if ( pendingViewTransitionEnabled ) {
let toPaths = appliedViewTransitions . get ( state . location . pathname ) ;
if ( toPaths ) {
2026-02-10 13:03:46 +05:00
toPaths . add ( location . pathname ) ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
toPaths = /* @__PURE__ */ new Set ( [ location . pathname ] ) ;
2026-02-04 00:11:19 +05:00
appliedViewTransitions . set ( state . location . pathname , toPaths ) ;
}
viewTransitionOpts = {
currentLocation : state . location ,
2026-02-10 13:03:46 +05:00
nextLocation : location
2026-02-04 00:11:19 +05:00
} ;
}
2026-02-10 13:03:46 +05:00
updateState ( _extends ( { } , newState , {
actionData ,
loaderData ,
historyAction : pendingAction ,
location ,
initialized : true ,
navigation : IDLE _NAVIGATION ,
revalidation : "idle" ,
restoreScrollPosition : getSavedScrollPosition ( location , newState . matches || state . matches ) ,
preventScrollReset ,
blockers
} ) , {
viewTransitionOpts ,
flushSync : flushSync === true
} ) ;
pendingAction = Action . Pop ;
2026-02-04 00:11:19 +05:00
pendingPreventScrollReset = false ;
pendingViewTransitionEnabled = false ;
isUninterruptedRevalidation = false ;
isRevalidationRequired = false ;
2026-02-10 13:03:46 +05:00
cancelledDeferredRoutes = [ ] ;
2026-02-04 00:11:19 +05:00
}
async function navigate ( to , opts ) {
if ( typeof to === "number" ) {
init . history . go ( to ) ;
2026-02-10 13:03:46 +05:00
return ;
}
let normalizedPath = normalizeTo ( state . location , state . matches , basename , future . v7 _prependBasename , to , future . v7 _relativeSplatPath , opts == null ? void 0 : opts . fromRouteId , opts == null ? void 0 : opts . relative ) ;
let {
path ,
submission ,
error
} = normalizeNavigateOptions ( future . v7 _normalizeFormMethod , false , normalizedPath , opts ) ;
2026-02-04 00:11:19 +05:00
let currentLocation = state . location ;
let nextLocation = createLocation ( state . location , path , opts && opts . state ) ;
2026-02-10 13:03:46 +05:00
nextLocation = _extends ( { } , nextLocation , init . history . encodeLocation ( nextLocation ) ) ;
2026-02-04 00:11:19 +05:00
let userReplace = opts && opts . replace != null ? opts . replace : void 0 ;
2026-02-10 13:03:46 +05:00
let historyAction = Action . Push ;
2026-02-04 00:11:19 +05:00
if ( userReplace === true ) {
2026-02-10 13:03:46 +05:00
historyAction = Action . Replace ;
} else if ( userReplace === false ) ;
else if ( submission != null && isMutationMethod ( submission . formMethod ) && submission . formAction === state . location . pathname + state . location . search ) {
historyAction = Action . Replace ;
2026-02-04 00:11:19 +05:00
}
let preventScrollReset = opts && "preventScrollReset" in opts ? opts . preventScrollReset === true : void 0 ;
2026-02-10 13:03:46 +05:00
let flushSync = ( opts && opts . flushSync ) === true ;
2026-02-04 00:11:19 +05:00
let blockerKey = shouldBlockNavigation ( {
currentLocation ,
nextLocation ,
historyAction
} ) ;
if ( blockerKey ) {
updateBlocker ( blockerKey , {
state : "blocked" ,
location : nextLocation ,
proceed ( ) {
updateBlocker ( blockerKey , {
state : "proceeding" ,
proceed : void 0 ,
reset : void 0 ,
location : nextLocation
} ) ;
navigate ( to , opts ) ;
} ,
reset ( ) {
let blockers = new Map ( state . blockers ) ;
blockers . set ( blockerKey , IDLE _BLOCKER ) ;
2026-02-10 13:03:46 +05:00
updateState ( {
blockers
} ) ;
2026-02-04 00:11:19 +05:00
}
} ) ;
return ;
}
2026-02-10 13:03:46 +05:00
return await startNavigation ( historyAction , nextLocation , {
2026-02-04 00:11:19 +05:00
submission ,
// Send through the formData serialization error if we have one so we can
// render at the right error boundary after we match routes
pendingError : error ,
preventScrollReset ,
replace : opts && opts . replace ,
enableViewTransition : opts && opts . viewTransition ,
2026-02-10 13:03:46 +05:00
flushSync
2026-02-04 00:11:19 +05:00
} ) ;
}
function revalidate ( ) {
interruptActiveLoads ( ) ;
2026-02-10 13:03:46 +05:00
updateState ( {
revalidation : "loading"
} ) ;
2026-02-04 00:11:19 +05:00
if ( state . navigation . state === "submitting" ) {
2026-02-10 13:03:46 +05:00
return ;
2026-02-04 00:11:19 +05:00
}
if ( state . navigation . state === "idle" ) {
startNavigation ( state . historyAction , state . location , {
startUninterruptedRevalidation : true
} ) ;
2026-02-10 13:03:46 +05:00
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
startNavigation ( pendingAction || state . historyAction , state . navigation . location , {
overrideNavigation : state . navigation ,
// Proxy through any rending view transition
enableViewTransition : pendingViewTransitionEnabled === true
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function startNavigation ( historyAction , location , opts ) {
2026-02-04 00:11:19 +05:00
pendingNavigationController && pendingNavigationController . abort ( ) ;
pendingNavigationController = null ;
pendingAction = historyAction ;
isUninterruptedRevalidation = ( opts && opts . startUninterruptedRevalidation ) === true ;
saveScrollPosition ( state . location , state . matches ) ;
pendingPreventScrollReset = ( opts && opts . preventScrollReset ) === true ;
pendingViewTransitionEnabled = ( opts && opts . enableViewTransition ) === true ;
let routesToUse = inFlightDataRoutes || dataRoutes ;
let loadingNavigation = opts && opts . overrideNavigation ;
2026-02-10 13:03:46 +05:00
let matches = opts != null && opts . initialHydration && state . matches && state . matches . length > 0 && ! initialMatchesIsFOW ? (
2026-02-04 00:11:19 +05:00
// `matchRoutes()` has already been called if we're in here via `router.initialize()`
state . matches
2026-02-10 13:03:46 +05:00
) : matchRoutes ( routesToUse , location , basename ) ;
let flushSync = ( opts && opts . flushSync ) === true ;
if ( matches && state . initialized && ! isRevalidationRequired && isHashChangeOnly ( state . location , location ) && ! ( opts && opts . submission && isMutationMethod ( opts . submission . formMethod ) ) ) {
completeNavigation ( location , {
matches
} , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
let fogOfWar = checkFogOfWar ( matches , routesToUse , location . pathname ) ;
2026-02-04 00:11:19 +05:00
if ( fogOfWar . active && fogOfWar . matches ) {
matches = fogOfWar . matches ;
}
if ( ! matches ) {
2026-02-10 13:03:46 +05:00
let {
error ,
notFoundMatches ,
route
} = handleNavigational404 ( location . pathname ) ;
completeNavigation ( location , {
matches : notFoundMatches ,
loaderData : { } ,
errors : {
[ route . id ] : error
}
} , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
}
pendingNavigationController = new AbortController ( ) ;
2026-02-10 13:03:46 +05:00
let request = createClientSideRequest ( init . history , location , pendingNavigationController . signal , opts && opts . submission ) ;
2026-02-04 00:11:19 +05:00
let pendingActionResult ;
if ( opts && opts . pendingError ) {
2026-02-10 13:03:46 +05:00
pendingActionResult = [ findNearestBoundary ( matches ) . route . id , {
type : ResultType . error ,
error : opts . pendingError
} ] ;
2026-02-04 00:11:19 +05:00
} else if ( opts && opts . submission && isMutationMethod ( opts . submission . formMethod ) ) {
2026-02-10 13:03:46 +05:00
let actionResult = await handleAction ( request , location , opts . submission , matches , fogOfWar . active , {
replace : opts . replace ,
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
if ( actionResult . shortCircuited ) {
return ;
}
if ( actionResult . pendingActionResult ) {
let [ routeId , result ] = actionResult . pendingActionResult ;
if ( isErrorResult ( result ) && isRouteErrorResponse ( result . error ) && result . error . status === 404 ) {
pendingNavigationController = null ;
2026-02-10 13:03:46 +05:00
completeNavigation ( location , {
2026-02-04 00:11:19 +05:00
matches : actionResult . matches ,
loaderData : { } ,
errors : {
[ routeId ] : result . error
}
} ) ;
return ;
}
}
matches = actionResult . matches || matches ;
pendingActionResult = actionResult . pendingActionResult ;
2026-02-10 13:03:46 +05:00
loadingNavigation = getLoadingNavigation ( location , opts . submission ) ;
flushSync = false ;
2026-02-04 00:11:19 +05:00
fogOfWar . active = false ;
2026-02-10 13:03:46 +05:00
request = createClientSideRequest ( init . history , request . url , request . signal ) ;
2026-02-04 00:11:19 +05:00
}
let {
shortCircuited ,
matches : updatedMatches ,
loaderData ,
errors
2026-02-10 13:03:46 +05:00
} = await handleLoaders ( request , location , matches , fogOfWar . active , loadingNavigation , opts && opts . submission , opts && opts . fetcherSubmission , opts && opts . replace , opts && opts . initialHydration === true , flushSync , pendingActionResult ) ;
2026-02-04 00:11:19 +05:00
if ( shortCircuited ) {
return ;
}
pendingNavigationController = null ;
2026-02-10 13:03:46 +05:00
completeNavigation ( location , _extends ( {
matches : updatedMatches || matches
} , getActionDataForCommit ( pendingActionResult ) , {
2026-02-04 00:11:19 +05:00
loaderData ,
errors
2026-02-10 13:03:46 +05:00
} ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function handleAction ( request , location , submission , matches , isFogOfWar , opts ) {
if ( opts === void 0 ) {
opts = { } ;
}
2026-02-04 00:11:19 +05:00
interruptActiveLoads ( ) ;
2026-02-10 13:03:46 +05:00
let navigation = getSubmittingNavigation ( location , submission ) ;
updateState ( {
navigation
} , {
flushSync : opts . flushSync === true
} ) ;
2026-02-04 00:11:19 +05:00
if ( isFogOfWar ) {
2026-02-10 13:03:46 +05:00
let discoverResult = await discoverRoutes ( matches , location . pathname , request . signal ) ;
2026-02-04 00:11:19 +05:00
if ( discoverResult . type === "aborted" ) {
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
} else if ( discoverResult . type === "error" ) {
let boundaryId = findNearestBoundary ( discoverResult . partialMatches ) . route . id ;
return {
matches : discoverResult . partialMatches ,
2026-02-10 13:03:46 +05:00
pendingActionResult : [ boundaryId , {
type : ResultType . error ,
error : discoverResult . error
} ]
2026-02-04 00:11:19 +05:00
} ;
} else if ( ! discoverResult . matches ) {
2026-02-10 13:03:46 +05:00
let {
notFoundMatches ,
error ,
route
} = handleNavigational404 ( location . pathname ) ;
2026-02-04 00:11:19 +05:00
return {
matches : notFoundMatches ,
2026-02-10 13:03:46 +05:00
pendingActionResult : [ route . id , {
type : ResultType . error ,
error
} ]
2026-02-04 00:11:19 +05:00
} ;
} else {
matches = discoverResult . matches ;
}
}
let result ;
2026-02-10 13:03:46 +05:00
let actionMatch = getTargetMatch ( matches , location ) ;
2026-02-04 00:11:19 +05:00
if ( ! actionMatch . route . action && ! actionMatch . route . lazy ) {
result = {
2026-02-10 13:03:46 +05:00
type : ResultType . error ,
2026-02-04 00:11:19 +05:00
error : getInternalRouterError ( 405 , {
method : request . method ,
2026-02-10 13:03:46 +05:00
pathname : location . pathname ,
2026-02-04 00:11:19 +05:00
routeId : actionMatch . route . id
} )
} ;
} else {
2026-02-10 13:03:46 +05:00
let results = await callDataStrategy ( "action" , state , request , [ actionMatch ] , matches , null ) ;
2026-02-04 00:11:19 +05:00
result = results [ actionMatch . route . id ] ;
if ( request . signal . aborted ) {
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
}
}
if ( isRedirectResult ( result ) ) {
let replace2 ;
if ( opts && opts . replace != null ) {
replace2 = opts . replace ;
} else {
2026-02-10 13:03:46 +05:00
let location2 = normalizeRedirectLocation ( result . response . headers . get ( "Location" ) , new URL ( request . url ) , basename , init . history ) ;
replace2 = location2 === state . location . pathname + state . location . search ;
2026-02-04 00:11:19 +05:00
}
await startRedirectNavigation ( request , result , true , {
submission ,
replace : replace2
} ) ;
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
}
if ( isDeferredResult ( result ) ) {
throw getInternalRouterError ( 400 , {
type : "defer-action"
} ) ;
}
2026-02-04 00:11:19 +05:00
if ( isErrorResult ( result ) ) {
let boundaryMatch = findNearestBoundary ( matches , actionMatch . route . id ) ;
if ( ( opts && opts . replace ) !== true ) {
2026-02-10 13:03:46 +05:00
pendingAction = Action . Push ;
2026-02-04 00:11:19 +05:00
}
return {
matches ,
2026-02-10 13:03:46 +05:00
pendingActionResult : [ boundaryMatch . route . id , result ]
2026-02-04 00:11:19 +05:00
} ;
}
return {
matches ,
pendingActionResult : [ actionMatch . route . id , result ]
} ;
}
2026-02-10 13:03:46 +05:00
async function handleLoaders ( request , location , matches , isFogOfWar , overrideNavigation , submission , fetcherSubmission , replace2 , initialHydration , flushSync , pendingActionResult ) {
let loadingNavigation = overrideNavigation || getLoadingNavigation ( location , submission ) ;
2026-02-04 00:11:19 +05:00
let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation ( loadingNavigation ) ;
2026-02-10 13:03:46 +05:00
let shouldUpdateNavigationState = ! isUninterruptedRevalidation && ( ! future . v7 _partialHydration || ! initialHydration ) ;
2026-02-04 00:11:19 +05:00
if ( isFogOfWar ) {
if ( shouldUpdateNavigationState ) {
let actionData = getUpdatedActionData ( pendingActionResult ) ;
2026-02-10 13:03:46 +05:00
updateState ( _extends ( {
navigation : loadingNavigation
} , actionData !== void 0 ? {
actionData
} : { } ) , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let discoverResult = await discoverRoutes ( matches , location . pathname , request . signal ) ;
2026-02-04 00:11:19 +05:00
if ( discoverResult . type === "aborted" ) {
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
} else if ( discoverResult . type === "error" ) {
let boundaryId = findNearestBoundary ( discoverResult . partialMatches ) . route . id ;
return {
matches : discoverResult . partialMatches ,
loaderData : { } ,
errors : {
[ boundaryId ] : discoverResult . error
}
} ;
} else if ( ! discoverResult . matches ) {
2026-02-10 13:03:46 +05:00
let {
error ,
notFoundMatches ,
route
} = handleNavigational404 ( location . pathname ) ;
2026-02-04 00:11:19 +05:00
return {
matches : notFoundMatches ,
loaderData : { } ,
errors : {
[ route . id ] : error
}
} ;
} else {
matches = discoverResult . matches ;
}
}
let routesToUse = inFlightDataRoutes || dataRoutes ;
2026-02-10 13:03:46 +05:00
let [ matchesToLoad , revalidatingFetchers ] = getMatchesToLoad ( init . history , state , matches , activeSubmission , location , future . v7 _partialHydration && initialHydration === true , future . v7 _skipActionErrorRevalidation , isRevalidationRequired , cancelledDeferredRoutes , cancelledFetcherLoads , deletedFetchers , fetchLoadMatches , fetchRedirectIds , routesToUse , basename , pendingActionResult ) ;
cancelActiveDeferreds ( ( routeId ) => ! ( matches && matches . some ( ( m ) => m . route . id === routeId ) ) || matchesToLoad && matchesToLoad . some ( ( m ) => m . route . id === routeId ) ) ;
2026-02-04 00:11:19 +05:00
pendingNavigationLoadId = ++ incrementingLoadId ;
2026-02-10 13:03:46 +05:00
if ( matchesToLoad . length === 0 && revalidatingFetchers . length === 0 ) {
2026-02-04 00:11:19 +05:00
let updatedFetchers2 = markFetchRedirectsDone ( ) ;
2026-02-10 13:03:46 +05:00
completeNavigation ( location , _extends ( {
matches ,
loaderData : { } ,
// Commit pending error if we're short circuiting
errors : pendingActionResult && isErrorResult ( pendingActionResult [ 1 ] ) ? {
[ pendingActionResult [ 0 ] ] : pendingActionResult [ 1 ] . error
} : null
} , getActionDataForCommit ( pendingActionResult ) , updatedFetchers2 ? {
fetchers : new Map ( state . fetchers )
} : { } ) , {
flushSync
} ) ;
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
}
if ( shouldUpdateNavigationState ) {
let updates = { } ;
if ( ! isFogOfWar ) {
updates . navigation = loadingNavigation ;
let actionData = getUpdatedActionData ( pendingActionResult ) ;
if ( actionData !== void 0 ) {
updates . actionData = actionData ;
}
}
if ( revalidatingFetchers . length > 0 ) {
updates . fetchers = getUpdatedRevalidatingFetchers ( revalidatingFetchers ) ;
}
2026-02-10 13:03:46 +05:00
updateState ( updates , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
}
revalidatingFetchers . forEach ( ( rf ) => {
abortFetcher ( rf . key ) ;
if ( rf . controller ) {
fetchControllers . set ( rf . key , rf . controller ) ;
}
} ) ;
let abortPendingFetchRevalidations = ( ) => revalidatingFetchers . forEach ( ( f ) => abortFetcher ( f . key ) ) ;
if ( pendingNavigationController ) {
2026-02-10 13:03:46 +05:00
pendingNavigationController . signal . addEventListener ( "abort" , abortPendingFetchRevalidations ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let {
loaderResults ,
fetcherResults
} = await callLoadersAndMaybeResolveData ( state , matches , matchesToLoad , revalidatingFetchers , request ) ;
2026-02-04 00:11:19 +05:00
if ( request . signal . aborted ) {
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
}
if ( pendingNavigationController ) {
2026-02-10 13:03:46 +05:00
pendingNavigationController . signal . removeEventListener ( "abort" , abortPendingFetchRevalidations ) ;
2026-02-04 00:11:19 +05:00
}
revalidatingFetchers . forEach ( ( rf ) => fetchControllers . delete ( rf . key ) ) ;
2026-02-10 13:03:46 +05:00
let redirect3 = findRedirect ( loaderResults ) ;
if ( redirect3 ) {
await startRedirectNavigation ( request , redirect3 . result , true , {
2026-02-04 00:11:19 +05:00
replace : replace2
} ) ;
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
redirect3 = findRedirect ( fetcherResults ) ;
if ( redirect3 ) {
fetchRedirectIds . add ( redirect3 . key ) ;
await startRedirectNavigation ( request , redirect3 . result , true , {
2026-02-04 00:11:19 +05:00
replace : replace2
} ) ;
2026-02-10 13:03:46 +05:00
return {
shortCircuited : true
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let {
loaderData ,
errors
} = processLoaderData ( state , matches , loaderResults , pendingActionResult , revalidatingFetchers , fetcherResults , activeDeferreds ) ;
activeDeferreds . forEach ( ( deferredData , routeId ) => {
deferredData . subscribe ( ( aborted ) => {
if ( aborted || deferredData . done ) {
activeDeferreds . delete ( routeId ) ;
}
} ) ;
} ) ;
if ( future . v7 _partialHydration && initialHydration && state . errors ) {
errors = _extends ( { } , state . errors , errors ) ;
2026-02-04 00:11:19 +05:00
}
let updatedFetchers = markFetchRedirectsDone ( ) ;
let didAbortFetchLoads = abortStaleFetchLoads ( pendingNavigationLoadId ) ;
let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers . length > 0 ;
2026-02-10 13:03:46 +05:00
return _extends ( {
2026-02-04 00:11:19 +05:00
matches ,
loaderData ,
2026-02-10 13:03:46 +05:00
errors
} , shouldUpdateFetchers ? {
fetchers : new Map ( state . fetchers )
} : { } ) ;
2026-02-04 00:11:19 +05:00
}
function getUpdatedActionData ( pendingActionResult ) {
if ( pendingActionResult && ! isErrorResult ( pendingActionResult [ 1 ] ) ) {
return {
[ pendingActionResult [ 0 ] ] : pendingActionResult [ 1 ] . data
} ;
} else if ( state . actionData ) {
if ( Object . keys ( state . actionData ) . length === 0 ) {
return null ;
} else {
return state . actionData ;
}
}
}
function getUpdatedRevalidatingFetchers ( revalidatingFetchers ) {
revalidatingFetchers . forEach ( ( rf ) => {
let fetcher = state . fetchers . get ( rf . key ) ;
2026-02-10 13:03:46 +05:00
let revalidatingFetcher = getLoadingFetcher ( void 0 , fetcher ? fetcher . data : void 0 ) ;
2026-02-04 00:11:19 +05:00
state . fetchers . set ( rf . key , revalidatingFetcher ) ;
} ) ;
return new Map ( state . fetchers ) ;
}
2026-02-10 13:03:46 +05:00
function fetch ( key , routeId , href , opts ) {
if ( isServer ) {
throw new Error ( "router.fetch() was called during the server render, but it shouldn't be. You are likely calling a useFetcher() method in the body of your component. Try moving it to a useEffect or a callback." ) ;
}
2026-02-04 00:11:19 +05:00
abortFetcher ( key ) ;
2026-02-10 13:03:46 +05:00
let flushSync = ( opts && opts . flushSync ) === true ;
2026-02-04 00:11:19 +05:00
let routesToUse = inFlightDataRoutes || dataRoutes ;
2026-02-10 13:03:46 +05:00
let normalizedPath = normalizeTo ( state . location , state . matches , basename , future . v7 _prependBasename , href , future . v7 _relativeSplatPath , routeId , opts == null ? void 0 : opts . relative ) ;
2026-02-04 00:11:19 +05:00
let matches = matchRoutes ( routesToUse , normalizedPath , basename ) ;
let fogOfWar = checkFogOfWar ( matches , routesToUse , normalizedPath ) ;
if ( fogOfWar . active && fogOfWar . matches ) {
matches = fogOfWar . matches ;
}
if ( ! matches ) {
2026-02-10 13:03:46 +05:00
setFetcherError ( key , routeId , getInternalRouterError ( 404 , {
pathname : normalizedPath
} ) , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
let {
path ,
submission ,
error
} = normalizeNavigateOptions ( future . v7 _normalizeFormMethod , true , normalizedPath , opts ) ;
2026-02-04 00:11:19 +05:00
if ( error ) {
2026-02-10 13:03:46 +05:00
setFetcherError ( key , routeId , error , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
let match = getTargetMatch ( matches , path ) ;
2026-02-04 00:11:19 +05:00
let preventScrollReset = ( opts && opts . preventScrollReset ) === true ;
if ( submission && isMutationMethod ( submission . formMethod ) ) {
2026-02-10 13:03:46 +05:00
handleFetcherAction ( key , routeId , path , match , matches , fogOfWar . active , flushSync , preventScrollReset , submission ) ;
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
fetchLoadMatches . set ( key , {
2026-02-04 00:11:19 +05:00
routeId ,
2026-02-10 13:03:46 +05:00
path
} ) ;
handleFetcherLoader ( key , routeId , path , match , matches , fogOfWar . active , flushSync , preventScrollReset , submission ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function handleFetcherAction ( key , routeId , path , match , requestMatches , isFogOfWar , flushSync , preventScrollReset , submission ) {
2026-02-04 00:11:19 +05:00
interruptActiveLoads ( ) ;
fetchLoadMatches . delete ( key ) ;
2026-02-10 13:03:46 +05:00
function detectAndHandle405Error ( m ) {
if ( ! m . route . action && ! m . route . lazy ) {
let error = getInternalRouterError ( 405 , {
method : submission . formMethod ,
pathname : path ,
routeId
} ) ;
setFetcherError ( key , routeId , error , {
flushSync
} ) ;
return true ;
}
return false ;
}
if ( ! isFogOfWar && detectAndHandle405Error ( match ) ) {
return ;
}
2026-02-04 00:11:19 +05:00
let existingFetcher = state . fetchers . get ( key ) ;
updateFetcherState ( key , getSubmittingFetcher ( submission , existingFetcher ) , {
2026-02-10 13:03:46 +05:00
flushSync
2026-02-04 00:11:19 +05:00
} ) ;
let abortController = new AbortController ( ) ;
2026-02-10 13:03:46 +05:00
let fetchRequest = createClientSideRequest ( init . history , path , abortController . signal , submission ) ;
2026-02-04 00:11:19 +05:00
if ( isFogOfWar ) {
2026-02-10 13:03:46 +05:00
let discoverResult = await discoverRoutes ( requestMatches , new URL ( fetchRequest . url ) . pathname , fetchRequest . signal , key ) ;
2026-02-04 00:11:19 +05:00
if ( discoverResult . type === "aborted" ) {
return ;
} else if ( discoverResult . type === "error" ) {
2026-02-10 13:03:46 +05:00
setFetcherError ( key , routeId , discoverResult . error , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
} else if ( ! discoverResult . matches ) {
2026-02-10 13:03:46 +05:00
setFetcherError ( key , routeId , getInternalRouterError ( 404 , {
pathname : path
} ) , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
} else {
requestMatches = discoverResult . matches ;
2026-02-10 13:03:46 +05:00
match = getTargetMatch ( requestMatches , path ) ;
if ( detectAndHandle405Error ( match ) ) {
return ;
}
2026-02-04 00:11:19 +05:00
}
}
fetchControllers . set ( key , abortController ) ;
let originatingLoadId = incrementingLoadId ;
2026-02-10 13:03:46 +05:00
let actionResults = await callDataStrategy ( "action" , state , fetchRequest , [ match ] , requestMatches , key ) ;
2026-02-04 00:11:19 +05:00
let actionResult = actionResults [ match . route . id ] ;
if ( fetchRequest . signal . aborted ) {
if ( fetchControllers . get ( key ) === abortController ) {
fetchControllers . delete ( key ) ;
}
return ;
}
2026-02-10 13:03:46 +05:00
if ( future . v7 _fetcherPersist && deletedFetchers . has ( key ) ) {
2026-02-04 00:11:19 +05:00
if ( isRedirectResult ( actionResult ) || isErrorResult ( actionResult ) ) {
updateFetcherState ( key , getDoneFetcher ( void 0 ) ) ;
return ;
}
} else {
if ( isRedirectResult ( actionResult ) ) {
fetchControllers . delete ( key ) ;
if ( pendingNavigationLoadId > originatingLoadId ) {
updateFetcherState ( key , getDoneFetcher ( void 0 ) ) ;
return ;
} else {
fetchRedirectIds . add ( key ) ;
updateFetcherState ( key , getLoadingFetcher ( submission ) ) ;
return startRedirectNavigation ( fetchRequest , actionResult , false , {
fetcherSubmission : submission ,
preventScrollReset
} ) ;
}
}
if ( isErrorResult ( actionResult ) ) {
setFetcherError ( key , routeId , actionResult . error ) ;
return ;
}
}
2026-02-10 13:03:46 +05:00
if ( isDeferredResult ( actionResult ) ) {
throw getInternalRouterError ( 400 , {
type : "defer-action"
} ) ;
}
2026-02-04 00:11:19 +05:00
let nextLocation = state . navigation . location || state . location ;
2026-02-10 13:03:46 +05:00
let revalidationRequest = createClientSideRequest ( init . history , nextLocation , abortController . signal ) ;
2026-02-04 00:11:19 +05:00
let routesToUse = inFlightDataRoutes || dataRoutes ;
let matches = state . navigation . state !== "idle" ? matchRoutes ( routesToUse , state . navigation . location , basename ) : state . matches ;
invariant ( matches , "Didn't find any matches after fetcher action" ) ;
let loadId = ++ incrementingLoadId ;
fetchReloadIds . set ( key , loadId ) ;
let loadFetcher = getLoadingFetcher ( submission , actionResult . data ) ;
state . fetchers . set ( key , loadFetcher ) ;
2026-02-10 13:03:46 +05:00
let [ matchesToLoad , revalidatingFetchers ] = getMatchesToLoad ( init . history , state , matches , submission , nextLocation , false , future . v7 _skipActionErrorRevalidation , isRevalidationRequired , cancelledDeferredRoutes , cancelledFetcherLoads , deletedFetchers , fetchLoadMatches , fetchRedirectIds , routesToUse , basename , [ match . route . id , actionResult ] ) ;
2026-02-04 00:11:19 +05:00
revalidatingFetchers . filter ( ( rf ) => rf . key !== key ) . forEach ( ( rf ) => {
let staleKey = rf . key ;
let existingFetcher2 = state . fetchers . get ( staleKey ) ;
2026-02-10 13:03:46 +05:00
let revalidatingFetcher = getLoadingFetcher ( void 0 , existingFetcher2 ? existingFetcher2 . data : void 0 ) ;
2026-02-04 00:11:19 +05:00
state . fetchers . set ( staleKey , revalidatingFetcher ) ;
abortFetcher ( staleKey ) ;
if ( rf . controller ) {
fetchControllers . set ( staleKey , rf . controller ) ;
}
} ) ;
2026-02-10 13:03:46 +05:00
updateState ( {
fetchers : new Map ( state . fetchers )
} ) ;
2026-02-04 00:11:19 +05:00
let abortPendingFetchRevalidations = ( ) => revalidatingFetchers . forEach ( ( rf ) => abortFetcher ( rf . key ) ) ;
2026-02-10 13:03:46 +05:00
abortController . signal . addEventListener ( "abort" , abortPendingFetchRevalidations ) ;
let {
loaderResults ,
fetcherResults
} = await callLoadersAndMaybeResolveData ( state , matches , matchesToLoad , revalidatingFetchers , revalidationRequest ) ;
2026-02-04 00:11:19 +05:00
if ( abortController . signal . aborted ) {
return ;
}
2026-02-10 13:03:46 +05:00
abortController . signal . removeEventListener ( "abort" , abortPendingFetchRevalidations ) ;
2026-02-04 00:11:19 +05:00
fetchReloadIds . delete ( key ) ;
fetchControllers . delete ( key ) ;
revalidatingFetchers . forEach ( ( r ) => fetchControllers . delete ( r . key ) ) ;
2026-02-10 13:03:46 +05:00
let redirect3 = findRedirect ( loaderResults ) ;
if ( redirect3 ) {
return startRedirectNavigation ( revalidationRequest , redirect3 . result , false , {
preventScrollReset
} ) ;
}
redirect3 = findRedirect ( fetcherResults ) ;
if ( redirect3 ) {
fetchRedirectIds . add ( redirect3 . key ) ;
return startRedirectNavigation ( revalidationRequest , redirect3 . result , false , {
preventScrollReset
} ) ;
}
let {
loaderData ,
errors
} = processLoaderData ( state , matches , loaderResults , void 0 , revalidatingFetchers , fetcherResults , activeDeferreds ) ;
2026-02-04 00:11:19 +05:00
if ( state . fetchers . has ( key ) ) {
let doneFetcher = getDoneFetcher ( actionResult . data ) ;
state . fetchers . set ( key , doneFetcher ) ;
}
abortStaleFetchLoads ( loadId ) ;
if ( state . navigation . state === "loading" && loadId > pendingNavigationLoadId ) {
invariant ( pendingAction , "Expected pending action" ) ;
pendingNavigationController && pendingNavigationController . abort ( ) ;
completeNavigation ( state . navigation . location , {
matches ,
loaderData ,
errors ,
fetchers : new Map ( state . fetchers )
} ) ;
} else {
updateState ( {
errors ,
2026-02-10 13:03:46 +05:00
loaderData : mergeLoaderData ( state . loaderData , loaderData , matches , errors ) ,
2026-02-04 00:11:19 +05:00
fetchers : new Map ( state . fetchers )
} ) ;
isRevalidationRequired = false ;
}
}
2026-02-10 13:03:46 +05:00
async function handleFetcherLoader ( key , routeId , path , match , matches , isFogOfWar , flushSync , preventScrollReset , submission ) {
2026-02-04 00:11:19 +05:00
let existingFetcher = state . fetchers . get ( key ) ;
2026-02-10 13:03:46 +05:00
updateFetcherState ( key , getLoadingFetcher ( submission , existingFetcher ? existingFetcher . data : void 0 ) , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
let abortController = new AbortController ( ) ;
2026-02-10 13:03:46 +05:00
let fetchRequest = createClientSideRequest ( init . history , path , abortController . signal ) ;
2026-02-04 00:11:19 +05:00
if ( isFogOfWar ) {
2026-02-10 13:03:46 +05:00
let discoverResult = await discoverRoutes ( matches , new URL ( fetchRequest . url ) . pathname , fetchRequest . signal , key ) ;
2026-02-04 00:11:19 +05:00
if ( discoverResult . type === "aborted" ) {
return ;
} else if ( discoverResult . type === "error" ) {
2026-02-10 13:03:46 +05:00
setFetcherError ( key , routeId , discoverResult . error , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
} else if ( ! discoverResult . matches ) {
2026-02-10 13:03:46 +05:00
setFetcherError ( key , routeId , getInternalRouterError ( 404 , {
pathname : path
} ) , {
flushSync
} ) ;
2026-02-04 00:11:19 +05:00
return ;
} else {
matches = discoverResult . matches ;
2026-02-10 13:03:46 +05:00
match = getTargetMatch ( matches , path ) ;
2026-02-04 00:11:19 +05:00
}
}
fetchControllers . set ( key , abortController ) ;
let originatingLoadId = incrementingLoadId ;
2026-02-10 13:03:46 +05:00
let results = await callDataStrategy ( "loader" , state , fetchRequest , [ match ] , matches , key ) ;
2026-02-04 00:11:19 +05:00
let result = results [ match . route . id ] ;
2026-02-10 13:03:46 +05:00
if ( isDeferredResult ( result ) ) {
result = await resolveDeferredData ( result , fetchRequest . signal , true ) || result ;
}
2026-02-04 00:11:19 +05:00
if ( fetchControllers . get ( key ) === abortController ) {
fetchControllers . delete ( key ) ;
}
if ( fetchRequest . signal . aborted ) {
return ;
}
2026-02-10 13:03:46 +05:00
if ( deletedFetchers . has ( key ) ) {
2026-02-04 00:11:19 +05:00
updateFetcherState ( key , getDoneFetcher ( void 0 ) ) ;
return ;
}
if ( isRedirectResult ( result ) ) {
if ( pendingNavigationLoadId > originatingLoadId ) {
updateFetcherState ( key , getDoneFetcher ( void 0 ) ) ;
return ;
} else {
fetchRedirectIds . add ( key ) ;
await startRedirectNavigation ( fetchRequest , result , false , {
preventScrollReset
} ) ;
return ;
}
}
if ( isErrorResult ( result ) ) {
setFetcherError ( key , routeId , result . error ) ;
return ;
}
2026-02-10 13:03:46 +05:00
invariant ( ! isDeferredResult ( result ) , "Unhandled fetcher deferred data" ) ;
2026-02-04 00:11:19 +05:00
updateFetcherState ( key , getDoneFetcher ( result . data ) ) ;
}
2026-02-10 13:03:46 +05:00
async function startRedirectNavigation ( request , redirect3 , isNavigation , _temp2 ) {
let {
submission ,
fetcherSubmission ,
preventScrollReset ,
replace : replace2
} = _temp2 === void 0 ? { } : _temp2 ;
if ( redirect3 . response . headers . has ( "X-Remix-Revalidate" ) ) {
2026-02-04 00:11:19 +05:00
isRevalidationRequired = true ;
}
2026-02-10 13:03:46 +05:00
let location = redirect3 . response . headers . get ( "Location" ) ;
invariant ( location , "Expected a Location header on the redirect Response" ) ;
location = normalizeRedirectLocation ( location , new URL ( request . url ) , basename , init . history ) ;
let redirectLocation = createLocation ( state . location , location , {
2026-02-04 00:11:19 +05:00
_isRedirect : true
} ) ;
2026-02-10 13:03:46 +05:00
if ( isBrowser2 ) {
2026-02-04 00:11:19 +05:00
let isDocumentReload = false ;
2026-02-10 13:03:46 +05:00
if ( redirect3 . response . headers . has ( "X-Remix-Reload-Document" ) ) {
2026-02-04 00:11:19 +05:00
isDocumentReload = true ;
2026-02-10 13:03:46 +05:00
} else if ( ABSOLUTE _URL _REGEX . test ( location ) ) {
const url = init . history . createURL ( location ) ;
2026-02-04 00:11:19 +05:00
isDocumentReload = // Hard reload if it's an absolute URL to a new origin
url . origin !== routerWindow . location . origin || // Hard reload if it's an absolute URL that does not match our basename
stripBasename ( url . pathname , basename ) == null ;
}
if ( isDocumentReload ) {
if ( replace2 ) {
2026-02-10 13:03:46 +05:00
routerWindow . location . replace ( location ) ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
routerWindow . location . assign ( location ) ;
2026-02-04 00:11:19 +05:00
}
return ;
}
}
pendingNavigationController = null ;
2026-02-10 13:03:46 +05:00
let redirectHistoryAction = replace2 === true || redirect3 . response . headers . has ( "X-Remix-Replace" ) ? Action . Replace : Action . Push ;
let {
formMethod ,
formAction ,
formEncType
} = state . navigation ;
2026-02-04 00:11:19 +05:00
if ( ! submission && ! fetcherSubmission && formMethod && formAction && formEncType ) {
submission = getSubmissionFromNavigation ( state . navigation ) ;
}
let activeSubmission = submission || fetcherSubmission ;
2026-02-10 13:03:46 +05:00
if ( redirectPreserveMethodStatusCodes . has ( redirect3 . response . status ) && activeSubmission && isMutationMethod ( activeSubmission . formMethod ) ) {
await startNavigation ( redirectHistoryAction , redirectLocation , {
submission : _extends ( { } , activeSubmission , {
formAction : location
} ) ,
2026-02-04 00:11:19 +05:00
// Preserve these flags across redirects
preventScrollReset : preventScrollReset || pendingPreventScrollReset ,
enableViewTransition : isNavigation ? pendingViewTransitionEnabled : void 0
} ) ;
} else {
2026-02-10 13:03:46 +05:00
let overrideNavigation = getLoadingNavigation ( redirectLocation , submission ) ;
await startNavigation ( redirectHistoryAction , redirectLocation , {
2026-02-04 00:11:19 +05:00
overrideNavigation ,
// Send fetcher submissions through for shouldRevalidate
fetcherSubmission ,
// Preserve these flags across redirects
preventScrollReset : preventScrollReset || pendingPreventScrollReset ,
enableViewTransition : isNavigation ? pendingViewTransitionEnabled : void 0
} ) ;
}
}
2026-02-10 13:03:46 +05:00
async function callDataStrategy ( type , state2 , request , matchesToLoad , matches , fetcherKey ) {
2026-02-04 00:11:19 +05:00
let results ;
let dataResults = { } ;
try {
2026-02-10 13:03:46 +05:00
results = await callDataStrategyImpl ( dataStrategyImpl , type , state2 , request , matchesToLoad , matches , fetcherKey , manifest , mapRouteProperties2 ) ;
2026-02-04 00:11:19 +05:00
} catch ( e ) {
2026-02-10 13:03:46 +05:00
matchesToLoad . forEach ( ( m ) => {
2026-02-04 00:11:19 +05:00
dataResults [ m . route . id ] = {
2026-02-10 13:03:46 +05:00
type : ResultType . error ,
2026-02-04 00:11:19 +05:00
error : e
} ;
} ) ;
return dataResults ;
}
for ( let [ routeId , result ] of Object . entries ( results ) ) {
2026-02-10 13:03:46 +05:00
if ( isRedirectDataStrategyResultResult ( result ) ) {
2026-02-04 00:11:19 +05:00
let response = result . result ;
dataResults [ routeId ] = {
2026-02-10 13:03:46 +05:00
type : ResultType . redirect ,
response : normalizeRelativeRoutingRedirectResponse ( response , request , routeId , matches , basename , future . v7 _relativeSplatPath )
2026-02-04 00:11:19 +05:00
} ;
} else {
dataResults [ routeId ] = await convertDataStrategyResultToDataResult ( result ) ;
}
}
return dataResults ;
}
2026-02-10 13:03:46 +05:00
async function callLoadersAndMaybeResolveData ( state2 , matches , matchesToLoad , fetchersToLoad , request ) {
let currentMatches = state2 . matches ;
let loaderResultsPromise = callDataStrategy ( "loader" , state2 , request , matchesToLoad , matches , null ) ;
let fetcherResultsPromise = Promise . all ( fetchersToLoad . map ( async ( f ) => {
if ( f . matches && f . match && f . controller ) {
let results = await callDataStrategy ( "loader" , state2 , createClientSideRequest ( init . history , f . path , f . controller . signal ) , [ f . match ] , f . matches , f . key ) ;
let result = results [ f . match . route . id ] ;
return {
[ f . key ] : result
} ;
} else {
return Promise . resolve ( {
[ f . key ] : {
type : ResultType . error ,
error : getInternalRouterError ( 404 , {
pathname : f . path
} )
}
} ) ;
}
} ) ) ;
2026-02-04 00:11:19 +05:00
let loaderResults = await loaderResultsPromise ;
2026-02-10 13:03:46 +05:00
let fetcherResults = ( await fetcherResultsPromise ) . reduce ( ( acc , r ) => Object . assign ( acc , r ) , { } ) ;
await Promise . all ( [ resolveNavigationDeferredResults ( matches , loaderResults , request . signal , currentMatches , state2 . loaderData ) , resolveFetcherDeferredResults ( matches , fetcherResults , fetchersToLoad ) ] ) ;
2026-02-04 00:11:19 +05:00
return {
loaderResults ,
fetcherResults
} ;
}
function interruptActiveLoads ( ) {
isRevalidationRequired = true ;
2026-02-10 13:03:46 +05:00
cancelledDeferredRoutes . push ( ... cancelActiveDeferreds ( ) ) ;
2026-02-04 00:11:19 +05:00
fetchLoadMatches . forEach ( ( _ , key ) => {
if ( fetchControllers . has ( key ) ) {
cancelledFetcherLoads . add ( key ) ;
}
abortFetcher ( key ) ;
} ) ;
}
2026-02-10 13:03:46 +05:00
function updateFetcherState ( key , fetcher , opts ) {
if ( opts === void 0 ) {
opts = { } ;
}
2026-02-04 00:11:19 +05:00
state . fetchers . set ( key , fetcher ) ;
2026-02-10 13:03:46 +05:00
updateState ( {
fetchers : new Map ( state . fetchers )
} , {
flushSync : ( opts && opts . flushSync ) === true
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function setFetcherError ( key , routeId , error , opts ) {
if ( opts === void 0 ) {
opts = { } ;
}
2026-02-04 00:11:19 +05:00
let boundaryMatch = findNearestBoundary ( state . matches , routeId ) ;
deleteFetcher ( key ) ;
2026-02-10 13:03:46 +05:00
updateState ( {
errors : {
[ boundaryMatch . route . id ] : error
2026-02-04 00:11:19 +05:00
} ,
2026-02-10 13:03:46 +05:00
fetchers : new Map ( state . fetchers )
} , {
flushSync : ( opts && opts . flushSync ) === true
} ) ;
2026-02-04 00:11:19 +05:00
}
function getFetcher ( key ) {
activeFetchers . set ( key , ( activeFetchers . get ( key ) || 0 ) + 1 ) ;
2026-02-10 13:03:46 +05:00
if ( deletedFetchers . has ( key ) ) {
deletedFetchers . delete ( key ) ;
2026-02-04 00:11:19 +05:00
}
return state . fetchers . get ( key ) || IDLE _FETCHER ;
}
function deleteFetcher ( key ) {
let fetcher = state . fetchers . get ( key ) ;
if ( fetchControllers . has ( key ) && ! ( fetcher && fetcher . state === "loading" && fetchReloadIds . has ( key ) ) ) {
abortFetcher ( key ) ;
}
fetchLoadMatches . delete ( key ) ;
fetchReloadIds . delete ( key ) ;
fetchRedirectIds . delete ( key ) ;
2026-02-10 13:03:46 +05:00
if ( future . v7 _fetcherPersist ) {
deletedFetchers . delete ( key ) ;
}
2026-02-04 00:11:19 +05:00
cancelledFetcherLoads . delete ( key ) ;
state . fetchers . delete ( key ) ;
}
2026-02-10 13:03:46 +05:00
function deleteFetcherAndUpdateState ( key ) {
2026-02-04 00:11:19 +05:00
let count = ( activeFetchers . get ( key ) || 0 ) - 1 ;
if ( count <= 0 ) {
activeFetchers . delete ( key ) ;
2026-02-10 13:03:46 +05:00
deletedFetchers . add ( key ) ;
if ( ! future . v7 _fetcherPersist ) {
deleteFetcher ( key ) ;
}
2026-02-04 00:11:19 +05:00
} else {
activeFetchers . set ( key , count ) ;
}
2026-02-10 13:03:46 +05:00
updateState ( {
fetchers : new Map ( state . fetchers )
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function abortFetcher ( key ) {
2026-02-04 00:11:19 +05:00
let controller = fetchControllers . get ( key ) ;
if ( controller ) {
2026-02-10 13:03:46 +05:00
controller . abort ( ) ;
2026-02-04 00:11:19 +05:00
fetchControllers . delete ( key ) ;
}
}
function markFetchersDone ( keys ) {
for ( let key of keys ) {
let fetcher = getFetcher ( key ) ;
let doneFetcher = getDoneFetcher ( fetcher . data ) ;
state . fetchers . set ( key , doneFetcher ) ;
}
}
function markFetchRedirectsDone ( ) {
let doneKeys = [ ] ;
let updatedFetchers = false ;
for ( let key of fetchRedirectIds ) {
let fetcher = state . fetchers . get ( key ) ;
2026-02-10 13:03:46 +05:00
invariant ( fetcher , "Expected fetcher: " + key ) ;
2026-02-04 00:11:19 +05:00
if ( fetcher . state === "loading" ) {
fetchRedirectIds . delete ( key ) ;
doneKeys . push ( key ) ;
updatedFetchers = true ;
}
}
markFetchersDone ( doneKeys ) ;
return updatedFetchers ;
}
function abortStaleFetchLoads ( landedId ) {
let yeetedKeys = [ ] ;
for ( let [ key , id ] of fetchReloadIds ) {
if ( id < landedId ) {
let fetcher = state . fetchers . get ( key ) ;
2026-02-10 13:03:46 +05:00
invariant ( fetcher , "Expected fetcher: " + key ) ;
2026-02-04 00:11:19 +05:00
if ( fetcher . state === "loading" ) {
abortFetcher ( key ) ;
fetchReloadIds . delete ( key ) ;
yeetedKeys . push ( key ) ;
}
}
}
markFetchersDone ( yeetedKeys ) ;
return yeetedKeys . length > 0 ;
}
function getBlocker ( key , fn ) {
let blocker = state . blockers . get ( key ) || IDLE _BLOCKER ;
if ( blockerFunctions . get ( key ) !== fn ) {
blockerFunctions . set ( key , fn ) ;
}
return blocker ;
}
function deleteBlocker ( key ) {
state . blockers . delete ( key ) ;
blockerFunctions . delete ( key ) ;
}
function updateBlocker ( key , newBlocker ) {
let blocker = state . blockers . get ( key ) || IDLE _BLOCKER ;
2026-02-10 13:03:46 +05:00
invariant ( blocker . state === "unblocked" && newBlocker . state === "blocked" || blocker . state === "blocked" && newBlocker . state === "blocked" || blocker . state === "blocked" && newBlocker . state === "proceeding" || blocker . state === "blocked" && newBlocker . state === "unblocked" || blocker . state === "proceeding" && newBlocker . state === "unblocked" , "Invalid blocker state transition: " + blocker . state + " -> " + newBlocker . state ) ;
2026-02-04 00:11:19 +05:00
let blockers = new Map ( state . blockers ) ;
blockers . set ( key , newBlocker ) ;
2026-02-10 13:03:46 +05:00
updateState ( {
blockers
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function shouldBlockNavigation ( _ref2 ) {
let {
currentLocation ,
nextLocation ,
historyAction
} = _ref2 ;
2026-02-04 00:11:19 +05:00
if ( blockerFunctions . size === 0 ) {
return ;
}
if ( blockerFunctions . size > 1 ) {
warning ( false , "A router only supports one blocker at a time" ) ;
}
let entries = Array . from ( blockerFunctions . entries ( ) ) ;
let [ blockerKey , blockerFunction ] = entries [ entries . length - 1 ] ;
let blocker = state . blockers . get ( blockerKey ) ;
if ( blocker && blocker . state === "proceeding" ) {
return ;
}
2026-02-10 13:03:46 +05:00
if ( blockerFunction ( {
currentLocation ,
nextLocation ,
historyAction
} ) ) {
2026-02-04 00:11:19 +05:00
return blockerKey ;
}
}
function handleNavigational404 ( pathname ) {
2026-02-10 13:03:46 +05:00
let error = getInternalRouterError ( 404 , {
pathname
} ) ;
2026-02-04 00:11:19 +05:00
let routesToUse = inFlightDataRoutes || dataRoutes ;
2026-02-10 13:03:46 +05:00
let {
matches ,
route
} = getShortCircuitMatches ( routesToUse ) ;
cancelActiveDeferreds ( ) ;
return {
notFoundMatches : matches ,
route ,
error
} ;
}
function cancelActiveDeferreds ( predicate ) {
let cancelledRouteIds = [ ] ;
activeDeferreds . forEach ( ( dfd , routeId ) => {
if ( ! predicate || predicate ( routeId ) ) {
dfd . cancel ( ) ;
cancelledRouteIds . push ( routeId ) ;
activeDeferreds . delete ( routeId ) ;
}
} ) ;
return cancelledRouteIds ;
2026-02-04 00:11:19 +05:00
}
function enableScrollRestoration ( positions , getPosition , getKey ) {
savedScrollPositions2 = positions ;
getScrollPosition = getPosition ;
2026-02-10 13:03:46 +05:00
getScrollRestorationKey = getKey || null ;
2026-02-04 00:11:19 +05:00
if ( ! initialScrollRestored && state . navigation === IDLE _NAVIGATION ) {
initialScrollRestored = true ;
let y = getSavedScrollPosition ( state . location , state . matches ) ;
if ( y != null ) {
2026-02-10 13:03:46 +05:00
updateState ( {
restoreScrollPosition : y
} ) ;
2026-02-04 00:11:19 +05:00
}
}
return ( ) => {
savedScrollPositions2 = null ;
getScrollPosition = null ;
2026-02-10 13:03:46 +05:00
getScrollRestorationKey = null ;
2026-02-04 00:11:19 +05:00
} ;
}
2026-02-10 13:03:46 +05:00
function getScrollKey ( location , matches ) {
if ( getScrollRestorationKey ) {
let key = getScrollRestorationKey ( location , matches . map ( ( m ) => convertRouteMatchToUiMatch ( m , state . loaderData ) ) ) ;
return key || location . key ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return location . key ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function saveScrollPosition ( location , matches ) {
2026-02-04 00:11:19 +05:00
if ( savedScrollPositions2 && getScrollPosition ) {
2026-02-10 13:03:46 +05:00
let key = getScrollKey ( location , matches ) ;
2026-02-04 00:11:19 +05:00
savedScrollPositions2 [ key ] = getScrollPosition ( ) ;
}
}
2026-02-10 13:03:46 +05:00
function getSavedScrollPosition ( location , matches ) {
2026-02-04 00:11:19 +05:00
if ( savedScrollPositions2 ) {
2026-02-10 13:03:46 +05:00
let key = getScrollKey ( location , matches ) ;
2026-02-04 00:11:19 +05:00
let y = savedScrollPositions2 [ key ] ;
if ( typeof y === "number" ) {
return y ;
}
}
return null ;
}
function checkFogOfWar ( matches , routesToUse , pathname ) {
2026-02-10 13:03:46 +05:00
if ( patchRoutesOnNavigationImpl ) {
2026-02-04 00:11:19 +05:00
if ( ! matches ) {
2026-02-10 13:03:46 +05:00
let fogMatches = matchRoutesImpl ( routesToUse , pathname , basename , true ) ;
return {
active : true ,
matches : fogMatches || [ ]
} ;
2026-02-04 00:11:19 +05:00
} else {
if ( Object . keys ( matches [ 0 ] . params ) . length > 0 ) {
2026-02-10 13:03:46 +05:00
let partialMatches = matchRoutesImpl ( routesToUse , pathname , basename , true ) ;
return {
active : true ,
matches : partialMatches
} ;
2026-02-04 00:11:19 +05:00
}
}
}
2026-02-10 13:03:46 +05:00
return {
active : false ,
matches : null
} ;
2026-02-04 00:11:19 +05:00
}
async function discoverRoutes ( matches , pathname , signal , fetcherKey ) {
2026-02-10 13:03:46 +05:00
if ( ! patchRoutesOnNavigationImpl ) {
return {
type : "success" ,
matches
} ;
2026-02-04 00:11:19 +05:00
}
let partialMatches = matches ;
while ( true ) {
let isNonHMR = inFlightDataRoutes == null ;
let routesToUse = inFlightDataRoutes || dataRoutes ;
let localManifest = manifest ;
try {
2026-02-10 13:03:46 +05:00
await patchRoutesOnNavigationImpl ( {
2026-02-04 00:11:19 +05:00
signal ,
path : pathname ,
matches : partialMatches ,
fetcherKey ,
patch : ( routeId , children ) => {
if ( signal . aborted ) return ;
2026-02-10 13:03:46 +05:00
patchRoutesImpl ( routeId , children , routesToUse , localManifest , mapRouteProperties2 ) ;
2026-02-04 00:11:19 +05:00
}
} ) ;
} catch ( e ) {
2026-02-10 13:03:46 +05:00
return {
type : "error" ,
error : e ,
partialMatches
} ;
2026-02-04 00:11:19 +05:00
} finally {
if ( isNonHMR && ! signal . aborted ) {
dataRoutes = [ ... dataRoutes ] ;
}
}
if ( signal . aborted ) {
2026-02-10 13:03:46 +05:00
return {
type : "aborted"
} ;
2026-02-04 00:11:19 +05:00
}
let newMatches = matchRoutes ( routesToUse , pathname , basename ) ;
if ( newMatches ) {
2026-02-10 13:03:46 +05:00
return {
type : "success" ,
matches : newMatches
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let newPartialMatches = matchRoutesImpl ( routesToUse , pathname , basename , true ) ;
if ( ! newPartialMatches || partialMatches . length === newPartialMatches . length && partialMatches . every ( ( m , i ) => m . route . id === newPartialMatches [ i ] . route . id ) ) {
return {
type : "success" ,
matches : null
} ;
2026-02-04 00:11:19 +05:00
}
partialMatches = newPartialMatches ;
}
}
function _internalSetRoutes ( newRoutes ) {
manifest = { } ;
2026-02-10 13:03:46 +05:00
inFlightDataRoutes = convertRoutesToDataRoutes ( newRoutes , mapRouteProperties2 , void 0 , manifest ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function patchRoutes ( routeId , children ) {
2026-02-04 00:11:19 +05:00
let isNonHMR = inFlightDataRoutes == null ;
let routesToUse = inFlightDataRoutes || dataRoutes ;
2026-02-10 13:03:46 +05:00
patchRoutesImpl ( routeId , children , routesToUse , manifest , mapRouteProperties2 ) ;
2026-02-04 00:11:19 +05:00
if ( isNonHMR ) {
dataRoutes = [ ... dataRoutes ] ;
updateState ( { } ) ;
}
}
2026-02-10 13:03:46 +05:00
router = {
2026-02-04 00:11:19 +05:00
get basename ( ) {
return basename ;
} ,
get future ( ) {
return future ;
} ,
get state ( ) {
return state ;
} ,
get routes ( ) {
return dataRoutes ;
} ,
get window ( ) {
return routerWindow ;
} ,
initialize ,
subscribe ,
enableScrollRestoration ,
navigate ,
2026-02-10 13:03:46 +05:00
fetch ,
2026-02-04 00:11:19 +05:00
revalidate ,
// Passthrough to history-aware createHref used by useHref so we get proper
// hash-aware URLs in DOM paths
createHref : ( to ) => init . history . createHref ( to ) ,
encodeLocation : ( to ) => init . history . encodeLocation ( to ) ,
getFetcher ,
2026-02-10 13:03:46 +05:00
deleteFetcher : deleteFetcherAndUpdateState ,
2026-02-04 00:11:19 +05:00
dispose ,
getBlocker ,
deleteBlocker ,
patchRoutes ,
_internalFetchControllers : fetchControllers ,
2026-02-10 13:03:46 +05:00
_internalActiveDeferreds : activeDeferreds ,
2026-02-04 00:11:19 +05:00
// TODO: Remove setRoutes, it's temporary to avoid dealing with
// updating the tree while validating the update algorithm.
2026-02-10 13:03:46 +05:00
_internalSetRoutes
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
return router ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var UNSAFE _DEFERRED _SYMBOL = Symbol ( "deferred" ) ;
2026-02-04 00:11:19 +05:00
function isSubmissionNavigation ( opts ) {
return opts != null && ( "formData" in opts && opts . formData != null || "body" in opts && opts . body !== void 0 ) ;
}
2026-02-10 13:03:46 +05:00
function normalizeTo ( location , matches , basename , prependBasename , to , v7 _relativeSplatPath , fromRouteId , relative ) {
2026-02-04 00:11:19 +05:00
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 ] ;
}
2026-02-10 13:03:46 +05:00
let path = resolveTo ( to ? to : "." , getResolveToMatches ( contextualMatches , v7 _relativeSplatPath ) , stripBasename ( location . pathname , basename ) || location . pathname , relative === "path" ) ;
2026-02-04 00:11:19 +05:00
if ( to == null ) {
2026-02-10 13:03:46 +05:00
path . search = location . search ;
path . hash = location . hash ;
2026-02-04 00:11:19 +05:00
}
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 ( ) ;
2026-02-10 13:03:46 +05:00
path . search = qs ? "?" + qs : "" ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
if ( prependBasename && basename !== "/" ) {
path . pathname = path . pathname === "/" ? basename : joinPaths ( [ basename , path . pathname ] ) ;
2026-02-04 00:11:19 +05:00
}
return createPath ( path ) ;
}
2026-02-10 13:03:46 +05:00
function normalizeNavigateOptions ( normalizeFormMethod , isFetcher , path , opts ) {
2026-02-04 00:11:19 +05:00
if ( ! opts || ! isSubmissionNavigation ( opts ) ) {
2026-02-10 13:03:46 +05:00
return {
path
} ;
2026-02-04 00:11:19 +05:00
}
if ( opts . formMethod && ! isValidMethod ( opts . formMethod ) ) {
return {
path ,
2026-02-10 13:03:46 +05:00
error : getInternalRouterError ( 405 , {
method : opts . formMethod
} )
2026-02-04 00:11:19 +05:00
} ;
}
let getInvalidBodyError = ( ) => ( {
path ,
2026-02-10 13:03:46 +05:00
error : getInternalRouterError ( 400 , {
type : "invalid-body"
} )
2026-02-04 00:11:19 +05:00
} ) ;
let rawFormMethod = opts . formMethod || "get" ;
2026-02-10 13:03:46 +05:00
let formMethod = normalizeFormMethod ? rawFormMethod . toUpperCase ( ) : rawFormMethod . toLowerCase ( ) ;
2026-02-04 00:11:19 +05:00
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
2026-02-10 13:03:46 +05:00
Array . from ( opts . body . entries ( ) ) . reduce ( ( acc , _ref3 ) => {
let [ name , value ] = _ref3 ;
return "" + acc + name + "=" + value + "\n" ;
} , "" )
2026-02-04 00:11:19 +05:00
) : 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 {
2026-02-10 13:03:46 +05:00
let json3 = typeof opts . body === "string" ? JSON . parse ( opts . body ) : opts . body ;
2026-02-04 00:11:19 +05:00
return {
path ,
submission : {
formMethod ,
formAction ,
formEncType : opts . formEncType ,
formData : void 0 ,
2026-02-10 13:03:46 +05:00
json : json3 ,
2026-02-04 00:11:19 +05:00
text : void 0
}
} ;
} catch ( e ) {
return getInvalidBodyError ( ) ;
}
}
}
2026-02-10 13:03:46 +05:00
invariant ( typeof FormData === "function" , "FormData is not available in this environment" ) ;
2026-02-04 00:11:19 +05:00
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 ) ) {
2026-02-10 13:03:46 +05:00
return {
path ,
submission
} ;
2026-02-04 00:11:19 +05:00
}
let parsedPath = parsePath ( path ) ;
if ( isFetcher && parsedPath . search && hasNakedIndexQuery ( parsedPath . search ) ) {
searchParams . append ( "index" , "" ) ;
}
2026-02-10 13:03:46 +05:00
parsedPath . search = "?" + searchParams ;
return {
path : createPath ( parsedPath ) ,
submission
} ;
}
function getLoaderMatchesUntilBoundary ( matches , boundaryId , includeBoundary ) {
if ( includeBoundary === void 0 ) {
includeBoundary = false ;
}
let index = matches . findIndex ( ( m ) => m . route . id === boundaryId ) ;
if ( index >= 0 ) {
return matches . slice ( 0 , includeBoundary ? index + 1 : index ) ;
}
return matches ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function getMatchesToLoad ( history , state , matches , submission , location , initialHydration , skipActionErrorRevalidation , isRevalidationRequired , cancelledDeferredRoutes , cancelledFetcherLoads , deletedFetchers , fetchLoadMatches , fetchRedirectIds , routesToUse , basename , pendingActionResult ) {
2026-02-04 00:11:19 +05:00
let actionResult = pendingActionResult ? isErrorResult ( pendingActionResult [ 1 ] ) ? pendingActionResult [ 1 ] . error : pendingActionResult [ 1 ] . data : void 0 ;
let currentUrl = history . createURL ( state . location ) ;
2026-02-10 13:03:46 +05:00
let nextUrl = history . createURL ( location ) ;
let boundaryMatches = matches ;
2026-02-04 00:11:19 +05:00
if ( initialHydration && state . errors ) {
2026-02-10 13:03:46 +05:00
boundaryMatches = getLoaderMatchesUntilBoundary ( matches , Object . keys ( state . errors ) [ 0 ] , true ) ;
2026-02-04 00:11:19 +05:00
} else if ( pendingActionResult && isErrorResult ( pendingActionResult [ 1 ] ) ) {
2026-02-10 13:03:46 +05:00
boundaryMatches = getLoaderMatchesUntilBoundary ( matches , pendingActionResult [ 0 ] ) ;
2026-02-04 00:11:19 +05:00
}
let actionStatus = pendingActionResult ? pendingActionResult [ 1 ] . statusCode : void 0 ;
2026-02-10 13:03:46 +05:00
let shouldSkipRevalidation = skipActionErrorRevalidation && actionStatus && actionStatus >= 400 ;
let navigationMatches = boundaryMatches . filter ( ( match , index ) => {
let {
route
} = match ;
if ( route . lazy ) {
return true ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( route . loader == null ) {
return false ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( initialHydration ) {
return shouldLoadRouteOnHydration ( route , state . loaderData , state . errors ) ;
}
if ( isNewLoader ( state . loaderData , state . matches [ index ] , match ) || cancelledDeferredRoutes . some ( ( id ) => id === match . route . id ) ) {
return true ;
}
let currentRouteMatch = state . matches [ index ] ;
let nextRouteMatch = match ;
return shouldRevalidateLoader ( match , _extends ( {
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 )
)
} ) ) ;
2026-02-04 00:11:19 +05:00
} ) ;
let revalidatingFetchers = [ ] ;
fetchLoadMatches . forEach ( ( f , key ) => {
2026-02-10 13:03:46 +05:00
if ( initialHydration || ! matches . some ( ( m ) => m . route . id === f . routeId ) || deletedFetchers . has ( key ) ) {
2026-02-04 00:11:19 +05:00
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 ;
}
2026-02-10 13:03:46 +05:00
let fetcher = state . fetchers . get ( key ) ;
2026-02-04 00:11:19 +05:00
let fetcherMatch = getTargetMatch ( fetcherMatches , f . path ) ;
2026-02-10 13:03:46 +05:00
let shouldRevalidate = false ;
if ( fetchRedirectIds . has ( key ) ) {
shouldRevalidate = false ;
} else if ( cancelledFetcherLoads . has ( key ) ) {
2026-02-04 00:11:19 +05:00
cancelledFetcherLoads . delete ( key ) ;
2026-02-10 13:03:46 +05:00
shouldRevalidate = true ;
} else if ( fetcher && fetcher . state !== "idle" && fetcher . data === void 0 ) {
shouldRevalidate = isRevalidationRequired ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
shouldRevalidate = shouldRevalidateLoader ( fetcherMatch , _extends ( {
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 ) {
2026-02-04 00:11:19 +05:00
revalidatingFetchers . push ( {
key ,
routeId : f . routeId ,
path : f . path ,
2026-02-10 13:03:46 +05:00
matches : fetcherMatches ,
2026-02-04 00:11:19 +05:00
match : fetcherMatch ,
2026-02-10 13:03:46 +05:00
controller : new AbortController ( )
2026-02-04 00:11:19 +05:00
} ) ;
}
} ) ;
2026-02-10 13:03:46 +05:00
return [ navigationMatches , revalidatingFetchers ] ;
2026-02-04 00:11:19 +05:00
}
function shouldLoadRouteOnHydration ( route , loaderData , errors ) {
if ( route . lazy ) {
return true ;
}
2026-02-10 13:03:46 +05:00
if ( ! route . loader ) {
2026-02-04 00:11:19 +05:00
return false ;
}
2026-02-10 13:03:46 +05:00
let hasData = loaderData != null && loaderData [ route . id ] !== void 0 ;
2026-02-04 00:11:19 +05:00
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
) ;
2026-02-10 13:03:46 +05:00
let isMissingData = currentLoaderData [ match . route . id ] === void 0 ;
2026-02-04 00:11:19 +05:00
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 ;
}
2026-02-10 13:03:46 +05:00
function patchRoutesImpl ( routeId , children , routesToUse , manifest , mapRouteProperties2 ) {
var _childrenToPatch ;
2026-02-04 00:11:19 +05:00
let childrenToPatch ;
if ( routeId ) {
let route = manifest [ routeId ] ;
2026-02-10 13:03:46 +05:00
invariant ( route , "No route found to patch children into: routeId = " + routeId ) ;
2026-02-04 00:11:19 +05:00
if ( ! route . children ) {
route . children = [ ] ;
}
childrenToPatch = route . children ;
} else {
childrenToPatch = routesToUse ;
}
2026-02-10 13:03:46 +05:00
let uniqueChildren = children . filter ( ( newRoute ) => ! childrenToPatch . some ( ( existingRoute ) => isSameRoute ( newRoute , existingRoute ) ) ) ;
let newRoutes = convertRoutesToDataRoutes ( uniqueChildren , mapRouteProperties2 , [ routeId || "_" , "patch" , String ( ( ( _childrenToPatch = childrenToPatch ) == null ? void 0 : _childrenToPatch . length ) || "0" ) ] , manifest ) ;
childrenToPatch . push ( ... newRoutes ) ;
2026-02-04 00:11:19 +05:00
}
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 ;
}
2026-02-10 13:03:46 +05:00
return newRoute . children . every ( ( aChild , i ) => {
var _existingRoute$childr ;
return ( _existingRoute$childr = existingRoute . children ) == null ? void 0 : _existingRoute$childr . some ( ( bChild ) => isSameRoute ( aChild , bChild ) ) ;
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function loadLazyRouteModule ( route , mapRouteProperties2 , manifest ) {
if ( ! route . lazy ) {
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
let lazyRoute = await route . lazy ( ) ;
if ( ! route . lazy ) {
2026-02-04 00:11:19 +05:00
return ;
}
let routeToUpdate = manifest [ route . id ] ;
invariant ( routeToUpdate , "No route found in manifest" ) ;
2026-02-10 13:03:46 +05:00
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 , _extends ( { } , mapRouteProperties2 ( routeToUpdate ) , {
lazy : void 0
} ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function defaultDataStrategy ( _ref4 ) {
let {
matches
} = _ref4 ;
let matchesToLoad = matches . filter ( ( m ) => m . shouldLoad ) ;
2026-02-04 00:11:19 +05:00
let results = await Promise . all ( matchesToLoad . map ( ( m ) => m . resolve ( ) ) ) ;
2026-02-10 13:03:46 +05:00
return results . reduce ( ( acc , result , i ) => Object . assign ( acc , {
[ matchesToLoad [ i ] . route . id ] : result
} ) , { } ) ;
}
async function callDataStrategyImpl ( dataStrategyImpl , type , state , request , matchesToLoad , matches , fetcherKey , manifest , mapRouteProperties2 , requestContext ) {
let loadRouteDefinitionsPromises = matches . map ( ( m ) => m . route . lazy ? loadLazyRouteModule ( m . route , mapRouteProperties2 , manifest ) : void 0 ) ;
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 , requestContext ) : Promise . resolve ( {
type : ResultType . data ,
result : void 0
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
} ;
return _extends ( { } , match , {
shouldLoad ,
resolve
} ) ;
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
let results = await dataStrategyImpl ( {
matches : dsMatches ,
2026-02-04 00:11:19 +05:00
request ,
params : matches [ 0 ] . params ,
fetcherKey ,
2026-02-10 13:03:46 +05:00
context : requestContext
2026-02-04 00:11:19 +05:00
} ) ;
try {
2026-02-10 13:03:46 +05:00
await Promise . all ( loadRouteDefinitionsPromises ) ;
2026-02-04 00:11:19 +05:00
} catch ( e ) {
}
return results ;
}
2026-02-10 13:03:46 +05:00
async function callLoaderOrAction ( type , request , match , loadRoutePromise , handlerOverride , staticContext ) {
2026-02-04 00:11:19 +05:00
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" ) {
2026-02-10 13:03:46 +05:00
return Promise . reject ( new Error ( "You cannot call the handler for a route which defines a boolean " + ( '"' + type + '" [routeId: ' + match . route . id + "]" ) ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return handler ( {
request ,
params : match . params ,
context : staticContext
} , ... ctx !== void 0 ? [ ctx ] : [ ] ) ;
2026-02-04 00:11:19 +05:00
} ;
let handlerPromise = ( async ( ) => {
try {
let val = await ( handlerOverride ? handlerOverride ( ( ctx ) => actualHandler ( ctx ) ) : actualHandler ( ) ) ;
2026-02-10 13:03:46 +05:00
return {
type : "data" ,
result : val
} ;
2026-02-04 00:11:19 +05:00
} catch ( e ) {
2026-02-10 13:03:46 +05:00
return {
type : "error" ,
result : e
} ;
2026-02-04 00:11:19 +05:00
}
} ) ( ) ;
return Promise . race ( [ handlerPromise , abortPromise ] ) ;
} ;
try {
2026-02-10 13:03:46 +05:00
let handler = match . route [ type ] ;
if ( loadRoutePromise ) {
2026-02-04 00:11:19 +05:00
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 ;
} ) ,
2026-02-10 13:03:46 +05:00
loadRoutePromise
2026-02-04 00:11:19 +05:00
] ) ;
if ( handlerError !== void 0 ) {
throw handlerError ;
}
result = value ;
} else {
2026-02-10 13:03:46 +05:00
await loadRoutePromise ;
handler = match . route [ type ] ;
if ( handler ) {
result = await runHandler ( handler ) ;
2026-02-04 00:11:19 +05:00
} 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 {
2026-02-10 13:03:46 +05:00
return {
type : ResultType . data ,
result : void 0
} ;
2026-02-04 00:11:19 +05:00
}
}
} else if ( ! handler ) {
let url = new URL ( request . url ) ;
let pathname = url . pathname + url . search ;
throw getInternalRouterError ( 404 , {
pathname
} ) ;
} else {
result = await runHandler ( handler ) ;
}
2026-02-10 13:03:46 +05:00
invariant ( result . result !== void 0 , "You defined " + ( type === "action" ? "an action" : "a loader" ) + " for route " + ( '"' + match . route . id + "\" but didn't return anything from your `" + type + "` " ) + "function. Please return a value or `null`." ) ;
2026-02-04 00:11:19 +05:00
} catch ( e ) {
2026-02-10 13:03:46 +05:00
return {
type : ResultType . error ,
result : e
} ;
2026-02-04 00:11:19 +05:00
} finally {
if ( onReject ) {
request . signal . removeEventListener ( "abort" , onReject ) ;
}
}
return result ;
}
async function convertDataStrategyResultToDataResult ( dataStrategyResult ) {
2026-02-10 13:03:46 +05:00
let {
result ,
type
} = dataStrategyResult ;
2026-02-04 00:11:19 +05:00
if ( isResponse ( result ) ) {
2026-02-10 13:03:46 +05:00
let data ;
2026-02-04 00:11:19 +05:00
try {
2026-02-10 13:03:46 +05:00
let contentType = result . headers . get ( "Content-Type" ) ;
if ( contentType && /\bapplication\/json\b/ . test ( contentType ) ) {
if ( result . body == null ) {
data = null ;
} else {
data = await result . json ( ) ;
}
} else {
data = await result . text ( ) ;
}
2026-02-04 00:11:19 +05:00
} catch ( e ) {
2026-02-10 13:03:46 +05:00
return {
type : ResultType . error ,
error : e
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( type === ResultType . error ) {
2026-02-04 00:11:19 +05:00
return {
2026-02-10 13:03:46 +05:00
type : ResultType . error ,
error : new ErrorResponseImpl ( result . status , result . statusText , data ) ,
2026-02-04 00:11:19 +05:00
statusCode : result . status ,
headers : result . headers
} ;
}
return {
2026-02-10 13:03:46 +05:00
type : ResultType . data ,
data ,
2026-02-04 00:11:19 +05:00
statusCode : result . status ,
headers : result . headers
} ;
}
2026-02-10 13:03:46 +05:00
if ( type === ResultType . error ) {
2026-02-04 00:11:19 +05:00
if ( isDataWithResponseInit ( result ) ) {
2026-02-10 13:03:46 +05:00
var _result$init3 , _result$init4 ;
2026-02-04 00:11:19 +05:00
if ( result . data instanceof Error ) {
2026-02-10 13:03:46 +05:00
var _result$init , _result$init2 ;
2026-02-04 00:11:19 +05:00
return {
2026-02-10 13:03:46 +05:00
type : ResultType . error ,
2026-02-04 00:11:19 +05:00
error : result . data ,
2026-02-10 13:03:46 +05:00
statusCode : ( _result$init = result . init ) == null ? void 0 : _result$init . status ,
headers : ( _result$init2 = result . init ) != null && _result$init2 . headers ? new Headers ( result . init . headers ) : void 0
2026-02-04 00:11:19 +05:00
} ;
}
return {
2026-02-10 13:03:46 +05:00
type : ResultType . error ,
error : new ErrorResponseImpl ( ( ( _result$init3 = result . init ) == null ? void 0 : _result$init3 . status ) || 500 , void 0 , result . data ) ,
2026-02-04 00:11:19 +05:00
statusCode : isRouteErrorResponse ( result ) ? result . status : void 0 ,
2026-02-10 13:03:46 +05:00
headers : ( _result$init4 = result . init ) != null && _result$init4 . headers ? new Headers ( result . init . headers ) : void 0
2026-02-04 00:11:19 +05:00
} ;
}
return {
2026-02-10 13:03:46 +05:00
type : ResultType . error ,
2026-02-04 00:11:19 +05:00
error : result ,
statusCode : isRouteErrorResponse ( result ) ? result . status : void 0
} ;
}
2026-02-10 13:03:46 +05:00
if ( isDeferredData ( result ) ) {
var _result$init5 , _result$init6 ;
return {
type : ResultType . deferred ,
deferredData : result ,
statusCode : ( _result$init5 = result . init ) == null ? void 0 : _result$init5 . status ,
headers : ( ( _result$init6 = result . init ) == null ? void 0 : _result$init6 . headers ) && new Headers ( result . init . headers )
} ;
}
2026-02-04 00:11:19 +05:00
if ( isDataWithResponseInit ( result ) ) {
2026-02-10 13:03:46 +05:00
var _result$init7 , _result$init8 ;
2026-02-04 00:11:19 +05:00
return {
2026-02-10 13:03:46 +05:00
type : ResultType . data ,
2026-02-04 00:11:19 +05:00
data : result . data ,
2026-02-10 13:03:46 +05:00
statusCode : ( _result$init7 = result . init ) == null ? void 0 : _result$init7 . status ,
headers : ( _result$init8 = result . init ) != null && _result$init8 . headers ? new Headers ( result . init . headers ) : void 0
2026-02-04 00:11:19 +05:00
} ;
}
2026-02-10 13:03:46 +05:00
return {
type : ResultType . data ,
data : result
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function normalizeRelativeRoutingRedirectResponse ( response , request , routeId , matches , basename , v7 _relativeSplatPath ) {
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 , true , location , v7 _relativeSplatPath ) ;
response . headers . set ( "Location" , location ) ;
2026-02-04 00:11:19 +05:00
}
return response ;
}
2026-02-10 13:03:46 +05:00
function normalizeRedirectLocation ( location , currentUrl , basename , historyInstance ) {
2026-02-04 00:11:19 +05:00
let invalidProtocols = [
"about:" ,
"blob:" ,
"chrome:" ,
"chrome-untrusted:" ,
"content:" ,
"data:" ,
"devtools:" ,
"file:" ,
"filesystem:" ,
// eslint-disable-next-line no-script-url
"javascript:"
] ;
2026-02-10 13:03:46 +05:00
if ( ABSOLUTE _URL _REGEX . test ( location ) ) {
let normalizedLocation = location ;
2026-02-04 00:11:19 +05:00
let url = normalizedLocation . startsWith ( "//" ) ? new URL ( currentUrl . protocol + normalizedLocation ) : new URL ( normalizedLocation ) ;
if ( invalidProtocols . includes ( url . protocol ) ) {
throw new Error ( "Invalid redirect location" ) ;
}
let isSameBasename = stripBasename ( url . pathname , basename ) != null ;
if ( url . origin === currentUrl . origin && isSameBasename ) {
return url . pathname + url . search + url . hash ;
}
}
try {
2026-02-10 13:03:46 +05:00
let url = historyInstance . createURL ( location ) ;
2026-02-04 00:11:19 +05:00
if ( invalidProtocols . includes ( url . protocol ) ) {
throw new Error ( "Invalid redirect location" ) ;
}
} catch ( e ) {
}
2026-02-10 13:03:46 +05:00
return location ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function createClientSideRequest ( history , location , signal , submission ) {
let url = history . createURL ( stripHashFromPath ( location ) ) . toString ( ) ;
let init = {
signal
} ;
2026-02-04 00:11:19 +05:00
if ( submission && isMutationMethod ( submission . formMethod ) ) {
2026-02-10 13:03:46 +05:00
let {
formMethod ,
formEncType
} = submission ;
2026-02-04 00:11:19 +05:00
init . method = formMethod . toUpperCase ( ) ;
if ( formEncType === "application/json" ) {
2026-02-10 13:03:46 +05:00
init . headers = new Headers ( {
"Content-Type" : formEncType
} ) ;
2026-02-04 00:11:19 +05:00
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 ;
}
2026-02-10 13:03:46 +05:00
function processRouteLoaderData ( matches , results , pendingActionResult , activeDeferreds , skipLoaderErrorBubbling ) {
2026-02-04 00:11:19 +05:00
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 ] ;
2026-02-10 13:03:46 +05:00
invariant ( ! isRedirectResult ( result ) , "Cannot handle redirect results in processLoaderData" ) ;
2026-02-04 00:11:19 +05:00
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 ;
}
}
2026-02-10 13:03:46 +05:00
loaderData [ id ] = void 0 ;
2026-02-04 00:11:19 +05:00
if ( ! foundError ) {
foundError = true ;
statusCode = isRouteErrorResponse ( result . error ) ? result . error . status : 500 ;
}
if ( result . headers ) {
loaderHeaders [ id ] = result . headers ;
}
} else {
2026-02-10 13:03:46 +05:00
if ( isDeferredResult ( result ) ) {
activeDeferreds . set ( id , result . deferredData ) ;
loaderData [ id ] = result . deferredData . data ;
if ( result . statusCode != null && result . statusCode !== 200 && ! foundError ) {
statusCode = result . statusCode ;
}
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 ;
}
2026-02-04 00:11:19 +05:00
}
}
} ) ;
if ( pendingError !== void 0 && pendingActionResult ) {
2026-02-10 13:03:46 +05:00
errors = {
[ pendingActionResult [ 0 ] ] : pendingError
} ;
loaderData [ pendingActionResult [ 0 ] ] = void 0 ;
2026-02-04 00:11:19 +05:00
}
return {
loaderData ,
errors ,
statusCode : statusCode || 200 ,
loaderHeaders
} ;
}
2026-02-10 13:03:46 +05:00
function processLoaderData ( state , matches , results , pendingActionResult , revalidatingFetchers , fetcherResults , activeDeferreds ) {
let {
loaderData ,
errors
} = processRouteLoaderData (
2026-02-04 00:11:19 +05:00
matches ,
results ,
2026-02-10 13:03:46 +05:00
pendingActionResult ,
activeDeferreds ,
false
// This method is only called client side so we always want to bubble
2026-02-04 00:11:19 +05:00
) ;
2026-02-10 13:03:46 +05:00
revalidatingFetchers . forEach ( ( rf ) => {
let {
key ,
match ,
controller
} = rf ;
2026-02-04 00:11:19 +05:00
let result = fetcherResults [ key ] ;
invariant ( result , "Did not find corresponding fetcher result" ) ;
2026-02-10 13:03:46 +05:00
if ( controller && controller . signal . aborted ) {
return ;
} else if ( isErrorResult ( result ) ) {
2026-02-04 00:11:19 +05:00
let boundaryMatch = findNearestBoundary ( state . matches , match == null ? void 0 : match . route . id ) ;
if ( ! ( errors && errors [ boundaryMatch . route . id ] ) ) {
2026-02-10 13:03:46 +05:00
errors = _extends ( { } , errors , {
2026-02-04 00:11:19 +05:00
[ boundaryMatch . route . id ] : result . error
2026-02-10 13:03:46 +05:00
} ) ;
2026-02-04 00:11:19 +05:00
}
state . fetchers . delete ( key ) ;
} else if ( isRedirectResult ( result ) ) {
invariant ( false , "Unhandled fetcher revalidation redirect" ) ;
2026-02-10 13:03:46 +05:00
} else if ( isDeferredResult ( result ) ) {
invariant ( false , "Unhandled fetcher deferred data" ) ;
2026-02-04 00:11:19 +05:00
} else {
let doneFetcher = getDoneFetcher ( result . data ) ;
state . fetchers . set ( key , doneFetcher ) ;
}
} ) ;
2026-02-10 13:03:46 +05:00
return {
loaderData ,
errors
} ;
2026-02-04 00:11:19 +05:00
}
function mergeLoaderData ( loaderData , newLoaderData , matches , errors ) {
2026-02-10 13:03:46 +05:00
let mergedLoaderData = _extends ( { } , newLoaderData ) ;
2026-02-04 00:11:19 +05:00
for ( let match of matches ) {
let id = match . route . id ;
2026-02-10 13:03:46 +05:00
if ( newLoaderData . hasOwnProperty ( id ) ) {
if ( newLoaderData [ id ] !== void 0 ) {
mergedLoaderData [ id ] = newLoaderData [ id ] ;
}
} else if ( loaderData [ id ] !== void 0 && match . route . loader ) {
2026-02-04 00:11:19 +05:00
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 === "/" ) || {
2026-02-10 13:03:46 +05:00
id : "__shim-error-route__"
2026-02-04 00:11:19 +05:00
} ;
return {
2026-02-10 13:03:46 +05:00
matches : [ {
params : { } ,
pathname : "" ,
pathnameBase : "" ,
route
} ] ,
2026-02-04 00:11:19 +05:00
route
} ;
}
2026-02-10 13:03:46 +05:00
function getInternalRouterError ( status , _temp5 ) {
let {
pathname ,
routeId ,
method ,
type ,
message
} = _temp5 === void 0 ? { } : _temp5 ;
2026-02-04 00:11:19 +05:00
let statusText = "Unknown Server Error" ;
let errorMessage = "Unknown @remix-run/router error" ;
if ( status === 400 ) {
statusText = "Bad Request" ;
if ( method && pathname && routeId ) {
2026-02-10 13:03:46 +05:00
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 === "defer-action" ) {
errorMessage = "defer() is not supported in actions" ;
2026-02-04 00:11:19 +05:00
} else if ( type === "invalid-body" ) {
errorMessage = "Unable to encode submission body" ;
}
} else if ( status === 403 ) {
statusText = "Forbidden" ;
2026-02-10 13:03:46 +05:00
errorMessage = 'Route "' + routeId + '" does not match URL "' + pathname + '"' ;
2026-02-04 00:11:19 +05:00
} else if ( status === 404 ) {
statusText = "Not Found" ;
2026-02-10 13:03:46 +05:00
errorMessage = 'No route matches URL "' + pathname + '"' ;
2026-02-04 00:11:19 +05:00
} else if ( status === 405 ) {
statusText = "Method Not Allowed" ;
if ( method && pathname && routeId ) {
2026-02-10 13:03:46 +05:00
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." ;
2026-02-04 00:11:19 +05:00
} else if ( method ) {
2026-02-10 13:03:46 +05:00
errorMessage = 'Invalid request method "' + method . toUpperCase ( ) + '"' ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
return new ErrorResponseImpl ( status || 500 , statusText , new Error ( errorMessage ) , true ) ;
2026-02-04 00:11:19 +05:00
}
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 ) ) {
2026-02-10 13:03:46 +05:00
return {
key ,
result
} ;
2026-02-04 00:11:19 +05:00
}
}
}
function stripHashFromPath ( path ) {
let parsedPath = typeof path === "string" ? parsePath ( path ) : path ;
2026-02-10 13:03:46 +05:00
return createPath ( _extends ( { } , parsedPath , {
hash : ""
} ) ) ;
2026-02-04 00:11:19 +05:00
}
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 ;
}
2026-02-10 13:03:46 +05:00
function isRedirectDataStrategyResultResult ( result ) {
2026-02-04 00:11:19 +05:00
return isResponse ( result . result ) && redirectStatusCodes . has ( result . result . status ) ;
}
2026-02-10 13:03:46 +05:00
function isDeferredResult ( result ) {
return result . type === ResultType . deferred ;
}
2026-02-04 00:11:19 +05:00
function isErrorResult ( result ) {
2026-02-10 13:03:46 +05:00
return result . type === ResultType . error ;
2026-02-04 00:11:19 +05:00
}
function isRedirectResult ( result ) {
2026-02-10 13:03:46 +05:00
return ( result && result . type ) === ResultType . redirect ;
2026-02-04 00:11:19 +05:00
}
function isDataWithResponseInit ( value ) {
return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value . type === "DataWithResponseInit" ;
}
2026-02-10 13:03:46 +05:00
function isDeferredData ( value ) {
let deferred = value ;
return deferred && typeof deferred === "object" && typeof deferred . data === "object" && typeof deferred . subscribe === "function" && typeof deferred . cancel === "function" && typeof deferred . resolveData === "function" ;
}
2026-02-04 00:11:19 +05:00
function isResponse ( value ) {
return value != null && typeof value . status === "number" && typeof value . statusText === "string" && typeof value . headers === "object" && typeof value . body !== "undefined" ;
}
function isValidMethod ( method ) {
2026-02-10 13:03:46 +05:00
return validRequestMethods . has ( method . toLowerCase ( ) ) ;
2026-02-04 00:11:19 +05:00
}
function isMutationMethod ( method ) {
2026-02-10 13:03:46 +05:00
return validMutationMethods . has ( method . toLowerCase ( ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function resolveNavigationDeferredResults ( matches , results , signal , currentMatches , currentLoaderData ) {
let entries = Object . entries ( results ) ;
for ( let index = 0 ; index < entries . length ; index ++ ) {
let [ routeId , result ] = entries [ index ] ;
let match = matches . find ( ( m ) => ( m == null ? void 0 : m . route . id ) === routeId ) ;
if ( ! match ) {
continue ;
}
let currentMatch = currentMatches . find ( ( m ) => m . route . id === match . route . id ) ;
let isRevalidatingLoader = currentMatch != null && ! isNewRouteInstance ( currentMatch , match ) && ( currentLoaderData && currentLoaderData [ match . route . id ] ) !== void 0 ;
if ( isDeferredResult ( result ) && isRevalidatingLoader ) {
await resolveDeferredData ( result , signal , false ) . then ( ( result2 ) => {
if ( result2 ) {
results [ routeId ] = result2 ;
}
} ) ;
}
}
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
async function resolveFetcherDeferredResults ( matches , results , revalidatingFetchers ) {
for ( let index = 0 ; index < revalidatingFetchers . length ; index ++ ) {
let {
key ,
routeId ,
controller
} = revalidatingFetchers [ index ] ;
let result = results [ key ] ;
let match = matches . find ( ( m ) => ( m == null ? void 0 : m . route . id ) === routeId ) ;
if ( ! match ) {
continue ;
}
if ( isDeferredResult ( result ) ) {
invariant ( controller , "Expected an AbortController for revalidating fetcher deferred result" ) ;
await resolveDeferredData ( result , controller . signal , true ) . then ( ( result2 ) => {
if ( result2 ) {
results [ key ] = result2 ;
}
} ) ;
}
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
async function resolveDeferredData ( result , signal , unwrap ) {
if ( unwrap === void 0 ) {
unwrap = false ;
}
let aborted = await result . deferredData . resolveData ( signal ) ;
if ( aborted ) {
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
if ( unwrap ) {
try {
return {
type : ResultType . data ,
data : result . deferredData . unwrappedData
} ;
} catch ( e ) {
return {
type : ResultType . error ,
error : e
} ;
}
}
return {
type : ResultType . data ,
data : result . deferredData . data
} ;
}
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 : json3
} = navigation ;
if ( ! formMethod || ! formAction || ! formEncType ) {
return ;
}
if ( text != null ) {
2026-02-04 00:11:19 +05:00
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
} ;
2026-02-10 13:03:46 +05:00
} else if ( json3 !== void 0 ) {
2026-02-04 00:11:19 +05:00
return {
formMethod ,
formAction ,
formEncType ,
formData : void 0 ,
2026-02-10 13:03:46 +05:00
json : json3 ,
2026-02-04 00:11:19 +05:00
text : void 0
} ;
}
}
2026-02-10 13:03:46 +05:00
function getLoadingNavigation ( location , submission ) {
2026-02-04 00:11:19 +05:00
if ( submission ) {
let navigation = {
state : "loading" ,
2026-02-10 13:03:46 +05:00
location ,
2026-02-04 00:11:19 +05:00
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" ,
2026-02-10 13:03:46 +05:00
location ,
2026-02-04 00:11:19 +05:00
formMethod : void 0 ,
formAction : void 0 ,
formEncType : void 0 ,
formData : void 0 ,
json : void 0 ,
text : void 0
} ;
return navigation ;
}
}
2026-02-10 13:03:46 +05:00
function getSubmittingNavigation ( location , submission ) {
2026-02-04 00:11:19 +05:00
let navigation = {
state : "submitting" ,
2026-02-10 13:03:46 +05:00
location ,
2026-02-04 00:11:19 +05:00
formMethod : submission . formMethod ,
formAction : submission . formAction ,
formEncType : submission . formEncType ,
formData : submission . formData ,
json : submission . json ,
text : submission . text
} ;
return navigation ;
}
2026-02-10 13:03:46 +05:00
function getLoadingFetcher ( submission , data ) {
2026-02-04 00:11:19 +05:00
if ( submission ) {
let fetcher = {
state : "loading" ,
formMethod : submission . formMethod ,
formAction : submission . formAction ,
formEncType : submission . formEncType ,
formData : submission . formData ,
json : submission . json ,
text : submission . text ,
2026-02-10 13:03:46 +05:00
data
2026-02-04 00:11:19 +05:00
} ;
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 ,
2026-02-10 13:03:46 +05:00
data
2026-02-04 00:11:19 +05:00
} ;
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 ;
}
2026-02-10 13:03:46 +05:00
function getDoneFetcher ( data ) {
2026-02-04 00:11:19 +05:00
let fetcher = {
state : "idle" ,
formMethod : void 0 ,
formAction : void 0 ,
formEncType : void 0 ,
formData : void 0 ,
json : void 0 ,
text : void 0 ,
2026-02-10 13:03:46 +05:00
data
2026-02-04 00:11:19 +05:00
} ;
return fetcher ;
}
function restoreAppliedTransitions ( _window , transitions ) {
try {
2026-02-10 13:03:46 +05:00
let sessionPositions = _window . sessionStorage . getItem ( TRANSITIONS _STORAGE _KEY ) ;
2026-02-04 00:11:19 +05:00
if ( sessionPositions ) {
2026-02-10 13:03:46 +05:00
let json3 = JSON . parse ( sessionPositions ) ;
for ( let [ k , v ] of Object . entries ( json3 || { } ) ) {
2026-02-04 00:11:19 +05:00
if ( v && Array . isArray ( v ) ) {
transitions . set ( k , new Set ( v || [ ] ) ) ;
}
}
}
} catch ( e ) {
}
}
function persistAppliedTransitions ( _window , transitions ) {
if ( transitions . size > 0 ) {
2026-02-10 13:03:46 +05:00
let json3 = { } ;
2026-02-04 00:11:19 +05:00
for ( let [ k , v ] of transitions ) {
2026-02-10 13:03:46 +05:00
json3 [ k ] = [ ... v ] ;
2026-02-04 00:11:19 +05:00
}
try {
2026-02-10 13:03:46 +05:00
_window . sessionStorage . setItem ( TRANSITIONS _STORAGE _KEY , JSON . stringify ( json3 ) ) ;
2026-02-04 00:11:19 +05:00
} catch ( error ) {
2026-02-10 13:03:46 +05:00
warning ( false , "Failed to save applied view transitions in sessionStorage (" + error + ")." ) ;
2026-02-04 00:11:19 +05:00
}
}
}
2026-02-10 13:03:46 +05:00
// node_modules/react-router/dist/index.js
function _extends2 ( ) {
_extends2 = Object . assign ? Object . assign . bind ( ) : function ( target ) {
for ( var i = 1 ; i < arguments . length ; i ++ ) {
var source = arguments [ i ] ;
for ( var key in source ) {
if ( Object . prototype . hasOwnProperty . call ( source , key ) ) {
target [ key ] = source [ key ] ;
}
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
}
return target ;
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
return _extends2 . apply ( this , arguments ) ;
2026-02-04 00:11:19 +05:00
}
var DataRouterContext = React . createContext ( null ) ;
2026-02-10 13:03:46 +05:00
if ( true ) {
DataRouterContext . displayName = "DataRouter" ;
}
2026-02-04 00:11:19 +05:00
var DataRouterStateContext = React . createContext ( null ) ;
2026-02-10 13:03:46 +05:00
if ( true ) {
DataRouterStateContext . displayName = "DataRouterState" ;
2026-02-04 00:11:19 +05:00
}
var AwaitContext = React . createContext ( null ) ;
2026-02-10 13:03:46 +05:00
if ( true ) {
AwaitContext . displayName = "Await" ;
}
var NavigationContext = React . createContext ( null ) ;
if ( true ) {
NavigationContext . displayName = "Navigation" ;
}
var LocationContext = React . createContext ( null ) ;
if ( true ) {
LocationContext . displayName = "Location" ;
}
2026-02-04 00:11:19 +05:00
var RouteContext = React . createContext ( {
outlet : null ,
matches : [ ] ,
isDataRoute : false
} ) ;
2026-02-10 13:03:46 +05:00
if ( true ) {
RouteContext . displayName = "Route" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var RouteErrorContext = React . createContext ( null ) ;
if ( true ) {
RouteErrorContext . displayName = "RouteError" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useHref ( to , _temp ) {
let {
relative
} = _temp === void 0 ? { } : _temp ;
! useInRouterContext ( ) ? true ? invariant (
false ,
2026-02-04 00:11:19 +05:00
// TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
2026-02-10 13:03:46 +05:00
"useHref() may be used only in the context of a <Router> component."
) : invariant ( false ) : void 0 ;
let {
basename ,
navigator
} = React . useContext ( NavigationContext ) ;
let {
hash ,
pathname ,
search
} = useResolvedPath ( to , {
relative
} ) ;
2026-02-04 00:11:19 +05:00
let joinedPathname = pathname ;
if ( basename !== "/" ) {
joinedPathname = pathname === "/" ? basename : joinPaths ( [ basename , pathname ] ) ;
}
2026-02-10 13:03:46 +05:00
return navigator . createHref ( {
pathname : joinedPathname ,
search ,
hash
} ) ;
2026-02-04 00:11:19 +05:00
}
function useInRouterContext ( ) {
2026-02-10 13:03:46 +05:00
return React . useContext ( LocationContext ) != null ;
2026-02-04 00:11:19 +05:00
}
function useLocation ( ) {
2026-02-10 13:03:46 +05:00
! useInRouterContext ( ) ? true ? invariant (
false ,
2026-02-04 00:11:19 +05:00
// TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
2026-02-10 13:03:46 +05:00
"useLocation() may be used only in the context of a <Router> component."
) : invariant ( false ) : void 0 ;
return React . useContext ( LocationContext ) . location ;
2026-02-04 00:11:19 +05:00
}
function useNavigationType ( ) {
2026-02-10 13:03:46 +05:00
return React . useContext ( LocationContext ) . navigationType ;
2026-02-04 00:11:19 +05:00
}
function useMatch ( pattern ) {
2026-02-10 13:03:46 +05:00
! useInRouterContext ( ) ? true ? invariant (
false ,
2026-02-04 00:11:19 +05:00
// TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
2026-02-10 13:03:46 +05:00
"useMatch() may be used only in the context of a <Router> component."
) : invariant ( false ) : void 0 ;
let {
pathname
} = useLocation ( ) ;
return React . useMemo ( ( ) => matchPath ( pattern , decodePath ( pathname ) ) , [ pathname , pattern ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var navigateEffectWarning = "You should call navigate() in a React.useEffect(), not when your component is first rendered." ;
2026-02-04 00:11:19 +05:00
function useIsomorphicLayoutEffect ( cb ) {
2026-02-10 13:03:46 +05:00
let isStatic = React . useContext ( NavigationContext ) . static ;
2026-02-04 00:11:19 +05:00
if ( ! isStatic ) {
2026-02-10 13:03:46 +05:00
React . useLayoutEffect ( cb ) ;
2026-02-04 00:11:19 +05:00
}
}
function useNavigate ( ) {
2026-02-10 13:03:46 +05:00
let {
isDataRoute
} = React . useContext ( RouteContext ) ;
2026-02-04 00:11:19 +05:00
return isDataRoute ? useNavigateStable ( ) : useNavigateUnstable ( ) ;
}
function useNavigateUnstable ( ) {
2026-02-10 13:03:46 +05:00
! useInRouterContext ( ) ? true ? invariant (
false ,
2026-02-04 00:11:19 +05:00
// TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
2026-02-10 13:03:46 +05:00
"useNavigate() may be used only in the context of a <Router> component."
) : invariant ( false ) : void 0 ;
let dataRouterContext = React . useContext ( DataRouterContext ) ;
let {
basename ,
future ,
navigator
} = React . useContext ( NavigationContext ) ;
let {
matches
} = React . useContext ( RouteContext ) ;
let {
pathname : locationPathname
} = useLocation ( ) ;
let routePathnamesJson = JSON . stringify ( getResolveToMatches ( matches , future . v7 _relativeSplatPath ) ) ;
let activeRef = React . useRef ( false ) ;
2026-02-04 00:11:19 +05:00
useIsomorphicLayoutEffect ( ( ) => {
activeRef . current = true ;
} ) ;
2026-02-10 13:03:46 +05:00
let navigate = React . useCallback ( function ( to , options ) {
if ( options === void 0 ) {
options = { } ;
}
true ? warning ( activeRef . current , navigateEffectWarning ) : void 0 ;
if ( ! activeRef . current ) return ;
if ( typeof to === "number" ) {
navigator . 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 ? navigator . replace : navigator . push ) ( path , options . state , options ) ;
} , [ basename , navigator , routePathnamesJson , locationPathname , dataRouterContext ] ) ;
2026-02-04 00:11:19 +05:00
return navigate ;
}
2026-02-10 13:03:46 +05:00
var OutletContext = React . createContext ( null ) ;
2026-02-04 00:11:19 +05:00
function useOutletContext ( ) {
2026-02-10 13:03:46 +05:00
return React . useContext ( OutletContext ) ;
2026-02-04 00:11:19 +05:00
}
function useOutlet ( context ) {
2026-02-10 13:03:46 +05:00
let outlet = React . useContext ( RouteContext ) . outlet ;
if ( outlet ) {
return React . createElement ( OutletContext . Provider , {
value : context
} , outlet ) ;
}
return outlet ;
2026-02-04 00:11:19 +05:00
}
function useParams ( ) {
2026-02-10 13:03:46 +05:00
let {
matches
} = React . useContext ( RouteContext ) ;
2026-02-04 00:11:19 +05:00
let routeMatch = matches [ matches . length - 1 ] ;
return routeMatch ? routeMatch . params : { } ;
}
2026-02-10 13:03:46 +05:00
function useResolvedPath ( to , _temp2 ) {
let {
relative
} = _temp2 === void 0 ? { } : _temp2 ;
let {
future
} = React . useContext ( NavigationContext ) ;
let {
matches
} = React . useContext ( RouteContext ) ;
let {
pathname : locationPathname
} = useLocation ( ) ;
let routePathnamesJson = JSON . stringify ( getResolveToMatches ( matches , future . v7 _relativeSplatPath ) ) ;
return React . useMemo ( ( ) => resolveTo ( to , JSON . parse ( routePathnamesJson ) , locationPathname , relative === "path" ) , [ to , routePathnamesJson , locationPathname , relative ] ) ;
2026-02-04 00:11:19 +05:00
}
function useRoutes ( routes , locationArg ) {
return useRoutesImpl ( routes , locationArg ) ;
}
2026-02-10 13:03:46 +05:00
function useRoutesImpl ( routes , locationArg , dataRouterState , future ) {
! useInRouterContext ( ) ? true ? invariant (
false ,
2026-02-04 00:11:19 +05:00
// TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
2026-02-10 13:03:46 +05:00
"useRoutes() may be used only in the context of a <Router> component."
) : invariant ( false ) : void 0 ;
let {
navigator
} = React . useContext ( NavigationContext ) ;
let {
matches : parentMatches
} = React . useContext ( RouteContext ) ;
2026-02-04 00:11:19 +05:00
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 ;
2026-02-10 13:03:46 +05:00
if ( true ) {
2026-02-04 00:11:19 +05:00
let parentPath = parentRoute && parentRoute . path || "" ;
2026-02-10 13:03:46 +05:00
warningOnce ( parentPathname , ! parentRoute || parentPath . endsWith ( "*" ) , "You rendered descendant <Routes> (or called `useRoutes()`) at " + ( '"' + parentPathname + '" (under <Route path="' + parentPath + '">) 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.
2026-02-04 00:11:19 +05:00
2026-02-10 13:03:46 +05:00
` + ('Please change the parent <Route path="' + parentPath + '"> to <Route ') + ('path="' + (parentPath === "/" ? "*" : parentPath + "/*") + '">.'));
2026-02-04 00:11:19 +05:00
}
let locationFromContext = useLocation ( ) ;
2026-02-10 13:03:46 +05:00
let location ;
2026-02-04 00:11:19 +05:00
if ( locationArg ) {
2026-02-10 13:03:46 +05:00
var _parsedLocationArg$pa ;
2026-02-04 00:11:19 +05:00
let parsedLocationArg = typeof locationArg === "string" ? parsePath ( locationArg ) : locationArg ;
2026-02-10 13:03:46 +05:00
! ( parentPathnameBase === "/" || ( ( _parsedLocationArg$pa = parsedLocationArg . pathname ) == null ? void 0 : _parsedLocationArg$pa . startsWith ( parentPathnameBase ) ) ) ? true ? invariant ( false , "When overriding the location using `<Routes location>` 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.' ) ) : invariant ( false ) : void 0 ;
location = parsedLocationArg ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
location = locationFromContext ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let pathname = location . pathname || "/" ;
2026-02-04 00:11:19 +05:00
let remainingPathname = pathname ;
if ( parentPathnameBase !== "/" ) {
let parentSegments = parentPathnameBase . replace ( /^\// , "" ) . split ( "/" ) ;
let segments = pathname . replace ( /^\// , "" ) . split ( "/" ) ;
remainingPathname = "/" + segments . slice ( parentSegments . length ) . join ( "/" ) ;
}
2026-02-10 13:03:46 +05:00
let matches = matchRoutes ( routes , {
pathname : remainingPathname
} ) ;
if ( true ) {
true ? warning ( parentRoute || matches != null , 'No routes matched location "' + location . pathname + location . search + location . hash + '" ' ) : void 0 ;
true ? 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 <Outlet /> with a null value by default resulting in an "empty" page.' ) : void 0 ;
}
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
navigator . encodeLocation ? navigator . encodeLocation ( match . pathname ) . pathname : match . pathname
] ) ,
pathnameBase : match . pathnameBase === "/" ? parentPathnameBase : joinPaths ( [
parentPathnameBase ,
// Re-encode pathnames that were decoded inside matchRoutes
navigator . encodeLocation ? navigator . encodeLocation ( match . pathnameBase ) . pathname : match . pathnameBase
] )
} ) ) , parentMatches , dataRouterState , future ) ;
2026-02-04 00:11:19 +05:00
if ( locationArg && renderedMatches ) {
2026-02-10 13:03:46 +05:00
return React . createElement ( LocationContext . Provider , {
value : {
location : _extends2 ( {
pathname : "/" ,
search : "" ,
hash : "" ,
state : null ,
key : "default"
} , location ) ,
navigationType : Action . Pop
}
} , renderedMatches ) ;
2026-02-04 00:11:19 +05:00
}
return renderedMatches ;
}
function DefaultErrorComponent ( ) {
let error = useRouteError ( ) ;
2026-02-10 13:03:46 +05:00
let message = isRouteErrorResponse ( error ) ? error . status + " " + error . statusText : error instanceof Error ? error . message : JSON . stringify ( error ) ;
2026-02-04 00:11:19 +05:00
let stack = error instanceof Error ? error . stack : null ;
let lightgrey = "rgba(200,200,200, 0.5)" ;
2026-02-10 13:03:46 +05:00
let preStyles = {
padding : "0.5rem" ,
backgroundColor : lightgrey
} ;
let codeStyles = {
padding : "2px 4px" ,
backgroundColor : lightgrey
} ;
2026-02-04 00:11:19 +05:00
let devInfo = null ;
2026-02-10 13:03:46 +05:00
if ( true ) {
console . error ( "Error handled by React Router default ErrorBoundary:" , error ) ;
devInfo = React . createElement ( React . Fragment , null , React . createElement ( "p" , null , "💿 Hey developer 👋" ) , React . createElement ( "p" , null , "You can provide a way better UX than this when your app throws errors by providing your own " , React . createElement ( "code" , {
style : codeStyles
} , "ErrorBoundary" ) , " or" , " " , React . createElement ( "code" , {
style : codeStyles
} , "errorElement" ) , " prop on your route." ) ) ;
}
return React . createElement ( React . Fragment , null , React . createElement ( "h2" , null , "Unexpected Application Error!" ) , React . createElement ( "h3" , {
style : {
fontStyle : "italic"
}
} , message ) , stack ? React . createElement ( "pre" , {
style : preStyles
} , stack ) : null , devInfo ) ;
}
var defaultErrorElement = React . createElement ( DefaultErrorComponent , null ) ;
var RenderErrorBoundary = class extends React . Component {
2026-02-04 00:11:19 +05:00
constructor ( props ) {
super ( props ) ;
this . state = {
location : props . location ,
revalidation : props . revalidation ,
error : props . error
} ;
}
static getDerivedStateFromError ( error ) {
2026-02-10 13:03:46 +05:00
return {
error
} ;
2026-02-04 00:11:19 +05:00
}
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 ) {
2026-02-10 13:03:46 +05:00
console . error ( "React Router caught the following error during render" , error , errorInfo ) ;
2026-02-04 00:11:19 +05:00
}
render ( ) {
2026-02-10 13:03:46 +05:00
return this . state . error !== void 0 ? React . createElement ( RouteContext . Provider , {
value : this . props . routeContext
} , React . createElement ( RouteErrorContext . Provider , {
value : this . state . error ,
children : this . props . component
} ) ) : this . props . children ;
2026-02-04 00:11:19 +05:00
}
} ;
2026-02-10 13:03:46 +05:00
function RenderedRoute ( _ref ) {
let {
routeContext ,
match ,
children
} = _ref ;
let dataRouterContext = React . useContext ( DataRouterContext ) ;
2026-02-04 00:11:19 +05:00
if ( dataRouterContext && dataRouterContext . static && dataRouterContext . staticContext && ( match . route . errorElement || match . route . ErrorBoundary ) ) {
dataRouterContext . staticContext . _deepestRenderedBoundaryId = match . route . id ;
}
2026-02-10 13:03:46 +05:00
return React . createElement ( RouteContext . Provider , {
value : routeContext
} , children ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function _renderMatches ( matches , parentMatches , dataRouterState , future ) {
var _dataRouterState ;
if ( parentMatches === void 0 ) {
parentMatches = [ ] ;
}
if ( dataRouterState === void 0 ) {
dataRouterState = null ;
}
if ( future === void 0 ) {
future = null ;
}
2026-02-04 00:11:19 +05:00
if ( matches == null ) {
2026-02-10 13:03:46 +05:00
var _future ;
2026-02-04 00:11:19 +05:00
if ( ! dataRouterState ) {
return null ;
}
if ( dataRouterState . errors ) {
matches = dataRouterState . matches ;
2026-02-10 13:03:46 +05:00
} else if ( ( _future = future ) != null && _future . v7 _partialHydration && parentMatches . length === 0 && ! dataRouterState . initialized && dataRouterState . matches . length > 0 ) {
2026-02-04 00:11:19 +05:00
matches = dataRouterState . matches ;
} else {
return null ;
}
}
let renderedMatches = matches ;
2026-02-10 13:03:46 +05:00
let errors = ( _dataRouterState = dataRouterState ) == null ? void 0 : _dataRouterState . errors ;
2026-02-04 00:11:19 +05:00
if ( errors != null ) {
2026-02-10 13:03:46 +05:00
let errorIndex = renderedMatches . findIndex ( ( m ) => m . route . id && ( errors == null ? void 0 : errors [ m . route . id ] ) !== void 0 ) ;
! ( errorIndex >= 0 ) ? true ? invariant ( false , "Could not find a matching route for errors on route IDs: " + Object . keys ( errors ) . join ( "," ) ) : invariant ( false ) : void 0 ;
renderedMatches = renderedMatches . slice ( 0 , Math . min ( renderedMatches . length , errorIndex + 1 ) ) ;
2026-02-04 00:11:19 +05:00
}
let renderFallback = false ;
let fallbackIndex = - 1 ;
2026-02-10 13:03:46 +05:00
if ( dataRouterState && future && future . v7 _partialHydration ) {
2026-02-04 00:11:19 +05:00
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 ) {
2026-02-10 13:03:46 +05:00
let {
loaderData ,
errors : errors2
} = dataRouterState ;
let needsToRunLoader = match . route . loader && loaderData [ match . route . id ] === void 0 && ( ! errors2 || errors2 [ match . route . id ] === void 0 ) ;
2026-02-04 00:11:19 +05:00
if ( match . route . lazy || needsToRunLoader ) {
renderFallback = true ;
if ( fallbackIndex >= 0 ) {
renderedMatches = renderedMatches . slice ( 0 , fallbackIndex + 1 ) ;
} else {
renderedMatches = [ renderedMatches [ 0 ] ] ;
}
break ;
}
}
}
}
2026-02-10 13:03:46 +05:00
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 = React . createElement ( match . route . Component , null ) ;
} else if ( match . route . element ) {
children = match . route . element ;
} else {
children = outlet ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return React . createElement ( RenderedRoute , {
match ,
routeContext : {
outlet ,
matches : matches2 ,
isDataRoute : dataRouterState != null
} ,
children
} ) ;
} ;
return dataRouterState && ( match . route . ErrorBoundary || match . route . errorElement || index === 0 ) ? React . createElement ( RenderErrorBoundary , {
location : dataRouterState . location ,
revalidation : dataRouterState . revalidation ,
component : errorElement ,
error ,
children : getChildren ( ) ,
routeContext : {
outlet : null ,
matches : matches2 ,
isDataRoute : true
}
} ) : getChildren ( ) ;
} , null ) ;
}
var DataRouterHook = function ( DataRouterHook3 ) {
DataRouterHook3 [ "UseBlocker" ] = "useBlocker" ;
DataRouterHook3 [ "UseRevalidator" ] = "useRevalidator" ;
DataRouterHook3 [ "UseNavigateStable" ] = "useNavigate" ;
return DataRouterHook3 ;
} ( DataRouterHook || { } ) ;
var DataRouterStateHook = function ( DataRouterStateHook3 ) {
DataRouterStateHook3 [ "UseBlocker" ] = "useBlocker" ;
DataRouterStateHook3 [ "UseLoaderData" ] = "useLoaderData" ;
DataRouterStateHook3 [ "UseActionData" ] = "useActionData" ;
DataRouterStateHook3 [ "UseRouteError" ] = "useRouteError" ;
DataRouterStateHook3 [ "UseNavigation" ] = "useNavigation" ;
DataRouterStateHook3 [ "UseRouteLoaderData" ] = "useRouteLoaderData" ;
DataRouterStateHook3 [ "UseMatches" ] = "useMatches" ;
DataRouterStateHook3 [ "UseRevalidator" ] = "useRevalidator" ;
DataRouterStateHook3 [ "UseNavigateStable" ] = "useNavigate" ;
DataRouterStateHook3 [ "UseRouteId" ] = "useRouteId" ;
return DataRouterStateHook3 ;
} ( DataRouterStateHook || { } ) ;
2026-02-04 00:11:19 +05:00
function getDataRouterConsoleError ( hookName ) {
2026-02-10 13:03:46 +05:00
return hookName + " must be used within a data router. See https://reactrouter.com/v6/routers/picking-a-router." ;
2026-02-04 00:11:19 +05:00
}
function useDataRouterContext ( hookName ) {
2026-02-10 13:03:46 +05:00
let ctx = React . useContext ( DataRouterContext ) ;
! ctx ? true ? invariant ( false , getDataRouterConsoleError ( hookName ) ) : invariant ( false ) : void 0 ;
2026-02-04 00:11:19 +05:00
return ctx ;
}
function useDataRouterState ( hookName ) {
2026-02-10 13:03:46 +05:00
let state = React . useContext ( DataRouterStateContext ) ;
! state ? true ? invariant ( false , getDataRouterConsoleError ( hookName ) ) : invariant ( false ) : void 0 ;
2026-02-04 00:11:19 +05:00
return state ;
}
function useRouteContext ( hookName ) {
2026-02-10 13:03:46 +05:00
let route = React . useContext ( RouteContext ) ;
! route ? true ? invariant ( false , getDataRouterConsoleError ( hookName ) ) : invariant ( false ) : void 0 ;
2026-02-04 00:11:19 +05:00
return route ;
}
function useCurrentRouteId ( hookName ) {
let route = useRouteContext ( hookName ) ;
let thisRoute = route . matches [ route . matches . length - 1 ] ;
2026-02-10 13:03:46 +05:00
! thisRoute . route . id ? true ? invariant ( false , hookName + ' can only be used on routes that contain a unique "id"' ) : invariant ( false ) : void 0 ;
2026-02-04 00:11:19 +05:00
return thisRoute . route . id ;
}
function useRouteId ( ) {
2026-02-10 13:03:46 +05:00
return useCurrentRouteId ( DataRouterStateHook . UseRouteId ) ;
2026-02-04 00:11:19 +05:00
}
function useNavigation ( ) {
2026-02-10 13:03:46 +05:00
let state = useDataRouterState ( DataRouterStateHook . UseNavigation ) ;
2026-02-04 00:11:19 +05:00
return state . navigation ;
}
function useRevalidator ( ) {
2026-02-10 13:03:46 +05:00
let dataRouterContext = useDataRouterContext ( DataRouterHook . UseRevalidator ) ;
let state = useDataRouterState ( DataRouterStateHook . UseRevalidator ) ;
return React . useMemo ( ( ) => ( {
revalidate : dataRouterContext . router . revalidate ,
state : state . revalidation
} ) , [ dataRouterContext . router . revalidate , state . revalidation ] ) ;
2026-02-04 00:11:19 +05:00
}
function useMatches ( ) {
2026-02-10 13:03:46 +05:00
let {
matches ,
loaderData
} = useDataRouterState ( DataRouterStateHook . UseMatches ) ;
return React . useMemo ( ( ) => matches . map ( ( m ) => convertRouteMatchToUiMatch ( m , loaderData ) ) , [ matches , loaderData ] ) ;
2026-02-04 00:11:19 +05:00
}
function useLoaderData ( ) {
2026-02-10 13:03:46 +05:00
let state = useDataRouterState ( DataRouterStateHook . UseLoaderData ) ;
let routeId = useCurrentRouteId ( DataRouterStateHook . UseLoaderData ) ;
if ( state . errors && state . errors [ routeId ] != null ) {
console . error ( "You cannot `useLoaderData` in an errorElement (routeId: " + routeId + ")" ) ;
return void 0 ;
}
2026-02-04 00:11:19 +05:00
return state . loaderData [ routeId ] ;
}
function useRouteLoaderData ( routeId ) {
2026-02-10 13:03:46 +05:00
let state = useDataRouterState ( DataRouterStateHook . UseRouteLoaderData ) ;
2026-02-04 00:11:19 +05:00
return state . loaderData [ routeId ] ;
}
function useActionData ( ) {
2026-02-10 13:03:46 +05:00
let state = useDataRouterState ( DataRouterStateHook . UseActionData ) ;
let routeId = useCurrentRouteId ( DataRouterStateHook . UseLoaderData ) ;
2026-02-04 00:11:19 +05:00
return state . actionData ? state . actionData [ routeId ] : void 0 ;
}
function useRouteError ( ) {
2026-02-10 13:03:46 +05:00
var _state$errors ;
let error = React . useContext ( RouteErrorContext ) ;
let state = useDataRouterState ( DataRouterStateHook . UseRouteError ) ;
let routeId = useCurrentRouteId ( DataRouterStateHook . UseRouteError ) ;
2026-02-04 00:11:19 +05:00
if ( error !== void 0 ) {
return error ;
}
2026-02-10 13:03:46 +05:00
return ( _state$errors = state . errors ) == null ? void 0 : _state$errors [ routeId ] ;
2026-02-04 00:11:19 +05:00
}
function useAsyncValue ( ) {
2026-02-10 13:03:46 +05:00
let value = React . useContext ( AwaitContext ) ;
2026-02-04 00:11:19 +05:00
return value == null ? void 0 : value . _data ;
}
function useAsyncError ( ) {
2026-02-10 13:03:46 +05:00
let value = React . useContext ( AwaitContext ) ;
2026-02-04 00:11:19 +05:00
return value == null ? void 0 : value . _error ;
}
var blockerId = 0 ;
function useBlocker ( shouldBlock ) {
2026-02-10 13:03:46 +05:00
let {
router ,
basename
} = useDataRouterContext ( DataRouterHook . UseBlocker ) ;
let state = useDataRouterState ( DataRouterStateHook . UseBlocker ) ;
let [ blockerKey , setBlockerKey ] = React . useState ( "" ) ;
let blockerFunction = React . useCallback ( ( arg ) => {
if ( typeof shouldBlock !== "function" ) {
return ! ! shouldBlock ;
}
if ( basename === "/" ) {
return shouldBlock ( arg ) ;
}
let {
currentLocation ,
nextLocation ,
historyAction
} = arg ;
return shouldBlock ( {
currentLocation : _extends2 ( { } , currentLocation , {
pathname : stripBasename ( currentLocation . pathname , basename ) || currentLocation . pathname
} ) ,
nextLocation : _extends2 ( { } , nextLocation , {
pathname : stripBasename ( nextLocation . pathname , basename ) || nextLocation . pathname
} ) ,
historyAction
} ) ;
} , [ basename , shouldBlock ] ) ;
React . useEffect ( ( ) => {
2026-02-04 00:11:19 +05:00
let key = String ( ++ blockerId ) ;
setBlockerKey ( key ) ;
2026-02-10 13:03:46 +05:00
return ( ) => router . deleteBlocker ( key ) ;
} , [ router ] ) ;
React . useEffect ( ( ) => {
2026-02-04 00:11:19 +05:00
if ( blockerKey !== "" ) {
2026-02-10 13:03:46 +05:00
router . getBlocker ( blockerKey , blockerFunction ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ router , blockerKey , blockerFunction ] ) ;
2026-02-04 00:11:19 +05:00
return blockerKey && state . blockers . has ( blockerKey ) ? state . blockers . get ( blockerKey ) : IDLE _BLOCKER ;
}
function useNavigateStable ( ) {
2026-02-10 13:03:46 +05:00
let {
router
} = useDataRouterContext ( DataRouterHook . UseNavigateStable ) ;
let id = useCurrentRouteId ( DataRouterStateHook . UseNavigateStable ) ;
let activeRef = React . useRef ( false ) ;
2026-02-04 00:11:19 +05:00
useIsomorphicLayoutEffect ( ( ) => {
activeRef . current = true ;
} ) ;
2026-02-10 13:03:46 +05:00
let navigate = React . useCallback ( function ( to , options ) {
if ( options === void 0 ) {
options = { } ;
}
true ? warning ( activeRef . current , navigateEffectWarning ) : void 0 ;
if ( ! activeRef . current ) return ;
if ( typeof to === "number" ) {
router . navigate ( to ) ;
} else {
router . navigate ( to , _extends2 ( {
fromRouteId : id
} , options ) ) ;
}
} , [ router , id ] ) ;
2026-02-04 00:11:19 +05:00
return navigate ;
}
2026-02-10 13:03:46 +05:00
var alreadyWarned$1 = { } ;
2026-02-04 00:11:19 +05:00
function warningOnce ( key , cond , message ) {
2026-02-10 13:03:46 +05:00
if ( ! cond && ! alreadyWarned$1 [ key ] ) {
alreadyWarned$1 [ key ] = true ;
true ? warning ( false , message ) : void 0 ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
var alreadyWarned = { } ;
function warnOnce ( key , message ) {
if ( ! alreadyWarned [ message ] ) {
alreadyWarned [ message ] = true ;
2026-02-04 00:11:19 +05:00
console . warn ( message ) ;
}
}
2026-02-10 13:03:46 +05:00
var logDeprecation = ( flag , msg , link ) => warnOnce ( flag , "⚠️ React Router Future Flag Warning: " + msg + ". " + ( "You can use the `" + flag + "` future flag to opt-in early. " ) + ( "For more information, see " + link + "." ) ) ;
function logV6DeprecationWarnings ( renderFuture , routerFuture ) {
if ( ( renderFuture == null ? void 0 : renderFuture . v7 _startTransition ) === void 0 ) {
logDeprecation ( "v7_startTransition" , "React Router will begin wrapping state updates in `React.startTransition` in v7" , "https://reactrouter.com/v6/upgrading/future#v7_starttransition" ) ;
}
if ( ( renderFuture == null ? void 0 : renderFuture . v7 _relativeSplatPath ) === void 0 && ( ! routerFuture || routerFuture . v7 _relativeSplatPath === void 0 ) ) {
logDeprecation ( "v7_relativeSplatPath" , "Relative route resolution within Splat routes is changing in v7" , "https://reactrouter.com/v6/upgrading/future#v7_relativesplatpath" ) ;
}
if ( routerFuture ) {
if ( routerFuture . v7 _fetcherPersist === void 0 ) {
logDeprecation ( "v7_fetcherPersist" , "The persistence behavior of fetchers is changing in v7" , "https://reactrouter.com/v6/upgrading/future#v7_fetcherpersist" ) ;
}
if ( routerFuture . v7 _normalizeFormMethod === void 0 ) {
logDeprecation ( "v7_normalizeFormMethod" , "Casing of `formMethod` fields is being normalized to uppercase in v7" , "https://reactrouter.com/v6/upgrading/future#v7_normalizeformmethod" ) ;
}
if ( routerFuture . v7 _partialHydration === void 0 ) {
logDeprecation ( "v7_partialHydration" , "`RouterProvider` hydration behavior is changing in v7" , "https://reactrouter.com/v6/upgrading/future#v7_partialhydration" ) ;
}
if ( routerFuture . v7 _skipActionErrorRevalidation === void 0 ) {
logDeprecation ( "v7_skipActionErrorRevalidation" , "The revalidation behavior after 4xx/5xx `action` responses is changing in v7" , "https://reactrouter.com/v6/upgrading/future#v7_skipactionerrorrevalidation" ) ;
}
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
var START _TRANSITION = "startTransition" ;
var startTransitionImpl = React [ START _TRANSITION ] ;
function MemoryRouter ( _ref3 ) {
let {
basename ,
children ,
initialEntries ,
initialIndex ,
future
} = _ref3 ;
let historyRef = React . useRef ( ) ;
2026-02-04 00:11:19 +05:00
if ( historyRef . current == null ) {
historyRef . current = createMemoryHistory ( {
initialEntries ,
initialIndex ,
v5Compat : true
} ) ;
}
let history = historyRef . current ;
2026-02-10 13:03:46 +05:00
let [ state , setStateImpl ] = React . useState ( {
2026-02-04 00:11:19 +05:00
action : history . action ,
location : history . location
} ) ;
2026-02-10 13:03:46 +05:00
let {
v7 _startTransition
} = future || { } ;
let setState = React . useCallback ( ( newState ) => {
v7 _startTransition && startTransitionImpl ? startTransitionImpl ( ( ) => setStateImpl ( newState ) ) : setStateImpl ( newState ) ;
} , [ setStateImpl , v7 _startTransition ] ) ;
React . useLayoutEffect ( ( ) => history . listen ( setState ) , [ history , setState ] ) ;
React . useEffect ( ( ) => logV6DeprecationWarnings ( future ) , [ future ] ) ;
return React . createElement ( Router , {
basename ,
children ,
location : state . location ,
navigationType : state . action ,
navigator : history ,
future
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function Navigate ( _ref4 ) {
let {
to ,
replace : replace2 ,
state ,
relative
} = _ref4 ;
! useInRouterContext ( ) ? true ? invariant (
false ,
2026-02-04 00:11:19 +05:00
// TODO: This error is probably because they somehow have 2 versions of
// the router loaded. We can help them understand how to avoid that.
2026-02-10 13:03:46 +05:00
"<Navigate> may be used only in the context of a <Router> component."
) : invariant ( false ) : void 0 ;
let {
future ,
static : isStatic
} = React . useContext ( NavigationContext ) ;
true ? warning ( ! isStatic , "<Navigate> must not be used on the initial render in a <StaticRouter>. This is a no-op, but you should modify your code so the <Navigate> is only ever rendered in response to some user interaction or state change." ) : void 0 ;
let {
matches
} = React . useContext ( RouteContext ) ;
let {
pathname : locationPathname
} = useLocation ( ) ;
2026-02-04 00:11:19 +05:00
let navigate = useNavigate ( ) ;
2026-02-10 13:03:46 +05:00
let path = resolveTo ( to , getResolveToMatches ( matches , future . v7 _relativeSplatPath ) , locationPathname , relative === "path" ) ;
2026-02-04 00:11:19 +05:00
let jsonPath = JSON . stringify ( path ) ;
2026-02-10 13:03:46 +05:00
React . useEffect ( ( ) => navigate ( JSON . parse ( jsonPath ) , {
replace : replace2 ,
state ,
relative
} ) , [ navigate , jsonPath , relative , replace2 , state ] ) ;
2026-02-04 00:11:19 +05:00
return null ;
}
function Outlet ( props ) {
return useOutlet ( props . context ) ;
}
2026-02-10 13:03:46 +05:00
function Route ( _props ) {
true ? invariant ( false , "A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>." ) : invariant ( false ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function Router ( _ref5 ) {
let {
basename : basenameProp = "/" ,
children = null ,
location : locationProp ,
navigationType = Action . Pop ,
navigator ,
static : staticProp = false ,
future
} = _ref5 ;
! ! useInRouterContext ( ) ? true ? invariant ( false , "You cannot render a <Router> inside another <Router>. You should never have more than one in your app." ) : invariant ( false ) : void 0 ;
2026-02-04 00:11:19 +05:00
let basename = basenameProp . replace ( /^\/*/ , "/" ) ;
2026-02-10 13:03:46 +05:00
let navigationContext = React . useMemo ( ( ) => ( {
basename ,
navigator ,
static : staticProp ,
future : _extends2 ( {
v7 _relativeSplatPath : false
} , future )
} ) , [ basename , future , navigator , staticProp ] ) ;
2026-02-04 00:11:19 +05:00
if ( typeof locationProp === "string" ) {
locationProp = parsePath ( locationProp ) ;
}
let {
pathname = "/" ,
search = "" ,
hash = "" ,
state = null ,
key = "default"
} = locationProp ;
2026-02-10 13:03:46 +05:00
let locationContext = React . useMemo ( ( ) => {
2026-02-04 00:11:19 +05:00
let trailingPathname = stripBasename ( pathname , basename ) ;
if ( trailingPathname == null ) {
return null ;
}
return {
location : {
pathname : trailingPathname ,
search ,
hash ,
state ,
key
} ,
navigationType
} ;
} , [ basename , pathname , search , hash , state , key , navigationType ] ) ;
2026-02-10 13:03:46 +05:00
true ? warning ( locationContext != null , '<Router basename="' + basename + '"> is not able to match the URL ' + ( '"' + pathname + search + hash + '" because it does not start with the ' ) + "basename, so the <Router> won't render anything." ) : void 0 ;
2026-02-04 00:11:19 +05:00
if ( locationContext == null ) {
return null ;
}
2026-02-10 13:03:46 +05:00
return React . createElement ( NavigationContext . Provider , {
value : navigationContext
} , React . createElement ( LocationContext . Provider , {
children ,
value : locationContext
} ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function Routes ( _ref6 ) {
let {
children ,
location
} = _ref6 ;
return useRoutes ( createRoutesFromChildren ( children ) , location ) ;
}
function Await ( _ref7 ) {
let {
children ,
errorElement ,
resolve
} = _ref7 ;
return React . createElement ( AwaitErrorBoundary , {
resolve ,
errorElement
} , React . createElement ( ResolveAwait , null , children ) ) ;
}
var AwaitRenderStatus = function ( AwaitRenderStatus2 ) {
AwaitRenderStatus2 [ AwaitRenderStatus2 [ "pending" ] = 0 ] = "pending" ;
AwaitRenderStatus2 [ AwaitRenderStatus2 [ "success" ] = 1 ] = "success" ;
AwaitRenderStatus2 [ AwaitRenderStatus2 [ "error" ] = 2 ] = "error" ;
return AwaitRenderStatus2 ;
} ( AwaitRenderStatus || { } ) ;
var neverSettledPromise = new Promise ( ( ) => {
} ) ;
var AwaitErrorBoundary = class extends React . Component {
2026-02-04 00:11:19 +05:00
constructor ( props ) {
super ( props ) ;
2026-02-10 13:03:46 +05:00
this . state = {
error : null
} ;
2026-02-04 00:11:19 +05:00
}
static getDerivedStateFromError ( error ) {
2026-02-10 13:03:46 +05:00
return {
error
} ;
2026-02-04 00:11:19 +05:00
}
componentDidCatch ( error , errorInfo ) {
2026-02-10 13:03:46 +05:00
console . error ( "<Await> caught the following error during render" , error , errorInfo ) ;
2026-02-04 00:11:19 +05:00
}
render ( ) {
2026-02-10 13:03:46 +05:00
let {
children ,
errorElement ,
resolve
} = this . props ;
2026-02-04 00:11:19 +05:00
let promise = null ;
2026-02-10 13:03:46 +05:00
let status = AwaitRenderStatus . pending ;
2026-02-04 00:11:19 +05:00
if ( ! ( resolve instanceof Promise ) ) {
2026-02-10 13:03:46 +05:00
status = AwaitRenderStatus . success ;
2026-02-04 00:11:19 +05:00
promise = Promise . resolve ( ) ;
2026-02-10 13:03:46 +05:00
Object . defineProperty ( promise , "_tracked" , {
get : ( ) => true
} ) ;
Object . defineProperty ( promise , "_data" , {
get : ( ) => resolve
} ) ;
2026-02-04 00:11:19 +05:00
} else if ( this . state . error ) {
2026-02-10 13:03:46 +05:00
status = AwaitRenderStatus . error ;
2026-02-04 00:11:19 +05:00
let renderError = this . state . error ;
promise = Promise . reject ( ) . catch ( ( ) => {
} ) ;
2026-02-10 13:03:46 +05:00
Object . defineProperty ( promise , "_tracked" , {
get : ( ) => true
} ) ;
Object . defineProperty ( promise , "_error" , {
get : ( ) => renderError
} ) ;
2026-02-04 00:11:19 +05:00
} else if ( resolve . _tracked ) {
promise = resolve ;
2026-02-10 13:03:46 +05:00
status = "_error" in promise ? AwaitRenderStatus . error : "_data" in promise ? AwaitRenderStatus . success : AwaitRenderStatus . pending ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
status = AwaitRenderStatus . pending ;
Object . defineProperty ( resolve , "_tracked" , {
get : ( ) => true
} ) ;
promise = resolve . then ( ( data ) => Object . defineProperty ( resolve , "_data" , {
get : ( ) => data
} ) , ( error ) => Object . defineProperty ( resolve , "_error" , {
get : ( ) => error
} ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( status === AwaitRenderStatus . error && promise . _error instanceof AbortedDeferredError ) {
throw neverSettledPromise ;
}
if ( status === AwaitRenderStatus . error && ! errorElement ) {
2026-02-04 00:11:19 +05:00
throw promise . _error ;
}
2026-02-10 13:03:46 +05:00
if ( status === AwaitRenderStatus . error ) {
return React . createElement ( AwaitContext . Provider , {
value : promise ,
children : errorElement
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( status === AwaitRenderStatus . success ) {
return React . createElement ( AwaitContext . Provider , {
value : promise ,
children
} ) ;
2026-02-04 00:11:19 +05:00
}
throw promise ;
}
} ;
2026-02-10 13:03:46 +05:00
function ResolveAwait ( _ref8 ) {
let {
children
} = _ref8 ;
let data = useAsyncValue ( ) ;
let toRender = typeof children === "function" ? children ( data ) : children ;
return React . createElement ( React . Fragment , null , toRender ) ;
}
function createRoutesFromChildren ( children , parentPath ) {
if ( parentPath === void 0 ) {
parentPath = [ ] ;
}
2026-02-04 00:11:19 +05:00
let routes = [ ] ;
2026-02-10 13:03:46 +05:00
React . Children . forEach ( children , ( element , index ) => {
if ( ! React . isValidElement ( element ) ) {
2026-02-04 00:11:19 +05:00
return ;
}
let treePath = [ ... parentPath , index ] ;
2026-02-10 13:03:46 +05:00
if ( element . type === React . Fragment ) {
routes . push . apply ( routes , createRoutesFromChildren ( element . props . children , treePath ) ) ;
2026-02-04 00:11:19 +05:00
return ;
}
2026-02-10 13:03:46 +05:00
! ( element . type === Route ) ? true ? invariant ( false , "[" + ( typeof element . type === "string" ? element . type : element . type . name ) + "] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>" ) : invariant ( false ) : void 0 ;
! ( ! element . props . index || ! element . props . children ) ? true ? invariant ( false , "An index route cannot have child routes." ) : invariant ( false ) : void 0 ;
2026-02-04 00:11:19 +05:00
let route = {
id : element . props . id || treePath . join ( "-" ) ,
caseSensitive : element . props . caseSensitive ,
element : element . props . element ,
Component : element . props . Component ,
index : element . props . index ,
path : element . props . path ,
loader : element . props . loader ,
action : element . props . action ,
errorElement : element . props . errorElement ,
ErrorBoundary : element . props . ErrorBoundary ,
2026-02-10 13:03:46 +05:00
hasErrorBoundary : element . props . ErrorBoundary != null || element . props . errorElement != null ,
2026-02-04 00:11:19 +05:00
shouldRevalidate : element . props . shouldRevalidate ,
handle : element . props . handle ,
lazy : element . props . lazy
} ;
if ( element . props . children ) {
2026-02-10 13:03:46 +05:00
route . children = createRoutesFromChildren ( element . props . children , treePath ) ;
2026-02-04 00:11:19 +05:00
}
routes . push ( route ) ;
} ) ;
return routes ;
}
function renderMatches ( matches ) {
return _renderMatches ( matches ) ;
}
2026-02-10 13:03:46 +05:00
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 . ErrorBoundary != null || route . errorElement != null
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
if ( route . Component ) {
if ( true ) {
if ( route . element ) {
true ? warning ( false , "You should not include both `Component` and `element` on your route - `Component` will be used." ) : void 0 ;
}
}
Object . assign ( updates , {
element : React . createElement ( route . Component ) ,
Component : void 0
} ) ;
}
if ( route . HydrateFallback ) {
if ( true ) {
if ( route . hydrateFallbackElement ) {
true ? warning ( false , "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used." ) : void 0 ;
}
}
Object . assign ( updates , {
hydrateFallbackElement : React . createElement ( route . HydrateFallback ) ,
HydrateFallback : void 0
} ) ;
}
if ( route . ErrorBoundary ) {
if ( true ) {
if ( route . errorElement ) {
true ? warning ( false , "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used." ) : void 0 ;
}
}
Object . assign ( updates , {
errorElement : React . createElement ( route . ErrorBoundary ) ,
ErrorBoundary : void 0
} ) ;
}
return updates ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function createMemoryRouter ( routes , opts ) {
return createRouter ( {
basename : opts == null ? void 0 : opts . basename ,
future : _extends2 ( { } , opts == null ? void 0 : opts . future , {
v7 _prependBasename : true
} ) ,
history : createMemoryHistory ( {
initialEntries : opts == null ? void 0 : opts . initialEntries ,
initialIndex : opts == null ? void 0 : opts . initialIndex
} ) ,
hydrationData : opts == null ? void 0 : opts . hydrationData ,
routes ,
mapRouteProperties ,
dataStrategy : opts == null ? void 0 : opts . dataStrategy ,
patchRoutesOnNavigation : opts == null ? void 0 : opts . patchRoutesOnNavigation
} ) . initialize ( ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
// node_modules/react-router-dom/dist/index.js
function _extends3 ( ) {
_extends3 = Object . assign ? Object . assign . bind ( ) : function ( target ) {
for ( var i = 1 ; i < arguments . length ; i ++ ) {
var source = arguments [ i ] ;
for ( var key in source ) {
if ( Object . prototype . hasOwnProperty . call ( source , key ) ) {
target [ key ] = source [ key ] ;
}
}
}
return target ;
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
return _extends3 . apply ( this , arguments ) ;
}
function _objectWithoutPropertiesLoose ( source , excluded ) {
if ( source == null ) return { } ;
var target = { } ;
var sourceKeys = Object . keys ( source ) ;
var key , i ;
for ( i = 0 ; i < sourceKeys . length ; i ++ ) {
key = sourceKeys [ i ] ;
if ( excluded . indexOf ( key ) >= 0 ) continue ;
target [ key ] = source [ key ] ;
}
return target ;
2026-02-04 00:11:19 +05:00
}
var defaultMethod = "get" ;
var defaultEncType = "application/x-www-form-urlencoded" ;
function isHtmlElement ( object ) {
2026-02-10 13:03:46 +05:00
return object != null && typeof object . tagName === "string" ;
2026-02-04 00:11:19 +05:00
}
function isButtonElement ( object ) {
return isHtmlElement ( object ) && object . tagName . toLowerCase ( ) === "button" ;
}
function isFormElement ( object ) {
return isHtmlElement ( object ) && object . tagName . toLowerCase ( ) === "form" ;
}
function isInputElement ( object ) {
return isHtmlElement ( object ) && object . tagName . toLowerCase ( ) === "input" ;
}
function isModifiedEvent ( event ) {
return ! ! ( event . metaKey || event . altKey || event . ctrlKey || event . shiftKey ) ;
}
function shouldProcessLinkClick ( event , target ) {
return event . button === 0 && // Ignore everything but left clicks
( ! target || target === "_self" ) && // Let browser handle "target=_blank" etc.
! isModifiedEvent ( event ) ;
}
2026-02-10 13:03:46 +05:00
function createSearchParams ( init ) {
if ( init === void 0 ) {
init = "" ;
}
return new URLSearchParams ( typeof init === "string" || Array . isArray ( init ) || init instanceof URLSearchParams ? init : Object . keys ( init ) . reduce ( ( memo2 , key ) => {
let value = init [ key ] ;
return memo2 . concat ( Array . isArray ( value ) ? value . map ( ( v ) => [ key , v ] ) : [ [ key , value ] ] ) ;
} , [ ] ) ) ;
2026-02-04 00:11:19 +05:00
}
function getSearchParamsForLocation ( locationSearch , defaultSearchParams ) {
let searchParams = createSearchParams ( locationSearch ) ;
if ( defaultSearchParams ) {
defaultSearchParams . forEach ( ( _ , key ) => {
if ( ! searchParams . has ( key ) ) {
defaultSearchParams . getAll ( key ) . forEach ( ( value ) => {
searchParams . append ( key , value ) ;
} ) ;
}
} ) ;
}
return searchParams ;
}
var _formDataSupportsSubmitter = null ;
function isFormDataSubmitterSupported ( ) {
if ( _formDataSupportsSubmitter === null ) {
try {
new FormData (
document . createElement ( "form" ) ,
// @ts-expect-error if FormData supports the submitter parameter, this will throw
0
) ;
_formDataSupportsSubmitter = false ;
} catch ( e ) {
_formDataSupportsSubmitter = true ;
}
}
return _formDataSupportsSubmitter ;
}
2026-02-10 13:03:46 +05:00
var supportedFormEncTypes = /* @__PURE__ */ new Set ( [ "application/x-www-form-urlencoded" , "multipart/form-data" , "text/plain" ] ) ;
2026-02-04 00:11:19 +05:00
function getFormEncType ( encType ) {
if ( encType != null && ! supportedFormEncTypes . has ( encType ) ) {
2026-02-10 13:03:46 +05:00
true ? warning ( false , '"' + encType + '" is not a valid `encType` for `<Form>`/`<fetcher.Form>` ' + ( 'and will default to "' + defaultEncType + '"' ) ) : void 0 ;
2026-02-04 00:11:19 +05:00
return null ;
}
return encType ;
}
function getFormSubmissionInfo ( target , basename ) {
let method ;
let action ;
let encType ;
let formData ;
let body ;
if ( isFormElement ( target ) ) {
let attr = target . getAttribute ( "action" ) ;
action = attr ? stripBasename ( attr , basename ) : null ;
method = target . getAttribute ( "method" ) || defaultMethod ;
encType = getFormEncType ( target . getAttribute ( "enctype" ) ) || defaultEncType ;
formData = new FormData ( target ) ;
} else if ( isButtonElement ( target ) || isInputElement ( target ) && ( target . type === "submit" || target . type === "image" ) ) {
let form = target . form ;
if ( form == null ) {
2026-02-10 13:03:46 +05:00
throw new Error ( 'Cannot submit a <button> or <input type="submit"> without a <form>' ) ;
2026-02-04 00:11:19 +05:00
}
let attr = target . getAttribute ( "formaction" ) || form . getAttribute ( "action" ) ;
action = attr ? stripBasename ( attr , basename ) : null ;
method = target . getAttribute ( "formmethod" ) || form . getAttribute ( "method" ) || defaultMethod ;
encType = getFormEncType ( target . getAttribute ( "formenctype" ) ) || getFormEncType ( form . getAttribute ( "enctype" ) ) || defaultEncType ;
formData = new FormData ( form , target ) ;
if ( ! isFormDataSubmitterSupported ( ) ) {
2026-02-10 13:03:46 +05:00
let {
name ,
type ,
value
} = target ;
2026-02-04 00:11:19 +05:00
if ( type === "image" ) {
2026-02-10 13:03:46 +05:00
let prefix = name ? name + "." : "" ;
formData . append ( prefix + "x" , "0" ) ;
formData . append ( prefix + "y" , "0" ) ;
2026-02-04 00:11:19 +05:00
} else if ( name ) {
formData . append ( name , value ) ;
}
}
} else if ( isHtmlElement ( target ) ) {
2026-02-10 13:03:46 +05:00
throw new Error ( 'Cannot submit element that is not <form>, <button>, or <input type="submit|image">' ) ;
2026-02-04 00:11:19 +05:00
} else {
method = defaultMethod ;
action = null ;
encType = defaultEncType ;
body = target ;
}
if ( formData && encType === "text/plain" ) {
body = formData ;
formData = void 0 ;
}
2026-02-10 13:03:46 +05:00
return {
action ,
method : method . toLowerCase ( ) ,
encType ,
formData ,
body
} ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var _excluded = [ "onClick" , "relative" , "reloadDocument" , "replace" , "state" , "target" , "to" , "preventScrollReset" , "viewTransition" ] ;
var _excluded2 = [ "aria-current" , "caseSensitive" , "className" , "end" , "style" , "to" , "viewTransition" , "children" ] ;
var _excluded3 = [ "fetcherKey" , "navigate" , "reloadDocument" , "replace" , "state" , "method" , "action" , "onSubmit" , "relative" , "preventScrollReset" , "viewTransition" ] ;
var REACT _ROUTER _VERSION = "6" ;
try {
window . _ _reactRouterVersion = REACT _ROUTER _VERSION ;
} catch ( e ) {
}
function createBrowserRouter ( routes , opts ) {
return createRouter ( {
basename : opts == null ? void 0 : opts . basename ,
future : _extends3 ( { } , opts == null ? void 0 : opts . future , {
v7 _prependBasename : true
} ) ,
history : createBrowserHistory ( {
window : opts == null ? void 0 : opts . window
} ) ,
hydrationData : ( opts == null ? void 0 : opts . hydrationData ) || parseHydrationData ( ) ,
routes ,
mapRouteProperties ,
dataStrategy : opts == null ? void 0 : opts . dataStrategy ,
patchRoutesOnNavigation : opts == null ? void 0 : opts . patchRoutesOnNavigation ,
window : opts == null ? void 0 : opts . window
} ) . initialize ( ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function createHashRouter ( routes , opts ) {
return createRouter ( {
basename : opts == null ? void 0 : opts . basename ,
future : _extends3 ( { } , opts == null ? void 0 : opts . future , {
v7 _prependBasename : true
} ) ,
history : createHashHistory ( {
window : opts == null ? void 0 : opts . window
} ) ,
hydrationData : ( opts == null ? void 0 : opts . hydrationData ) || parseHydrationData ( ) ,
routes ,
mapRouteProperties ,
dataStrategy : opts == null ? void 0 : opts . dataStrategy ,
patchRoutesOnNavigation : opts == null ? void 0 : opts . patchRoutesOnNavigation ,
window : opts == null ? void 0 : opts . window
} ) . initialize ( ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function parseHydrationData ( ) {
var _window ;
let state = ( _window = window ) == null ? void 0 : _window . _ _staticRouterHydrationData ;
if ( state && state . errors ) {
state = _extends3 ( { } , state , {
errors : deserializeErrors ( state . errors )
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return state ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function deserializeErrors ( errors ) {
if ( ! errors ) return null ;
let entries = Object . entries ( errors ) ;
let serialized = { } ;
for ( let [ key , val ] of entries ) {
if ( val && val . _ _type === "RouteErrorResponse" ) {
serialized [ key ] = new ErrorResponseImpl ( val . status , val . statusText , val . data , val . internal === true ) ;
} else if ( val && val . _ _type === "Error" ) {
if ( val . _ _subType ) {
let ErrorConstructor = window [ val . _ _subType ] ;
if ( typeof ErrorConstructor === "function" ) {
try {
let error = new ErrorConstructor ( val . message ) ;
error . stack = "" ;
serialized [ key ] = error ;
} catch ( e ) {
2026-02-04 00:11:19 +05:00
}
}
}
2026-02-10 13:03:46 +05:00
if ( serialized [ key ] == null ) {
let error = new Error ( val . message ) ;
error . stack = "" ;
serialized [ key ] = error ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} else {
serialized [ key ] = val ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
return serialized ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var ViewTransitionContext = React2 . createContext ( {
isTransitioning : false
} ) ;
if ( true ) {
ViewTransitionContext . displayName = "ViewTransition" ;
}
var FetchersContext = React2 . createContext ( /* @__PURE__ */ new Map ( ) ) ;
if ( true ) {
FetchersContext . displayName = "Fetchers" ;
}
var START _TRANSITION2 = "startTransition" ;
var startTransitionImpl2 = React2 [ START _TRANSITION2 ] ;
var FLUSH _SYNC = "flushSync" ;
var flushSyncImpl = ReactDOM [ FLUSH _SYNC ] ;
var USE _ID = "useId" ;
var useIdImpl = React2 [ USE _ID ] ;
function startTransitionSafe ( cb ) {
if ( startTransitionImpl2 ) {
startTransitionImpl2 ( cb ) ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
cb ( ) ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
function flushSyncSafe ( cb ) {
if ( flushSyncImpl ) {
flushSyncImpl ( cb ) ;
} else {
cb ( ) ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
var Deferred = class {
constructor ( ) {
this . status = "pending" ;
this . promise = new Promise ( ( resolve , reject ) => {
this . resolve = ( value ) => {
if ( this . status === "pending" ) {
this . status = "resolved" ;
resolve ( value ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} ;
this . reject = ( reason ) => {
if ( this . status === "pending" ) {
this . status = "rejected" ;
reject ( reason ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} ;
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} ;
function RouterProvider ( _ref ) {
let {
fallbackElement ,
router ,
future
} = _ref ;
let [ state , setStateImpl ] = React2 . useState ( router . state ) ;
let [ pendingState , setPendingState ] = React2 . useState ( ) ;
let [ vtContext , setVtContext ] = React2 . useState ( {
isTransitioning : false
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
let [ renderDfd , setRenderDfd ] = React2 . useState ( ) ;
let [ transition , setTransition ] = React2 . useState ( ) ;
let [ interruption , setInterruption ] = React2 . useState ( ) ;
let fetcherData = React2 . useRef ( /* @__PURE__ */ new Map ( ) ) ;
let {
v7 _startTransition
} = future || { } ;
let optInStartTransition = React2 . useCallback ( ( cb ) => {
if ( v7 _startTransition ) {
startTransitionSafe ( cb ) ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
cb ( ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ v7 _startTransition ] ) ;
let setState = React2 . useCallback ( ( newState , _ref2 ) => {
let {
deletedFetchers ,
flushSync ,
viewTransitionOpts
} = _ref2 ;
newState . fetchers . forEach ( ( fetcher , key ) => {
if ( fetcher . data !== void 0 ) {
fetcherData . current . set ( key , fetcher . data ) ;
}
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
deletedFetchers . forEach ( ( key ) => fetcherData . current . delete ( key ) ) ;
let isViewTransitionUnavailable = router . window == null || router . window . document == null || typeof router . window . document . startViewTransition !== "function" ;
if ( ! viewTransitionOpts || isViewTransitionUnavailable ) {
if ( flushSync ) {
flushSyncSafe ( ( ) => setStateImpl ( newState ) ) ;
} else {
optInStartTransition ( ( ) => setStateImpl ( newState ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( flushSync ) {
flushSyncSafe ( ( ) => {
if ( transition ) {
renderDfd && renderDfd . resolve ( ) ;
transition . skipTransition ( ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
setVtContext ( {
isTransitioning : true ,
flushSync : true ,
currentLocation : viewTransitionOpts . currentLocation ,
nextLocation : viewTransitionOpts . nextLocation
} ) ;
} ) ;
let t = router . window . document . startViewTransition ( ( ) => {
flushSyncSafe ( ( ) => setStateImpl ( newState ) ) ;
} ) ;
t . finished . finally ( ( ) => {
flushSyncSafe ( ( ) => {
setRenderDfd ( void 0 ) ;
setTransition ( void 0 ) ;
setPendingState ( void 0 ) ;
setVtContext ( {
isTransitioning : false
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
} ) ;
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
flushSyncSafe ( ( ) => setTransition ( t ) ) ;
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( transition ) {
renderDfd && renderDfd . resolve ( ) ;
transition . skipTransition ( ) ;
setInterruption ( {
state : newState ,
currentLocation : viewTransitionOpts . currentLocation ,
nextLocation : viewTransitionOpts . nextLocation
} ) ;
2026-02-04 00:11:19 +05:00
} else {
2026-02-10 13:03:46 +05:00
setPendingState ( newState ) ;
setVtContext ( {
isTransitioning : true ,
flushSync : false ,
currentLocation : viewTransitionOpts . currentLocation ,
nextLocation : viewTransitionOpts . nextLocation
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ router . window , transition , renderDfd , fetcherData , optInStartTransition ] ) ;
React2 . useLayoutEffect ( ( ) => router . subscribe ( setState ) , [ router , setState ] ) ;
React2 . useEffect ( ( ) => {
if ( vtContext . isTransitioning && ! vtContext . flushSync ) {
setRenderDfd ( new Deferred ( ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ vtContext ] ) ;
React2 . useEffect ( ( ) => {
if ( renderDfd && pendingState && router . window ) {
let newState = pendingState ;
let renderPromise = renderDfd . promise ;
let transition2 = router . window . document . startViewTransition ( async ( ) => {
optInStartTransition ( ( ) => setStateImpl ( newState ) ) ;
await renderPromise ;
} ) ;
transition2 . finished . finally ( ( ) => {
setRenderDfd ( void 0 ) ;
setTransition ( void 0 ) ;
setPendingState ( void 0 ) ;
setVtContext ( {
isTransitioning : false
} ) ;
} ) ;
setTransition ( transition2 ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ optInStartTransition , pendingState , renderDfd , router . window ] ) ;
React2 . useEffect ( ( ) => {
if ( renderDfd && pendingState && state . location . key === pendingState . location . key ) {
renderDfd . resolve ( ) ;
}
} , [ renderDfd , transition , state . location , pendingState ] ) ;
React2 . useEffect ( ( ) => {
if ( ! vtContext . isTransitioning && interruption ) {
setPendingState ( interruption . state ) ;
setVtContext ( {
isTransitioning : true ,
flushSync : false ,
currentLocation : interruption . currentLocation ,
nextLocation : interruption . nextLocation
} ) ;
setInterruption ( void 0 ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ vtContext . isTransitioning , interruption ] ) ;
React2 . useEffect ( ( ) => {
true ? warning ( fallbackElement == null || ! router . future . v7 _partialHydration , "`<RouterProvider fallbackElement>` is deprecated when using `v7_partialHydration`, use a `HydrateFallback` component instead" ) : void 0 ;
} , [ ] ) ;
let navigator = React2 . useMemo ( ( ) => {
2026-02-04 00:11:19 +05:00
return {
2026-02-10 13:03:46 +05:00
createHref : router . createHref ,
encodeLocation : router . encodeLocation ,
go : ( n ) => router . navigate ( n ) ,
push : ( to , state2 , opts ) => router . navigate ( to , {
state : state2 ,
preventScrollReset : opts == null ? void 0 : opts . preventScrollReset
} ) ,
replace : ( to , state2 , opts ) => router . navigate ( to , {
replace : true ,
state : state2 ,
preventScrollReset : opts == null ? void 0 : opts . preventScrollReset
} )
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
} , [ router ] ) ;
let basename = router . basename || "/" ;
let dataRouterContext = React2 . useMemo ( ( ) => ( {
router ,
navigator ,
static : false ,
basename
} ) , [ router , navigator , basename ] ) ;
let routerFuture = React2 . useMemo ( ( ) => ( {
v7 _relativeSplatPath : router . future . v7 _relativeSplatPath
} ) , [ router . future . v7 _relativeSplatPath ] ) ;
React2 . useEffect ( ( ) => logV6DeprecationWarnings ( future , router . future ) , [ future , router . future ] ) ;
return React2 . createElement ( React2 . Fragment , null , React2 . createElement ( DataRouterContext . Provider , {
value : dataRouterContext
} , React2 . createElement ( DataRouterStateContext . Provider , {
value : state
} , React2 . createElement ( FetchersContext . Provider , {
value : fetcherData . current
} , React2 . createElement ( ViewTransitionContext . Provider , {
value : vtContext
} , React2 . createElement ( Router , {
basename ,
location : state . location ,
navigationType : state . historyAction ,
navigator ,
future : routerFuture
} , state . initialized || router . future . v7 _partialHydration ? React2 . createElement ( MemoizedDataRoutes , {
routes : router . routes ,
future : router . future ,
state
} ) : fallbackElement ) ) ) ) ) , null ) ;
}
var MemoizedDataRoutes = React2 . memo ( DataRoutes ) ;
function DataRoutes ( _ref3 ) {
let {
routes ,
future ,
state
} = _ref3 ;
return useRoutesImpl ( routes , void 0 , state , future ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function BrowserRouter ( _ref4 ) {
let {
basename ,
children ,
future ,
window : window2
} = _ref4 ;
let historyRef = React2 . useRef ( ) ;
if ( historyRef . current == null ) {
historyRef . current = createBrowserHistory ( {
window : window2 ,
v5Compat : true
2026-02-04 00:11:19 +05:00
} ) ;
}
2026-02-10 13:03:46 +05:00
let history = historyRef . current ;
let [ state , setStateImpl ] = React2 . useState ( {
action : history . action ,
location : history . location
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
let {
v7 _startTransition
} = future || { } ;
let setState = React2 . useCallback ( ( newState ) => {
v7 _startTransition && startTransitionImpl2 ? startTransitionImpl2 ( ( ) => setStateImpl ( newState ) ) : setStateImpl ( newState ) ;
} , [ setStateImpl , v7 _startTransition ] ) ;
React2 . useLayoutEffect ( ( ) => history . listen ( setState ) , [ history , setState ] ) ;
React2 . useEffect ( ( ) => logV6DeprecationWarnings ( future ) , [ future ] ) ;
return React2 . createElement ( Router , {
basename ,
children ,
location : state . location ,
navigationType : state . action ,
navigator : history ,
future
2026-02-04 00:11:19 +05:00
} ) ;
}
2026-02-10 13:03:46 +05:00
function HashRouter ( _ref5 ) {
let {
basename ,
children ,
future ,
window : window2
} = _ref5 ;
let historyRef = React2 . useRef ( ) ;
if ( historyRef . current == null ) {
historyRef . current = createHashHistory ( {
window : window2 ,
v5Compat : true
2026-02-04 00:11:19 +05:00
} ) ;
}
2026-02-10 13:03:46 +05:00
let history = historyRef . current ;
let [ state , setStateImpl ] = React2 . useState ( {
action : history . action ,
location : history . location
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
let {
v7 _startTransition
} = future || { } ;
let setState = React2 . useCallback ( ( newState ) => {
v7 _startTransition && startTransitionImpl2 ? startTransitionImpl2 ( ( ) => setStateImpl ( newState ) ) : setStateImpl ( newState ) ;
} , [ setStateImpl , v7 _startTransition ] ) ;
React2 . useLayoutEffect ( ( ) => history . listen ( setState ) , [ history , setState ] ) ;
React2 . useEffect ( ( ) => logV6DeprecationWarnings ( future ) , [ future ] ) ;
return React2 . createElement ( Router , {
basename ,
children ,
location : state . location ,
navigationType : state . action ,
navigator : history ,
future
2026-02-04 00:11:19 +05:00
} ) ;
}
2026-02-10 13:03:46 +05:00
function HistoryRouter ( _ref6 ) {
let {
basename ,
children ,
future ,
history
} = _ref6 ;
let [ state , setStateImpl ] = React2 . useState ( {
action : history . action ,
location : history . location
} ) ;
let {
v7 _startTransition
} = future || { } ;
let setState = React2 . useCallback ( ( newState ) => {
v7 _startTransition && startTransitionImpl2 ? startTransitionImpl2 ( ( ) => setStateImpl ( newState ) ) : setStateImpl ( newState ) ;
} , [ setStateImpl , v7 _startTransition ] ) ;
React2 . useLayoutEffect ( ( ) => history . listen ( setState ) , [ history , setState ] ) ;
React2 . useEffect ( ( ) => logV6DeprecationWarnings ( future ) , [ future ] ) ;
return React2 . createElement ( Router , {
basename ,
children ,
location : state . location ,
navigationType : state . action ,
navigator : history ,
future
2026-02-04 00:11:19 +05:00
} ) ;
}
2026-02-10 13:03:46 +05:00
if ( true ) {
HistoryRouter . displayName = "unstable_HistoryRouter" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var isBrowser = typeof window !== "undefined" && typeof window . document !== "undefined" && typeof window . document . createElement !== "undefined" ;
var ABSOLUTE _URL _REGEX2 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i ;
var Link = React2 . forwardRef ( function LinkWithRef ( _ref7 , ref ) {
let {
onClick ,
relative ,
reloadDocument ,
replace : replace2 ,
state ,
target ,
to ,
preventScrollReset ,
viewTransition
} = _ref7 , rest = _objectWithoutPropertiesLoose ( _ref7 , _excluded ) ;
let {
basename
} = React2 . useContext ( NavigationContext ) ;
let absoluteHref ;
let isExternal = false ;
if ( typeof to === "string" && ABSOLUTE _URL _REGEX2 . test ( to ) ) {
absoluteHref = to ;
if ( isBrowser ) {
2026-02-04 00:11:19 +05:00
try {
2026-02-10 13:03:46 +05:00
let currentUrl = new URL ( window . location . href ) ;
let targetUrl = to . startsWith ( "//" ) ? new URL ( currentUrl . protocol + to ) : new URL ( to ) ;
let path = stripBasename ( targetUrl . pathname , basename ) ;
if ( targetUrl . origin === currentUrl . origin && path != null ) {
to = path + targetUrl . search + targetUrl . hash ;
} else {
isExternal = true ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} catch ( e ) {
true ? warning ( false , '<Link to="' + to + '"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.' ) : void 0 ;
2026-02-04 00:11:19 +05:00
}
}
}
2026-02-10 13:03:46 +05:00
let href = useHref ( to , {
relative
} ) ;
let internalOnClick = useLinkClickHandler ( to , {
replace : replace2 ,
state ,
target ,
preventScrollReset ,
relative ,
viewTransition
} ) ;
function handleClick ( event ) {
if ( onClick ) onClick ( event ) ;
if ( ! event . defaultPrevented ) {
internalOnClick ( event ) ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
return (
// eslint-disable-next-line jsx-a11y/anchor-has-content
React2 . createElement ( "a" , _extends3 ( { } , rest , {
href : absoluteHref || href ,
onClick : isExternal || reloadDocument ? onClick : handleClick ,
ref ,
target
} ) )
2026-02-04 00:11:19 +05:00
) ;
2026-02-10 13:03:46 +05:00
} ) ;
if ( true ) {
Link . displayName = "Link" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var NavLink = React2 . forwardRef ( function NavLinkWithRef ( _ref8 , ref ) {
let {
"aria-current" : ariaCurrentProp = "page" ,
caseSensitive = false ,
className : classNameProp = "" ,
end = false ,
style : styleProp ,
to ,
viewTransition ,
children
} = _ref8 , rest = _objectWithoutPropertiesLoose ( _ref8 , _excluded2 ) ;
let path = useResolvedPath ( to , {
relative : rest . relative
} ) ;
let location = useLocation ( ) ;
let routerState = React2 . useContext ( DataRouterStateContext ) ;
let {
navigator ,
basename
} = React2 . useContext ( NavigationContext ) ;
let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static
// eslint-disable-next-line react-hooks/rules-of-hooks
useViewTransitionState ( path ) && viewTransition === true ;
let toPathname = navigator . encodeLocation ? navigator . encodeLocation ( path ) . pathname : path . pathname ;
let locationPathname = location . pathname ;
let nextLocationPathname = routerState && routerState . navigation && routerState . navigation . location ? routerState . navigation . location . pathname : null ;
if ( ! caseSensitive ) {
locationPathname = locationPathname . toLowerCase ( ) ;
nextLocationPathname = nextLocationPathname ? nextLocationPathname . toLowerCase ( ) : null ;
toPathname = toPathname . toLowerCase ( ) ;
}
if ( nextLocationPathname && basename ) {
nextLocationPathname = stripBasename ( nextLocationPathname , basename ) || nextLocationPathname ;
}
const endSlashPosition = toPathname !== "/" && toPathname . endsWith ( "/" ) ? toPathname . length - 1 : toPathname . length ;
let isActive = locationPathname === toPathname || ! end && locationPathname . startsWith ( toPathname ) && locationPathname . charAt ( endSlashPosition ) === "/" ;
let isPending = nextLocationPathname != null && ( nextLocationPathname === toPathname || ! end && nextLocationPathname . startsWith ( toPathname ) && nextLocationPathname . charAt ( toPathname . length ) === "/" ) ;
let renderProps = {
isActive ,
isPending ,
isTransitioning
} ;
let ariaCurrent = isActive ? ariaCurrentProp : void 0 ;
let className ;
if ( typeof classNameProp === "function" ) {
className = classNameProp ( renderProps ) ;
} else {
className = [ classNameProp , isActive ? "active" : null , isPending ? "pending" : null , isTransitioning ? "transitioning" : null ] . filter ( Boolean ) . join ( " " ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let style = typeof styleProp === "function" ? styleProp ( renderProps ) : styleProp ;
return React2 . createElement ( Link , _extends3 ( { } , rest , {
"aria-current" : ariaCurrent ,
className ,
ref ,
style ,
to ,
viewTransition
} ) , typeof children === "function" ? children ( renderProps ) : children ) ;
} ) ;
if ( true ) {
NavLink . displayName = "NavLink" ;
}
var Form = React2 . forwardRef ( ( _ref9 , forwardedRef ) => {
let {
fetcherKey ,
navigate ,
reloadDocument ,
replace : replace2 ,
state ,
method = defaultMethod ,
action ,
onSubmit ,
relative ,
preventScrollReset ,
viewTransition
} = _ref9 , props = _objectWithoutPropertiesLoose ( _ref9 , _excluded3 ) ;
let submit = useSubmit ( ) ;
let formAction = useFormAction ( action , {
relative
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
let formMethod = method . toLowerCase ( ) === "get" ? "get" : "post" ;
let submitHandler = ( event ) => {
onSubmit && onSubmit ( event ) ;
if ( event . defaultPrevented ) return ;
event . preventDefault ( ) ;
let submitter = event . nativeEvent . submitter ;
let submitMethod = ( submitter == null ? void 0 : submitter . getAttribute ( "formmethod" ) ) || method ;
submit ( submitter || event . currentTarget , {
fetcherKey ,
method : submitMethod ,
navigate ,
replace : replace2 ,
state ,
relative ,
preventScrollReset ,
viewTransition
} ) ;
} ;
return React2 . createElement ( "form" , _extends3 ( {
ref : forwardedRef ,
method : formMethod ,
action : formAction ,
onSubmit : reloadDocument ? onSubmit : submitHandler
} , props ) ) ;
} ) ;
if ( true ) {
Form . displayName = "Form" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function ScrollRestoration ( _ref10 ) {
let {
getKey ,
storageKey
} = _ref10 ;
useScrollRestoration ( {
getKey ,
storageKey
} ) ;
return null ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( true ) {
ScrollRestoration . displayName = "ScrollRestoration" ;
}
var DataRouterHook2 ;
( function ( DataRouterHook3 ) {
DataRouterHook3 [ "UseScrollRestoration" ] = "useScrollRestoration" ;
DataRouterHook3 [ "UseSubmit" ] = "useSubmit" ;
DataRouterHook3 [ "UseSubmitFetcher" ] = "useSubmitFetcher" ;
DataRouterHook3 [ "UseFetcher" ] = "useFetcher" ;
DataRouterHook3 [ "useViewTransitionState" ] = "useViewTransitionState" ;
} ) ( DataRouterHook2 || ( DataRouterHook2 = { } ) ) ;
var DataRouterStateHook2 ;
( function ( DataRouterStateHook3 ) {
DataRouterStateHook3 [ "UseFetcher" ] = "useFetcher" ;
DataRouterStateHook3 [ "UseFetchers" ] = "useFetchers" ;
DataRouterStateHook3 [ "UseScrollRestoration" ] = "useScrollRestoration" ;
} ) ( DataRouterStateHook2 || ( DataRouterStateHook2 = { } ) ) ;
function getDataRouterConsoleError2 ( hookName ) {
return hookName + " must be used within a data router. See https://reactrouter.com/v6/routers/picking-a-router." ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useDataRouterContext2 ( hookName ) {
let ctx = React2 . useContext ( DataRouterContext ) ;
! ctx ? true ? invariant ( false , getDataRouterConsoleError2 ( hookName ) ) : invariant ( false ) : void 0 ;
return ctx ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useDataRouterState2 ( hookName ) {
let state = React2 . useContext ( DataRouterStateContext ) ;
! state ? true ? invariant ( false , getDataRouterConsoleError2 ( hookName ) ) : invariant ( false ) : void 0 ;
return state ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useLinkClickHandler ( to , _temp ) {
let {
target ,
replace : replaceProp ,
state ,
preventScrollReset ,
relative ,
viewTransition
} = _temp === void 0 ? { } : _temp ;
let navigate = useNavigate ( ) ;
let location = useLocation ( ) ;
let path = useResolvedPath ( to , {
relative
} ) ;
return React2 . useCallback ( ( event ) => {
if ( shouldProcessLinkClick ( event , target ) ) {
event . preventDefault ( ) ;
let replace2 = replaceProp !== void 0 ? replaceProp : createPath ( location ) === createPath ( path ) ;
navigate ( to , {
replace : replace2 ,
state ,
preventScrollReset ,
relative ,
viewTransition
2026-02-04 00:11:19 +05:00
} ) ;
}
2026-02-10 13:03:46 +05:00
} , [ location , navigate , path , replaceProp , state , target , to , preventScrollReset , relative , viewTransition ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useSearchParams ( defaultInit ) {
true ? warning ( typeof URLSearchParams !== "undefined" , "You cannot use the `useSearchParams` hook in a browser that does not support the URLSearchParams API. If you need to support Internet Explorer 11, we recommend you load a polyfill such as https://github.com/ungap/url-search-params." ) : void 0 ;
let defaultSearchParamsRef = React2 . useRef ( createSearchParams ( defaultInit ) ) ;
let hasSetSearchParamsRef = React2 . useRef ( false ) ;
let location = useLocation ( ) ;
let searchParams = React2 . useMemo ( ( ) => (
// Only merge in the defaults if we haven't yet called setSearchParams.
// Once we call that we want those to take precedence, otherwise you can't
// remove a param with setSearchParams({}) if it has an initial value
getSearchParamsForLocation ( location . search , hasSetSearchParamsRef . current ? null : defaultSearchParamsRef . current )
) , [ location . search ] ) ;
let navigate = useNavigate ( ) ;
let setSearchParams = React2 . useCallback ( ( nextInit , navigateOptions ) => {
const newSearchParams = createSearchParams ( typeof nextInit === "function" ? nextInit ( searchParams ) : nextInit ) ;
hasSetSearchParamsRef . current = true ;
navigate ( "?" + newSearchParams , navigateOptions ) ;
} , [ navigate , searchParams ] ) ;
return [ searchParams , setSearchParams ] ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function validateClientSideSubmission ( ) {
if ( typeof document === "undefined" ) {
throw new Error ( "You are calling submit during the server render. Try calling submit within a `useEffect` or callback instead." ) ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
var fetcherId = 0 ;
var getUniqueFetcherId = ( ) => "__" + String ( ++ fetcherId ) + "__" ;
function useSubmit ( ) {
let {
router
} = useDataRouterContext2 ( DataRouterHook2 . UseSubmit ) ;
let {
basename
} = React2 . useContext ( NavigationContext ) ;
let currentRouteId = useRouteId ( ) ;
return React2 . useCallback ( function ( target , options ) {
if ( options === void 0 ) {
options = { } ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
validateClientSideSubmission ( ) ;
let {
action ,
method ,
encType ,
formData ,
body
} = getFormSubmissionInfo ( target , basename ) ;
if ( options . navigate === false ) {
let key = options . fetcherKey || getUniqueFetcherId ( ) ;
router . fetch ( key , currentRouteId , options . action || action , {
preventScrollReset : options . preventScrollReset ,
formData ,
body ,
formMethod : options . method || method ,
formEncType : options . encType || encType ,
flushSync : options . flushSync
} ) ;
} else {
router . navigate ( options . action || action , {
preventScrollReset : options . preventScrollReset ,
formData ,
body ,
formMethod : options . method || method ,
formEncType : options . encType || encType ,
replace : options . replace ,
state : options . state ,
fromRouteId : currentRouteId ,
flushSync : options . flushSync ,
viewTransition : options . viewTransition
} ) ;
}
} , [ router , basename , currentRouteId ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useFormAction ( action , _temp2 ) {
let {
relative
} = _temp2 === void 0 ? { } : _temp2 ;
let {
basename
} = React2 . useContext ( NavigationContext ) ;
let routeContext = React2 . useContext ( RouteContext ) ;
! routeContext ? true ? invariant ( false , "useFormAction must be used inside a RouteContext" ) : invariant ( false ) : void 0 ;
let [ match ] = routeContext . matches . slice ( - 1 ) ;
let path = _extends3 ( { } , useResolvedPath ( action ? action : "." , {
relative
} ) ) ;
let location = useLocation ( ) ;
if ( action == null ) {
path . search = location . search ;
let params = new URLSearchParams ( path . search ) ;
let indexValues = params . getAll ( "index" ) ;
let hasNakedIndexParam = indexValues . some ( ( v ) => v === "" ) ;
if ( hasNakedIndexParam ) {
params . delete ( "index" ) ;
indexValues . filter ( ( v ) => v ) . forEach ( ( v ) => params . append ( "index" , v ) ) ;
let qs = params . toString ( ) ;
path . search = qs ? "?" + qs : "" ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
if ( ( ! action || action === "." ) && match . route . index ) {
path . search = path . search ? path . search . replace ( /^\?/ , "?index&" ) : "?index" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( basename !== "/" ) {
path . pathname = path . pathname === "/" ? basename : joinPaths ( [ basename , path . pathname ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return createPath ( path ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useFetcher ( _temp3 ) {
var _route$matches ;
let {
key
} = _temp3 === void 0 ? { } : _temp3 ;
let {
router
} = useDataRouterContext2 ( DataRouterHook2 . UseFetcher ) ;
let state = useDataRouterState2 ( DataRouterStateHook2 . UseFetcher ) ;
let fetcherData = React2 . useContext ( FetchersContext ) ;
let route = React2 . useContext ( RouteContext ) ;
let routeId = ( _route$matches = route . matches [ route . matches . length - 1 ] ) == null ? void 0 : _route$matches . route . id ;
! fetcherData ? true ? invariant ( false , "useFetcher must be used inside a FetchersContext" ) : invariant ( false ) : void 0 ;
! route ? true ? invariant ( false , "useFetcher must be used inside a RouteContext" ) : invariant ( false ) : void 0 ;
! ( routeId != null ) ? true ? invariant ( false , 'useFetcher can only be used on routes that contain a unique "id"' ) : invariant ( false ) : void 0 ;
let defaultKey = useIdImpl ? useIdImpl ( ) : "" ;
let [ fetcherKey , setFetcherKey ] = React2 . useState ( key || defaultKey ) ;
if ( key && key !== fetcherKey ) {
setFetcherKey ( key ) ;
} else if ( ! fetcherKey ) {
setFetcherKey ( getUniqueFetcherId ( ) ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
React2 . useEffect ( ( ) => {
router . getFetcher ( fetcherKey ) ;
return ( ) => {
router . deleteFetcher ( fetcherKey ) ;
} ;
} , [ router , fetcherKey ] ) ;
let load = React2 . useCallback ( ( href , opts ) => {
! routeId ? true ? invariant ( false , "No routeId available for fetcher.load()" ) : invariant ( false ) : void 0 ;
router . fetch ( fetcherKey , routeId , href , opts ) ;
} , [ fetcherKey , routeId , router ] ) ;
let submitImpl = useSubmit ( ) ;
let submit = React2 . useCallback ( ( target , opts ) => {
submitImpl ( target , _extends3 ( { } , opts , {
navigate : false ,
fetcherKey
} ) ) ;
} , [ fetcherKey , submitImpl ] ) ;
let FetcherForm = React2 . useMemo ( ( ) => {
let FetcherForm2 = React2 . forwardRef ( ( props , ref ) => {
return React2 . createElement ( Form , _extends3 ( { } , props , {
navigate : false ,
fetcherKey ,
ref
} ) ) ;
} ) ;
if ( true ) {
FetcherForm2 . displayName = "fetcher.Form" ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
return FetcherForm2 ;
} , [ fetcherKey ] ) ;
let fetcher = state . fetchers . get ( fetcherKey ) || IDLE _FETCHER ;
let data = fetcherData . get ( fetcherKey ) ;
let fetcherWithComponents = React2 . useMemo ( ( ) => _extends3 ( {
Form : FetcherForm ,
submit ,
load
} , fetcher , {
data
} ) , [ FetcherForm , submit , load , fetcher , data ] ) ;
return fetcherWithComponents ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useFetchers ( ) {
let state = useDataRouterState2 ( DataRouterStateHook2 . UseFetchers ) ;
return Array . from ( state . fetchers . entries ( ) ) . map ( ( _ref11 ) => {
let [ key , fetcher ] = _ref11 ;
return _extends3 ( { } , fetcher , {
key
} ) ;
} ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
var SCROLL _RESTORATION _STORAGE _KEY = "react-router-scroll-positions" ;
var savedScrollPositions = { } ;
function useScrollRestoration ( _temp4 ) {
let {
getKey ,
storageKey
} = _temp4 === void 0 ? { } : _temp4 ;
let {
router
} = useDataRouterContext2 ( DataRouterHook2 . UseScrollRestoration ) ;
let {
restoreScrollPosition ,
preventScrollReset
} = useDataRouterState2 ( DataRouterStateHook2 . UseScrollRestoration ) ;
let {
basename
} = React2 . useContext ( NavigationContext ) ;
let location = useLocation ( ) ;
let matches = useMatches ( ) ;
let navigation = useNavigation ( ) ;
React2 . useEffect ( ( ) => {
window . history . scrollRestoration = "manual" ;
return ( ) => {
window . history . scrollRestoration = "auto" ;
2026-02-04 00:11:19 +05:00
} ;
2026-02-10 13:03:46 +05:00
} , [ ] ) ;
usePageHide ( React2 . useCallback ( ( ) => {
if ( navigation . state === "idle" ) {
let key = ( getKey ? getKey ( location , matches ) : null ) || location . key ;
savedScrollPositions [ key ] = window . scrollY ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
try {
sessionStorage . setItem ( storageKey || SCROLL _RESTORATION _STORAGE _KEY , JSON . stringify ( savedScrollPositions ) ) ;
} catch ( error ) {
true ? warning ( false , "Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (" + error + ")." ) : void 0 ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
window . history . scrollRestoration = "auto" ;
} , [ storageKey , getKey , navigation . state , location , matches ] ) ) ;
if ( typeof document !== "undefined" ) {
React2 . useLayoutEffect ( ( ) => {
try {
let sessionPositions = sessionStorage . getItem ( storageKey || SCROLL _RESTORATION _STORAGE _KEY ) ;
if ( sessionPositions ) {
savedScrollPositions = JSON . parse ( sessionPositions ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} catch ( e ) {
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ storageKey ] ) ;
React2 . useLayoutEffect ( ( ) => {
let getKeyWithoutBasename = getKey && basename !== "/" ? ( location2 , matches2 ) => getKey (
// Strip the basename to match useLocation()
_extends3 ( { } , location2 , {
pathname : stripBasename ( location2 . pathname , basename ) || location2 . pathname
} ) ,
matches2
) : getKey ;
let disableScrollRestoration = router == null ? void 0 : router . enableScrollRestoration ( savedScrollPositions , ( ) => window . scrollY , getKeyWithoutBasename ) ;
return ( ) => disableScrollRestoration && disableScrollRestoration ( ) ;
} , [ router , basename , getKey ] ) ;
React2 . useLayoutEffect ( ( ) => {
if ( restoreScrollPosition === false ) {
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( typeof restoreScrollPosition === "number" ) {
window . scrollTo ( 0 , restoreScrollPosition ) ;
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
if ( location . hash ) {
let el = document . getElementById ( decodeURIComponent ( location . hash . slice ( 1 ) ) ) ;
if ( el ) {
el . scrollIntoView ( ) ;
return ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
if ( preventScrollReset === true ) {
return ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
window . scrollTo ( 0 , 0 ) ;
} , [ location , restoreScrollPosition , preventScrollReset ] ) ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
function useBeforeUnload ( callback , options ) {
let {
capture
} = options || { } ;
React2 . useEffect ( ( ) => {
let opts = capture != null ? {
capture
} : void 0 ;
window . addEventListener ( "beforeunload" , callback , opts ) ;
return ( ) => {
window . removeEventListener ( "beforeunload" , callback , opts ) ;
} ;
} , [ callback , capture ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function usePageHide ( callback , options ) {
let {
capture
} = options || { } ;
React2 . useEffect ( ( ) => {
let opts = capture != null ? {
capture
} : void 0 ;
window . addEventListener ( "pagehide" , callback , opts ) ;
return ( ) => {
window . removeEventListener ( "pagehide" , callback , opts ) ;
} ;
} , [ callback , capture ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function usePrompt ( _ref12 ) {
let {
when ,
message
} = _ref12 ;
let blocker = useBlocker ( when ) ;
React2 . useEffect ( ( ) => {
if ( blocker . state === "blocked" ) {
let proceed = window . confirm ( message ) ;
if ( proceed ) {
setTimeout ( blocker . proceed , 0 ) ;
} else {
blocker . reset ( ) ;
2026-02-04 00:11:19 +05:00
}
}
2026-02-10 13:03:46 +05:00
} , [ blocker , message ] ) ;
React2 . useEffect ( ( ) => {
if ( blocker . state === "blocked" && ! when ) {
blocker . reset ( ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
} , [ blocker , when ] ) ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
function useViewTransitionState ( to , opts ) {
if ( opts === void 0 ) {
opts = { } ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let vtContext = React2 . useContext ( ViewTransitionContext ) ;
! ( vtContext != null ) ? true ? invariant ( false , "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?" ) : invariant ( false ) : void 0 ;
let {
basename
} = useDataRouterContext2 ( DataRouterHook2 . useViewTransitionState ) ;
let path = useResolvedPath ( to , {
relative : opts . relative
2026-02-04 00:11:19 +05:00
} ) ;
2026-02-10 13:03:46 +05:00
if ( ! vtContext . isTransitioning ) {
return false ;
2026-02-04 00:11:19 +05:00
}
2026-02-10 13:03:46 +05:00
let currentPath = stripBasename ( vtContext . currentLocation . pathname , basename ) || vtContext . currentLocation . pathname ;
let nextPath = stripBasename ( vtContext . nextLocation . pathname , basename ) || vtContext . nextLocation . pathname ;
return matchPath ( path . pathname , nextPath ) != null || matchPath ( path . pathname , currentPath ) != null ;
2026-02-04 00:11:19 +05:00
}
export {
2026-02-10 13:03:46 +05:00
AbortedDeferredError ,
2026-02-04 00:11:19 +05:00
Await ,
BrowserRouter ,
Form ,
HashRouter ,
Link ,
MemoryRouter ,
NavLink ,
Navigate ,
Action as NavigationType ,
Outlet ,
Route ,
Router ,
2026-02-10 13:03:46 +05:00
RouterProvider ,
2026-02-04 00:11:19 +05:00
Routes ,
ScrollRestoration ,
DataRouterContext as UNSAFE _DataRouterContext ,
DataRouterStateContext as UNSAFE _DataRouterStateContext ,
ErrorResponseImpl as UNSAFE _ErrorResponseImpl ,
FetchersContext as UNSAFE _FetchersContext ,
LocationContext as UNSAFE _LocationContext ,
NavigationContext as UNSAFE _NavigationContext ,
RouteContext as UNSAFE _RouteContext ,
ViewTransitionContext as UNSAFE _ViewTransitionContext ,
2026-02-10 13:03:46 +05:00
useRouteId as UNSAFE _useRouteId ,
2026-02-04 00:11:19 +05:00
useScrollRestoration as UNSAFE _useScrollRestoration ,
createBrowserRouter ,
createHashRouter ,
createMemoryRouter ,
createPath ,
createRoutesFromChildren ,
2026-02-10 13:03:46 +05:00
createRoutesFromChildren as createRoutesFromElements ,
2026-02-04 00:11:19 +05:00
createSearchParams ,
2026-02-10 13:03:46 +05:00
defer ,
2026-02-04 00:11:19 +05:00
generatePath ,
isRouteErrorResponse ,
2026-02-10 13:03:46 +05:00
json ,
2026-02-04 00:11:19 +05:00
matchPath ,
matchRoutes ,
parsePath ,
redirect ,
redirectDocument ,
renderMatches ,
replace ,
resolvePath ,
HistoryRouter as unstable _HistoryRouter ,
usePrompt as unstable _usePrompt ,
useActionData ,
useAsyncError ,
useAsyncValue ,
useBeforeUnload ,
useBlocker ,
useFetcher ,
useFetchers ,
useFormAction ,
useHref ,
useInRouterContext ,
useLinkClickHandler ,
useLoaderData ,
useLocation ,
useMatch ,
useMatches ,
useNavigate ,
useNavigation ,
useNavigationType ,
useOutlet ,
useOutletContext ,
useParams ,
useResolvedPath ,
useRevalidator ,
useRouteError ,
useRouteLoaderData ,
useRoutes ,
useSearchParams ,
useSubmit ,
useViewTransitionState
} ;
/ * ! B u n d l e d l i c e n s e i n f o r m a t i o n :
2026-02-10 13:03:46 +05:00
@ remix - run / router / dist / router . js :
2026-02-04 00:11:19 +05:00
( * *
2026-02-10 13:03:46 +05:00
* @ remix - run / router v1 . 23.2
2026-02-04 00:11:19 +05:00
*
* Copyright ( c ) Remix Software Inc .
*
* This source code is licensed under the MIT license found in the
* LICENSE . md file in the root directory of this source tree .
*
* @ license MIT
* )
2026-02-10 13:03:46 +05:00
react - router / dist / index . js :
2026-02-04 00:11:19 +05:00
( * *
2026-02-10 13:03:46 +05:00
* React Router v6 . 30.3
2026-02-04 00:11:19 +05:00
*
* Copyright ( c ) Remix Software Inc .
*
* This source code is licensed under the MIT license found in the
* LICENSE . md file in the root directory of this source tree .
*
* @ license MIT
* )
2026-02-10 13:03:46 +05:00
react - router - dom / dist / index . js :
2026-02-04 00:11:19 +05:00
( * *
2026-02-10 13:03:46 +05:00
* React Router DOM v6 . 30.3
2026-02-04 00:11:19 +05:00
*
* Copyright ( c ) Remix Software Inc .
*
* This source code is licensed under the MIT license found in the
* LICENSE . md file in the root directory of this source tree .
*
* @ license MIT
* )
* /
//# sourceMappingURL=react-router-dom.js.map