@tanstack/router
Advanced tools
Comparing version 0.0.1-beta.63 to 0.0.1-beta.64
@@ -16,5 +16,4 @@ /** | ||
var store = require('@tanstack/store'); | ||
var utils = require('./utils.js'); | ||
// | ||
const componentTypes = ['component', 'errorComponent', 'pendingComponent']; | ||
@@ -53,37 +52,39 @@ class RouteMatch { | ||
}; | ||
__init = opts => { | ||
__commit = () => { | ||
const { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
} = this.#resolveInfo({ | ||
location: this.router.state.currentLocation | ||
}); | ||
this.context = context; | ||
this.routeContext = routeContext; | ||
this.store.setState(s => ({ | ||
...s, | ||
routeSearch: utils.replaceEqualDeep(s.routeSearch, routeSearch), | ||
search: utils.replaceEqualDeep(s.search, search) | ||
})); | ||
}; | ||
cancel = () => { | ||
this.abortController?.abort(); | ||
}; | ||
#resolveSearchInfo = opts => { | ||
// Validate the search params and stabilize them | ||
this.parentMatch = opts.parentMatch; | ||
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search; | ||
const parentSearchInfo = this.parentMatch ? this.parentMatch.#resolveSearchInfo(opts) : { | ||
search: opts.location.search, | ||
routeSearch: opts.location.search | ||
}; | ||
try { | ||
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch; | ||
let nextSearch = validator?.(parentSearch) ?? {}; | ||
this.store.setState(s => ({ | ||
...s, | ||
routeSearch: nextSearch, | ||
search: { | ||
...parentSearch, | ||
...nextSearch | ||
} | ||
})); | ||
componentTypes.map(async type => { | ||
const component = this.route.options[type]; | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component; | ||
} | ||
}); | ||
const parent = this.parentMatch; | ||
this.routeContext = this.route.options.getContext?.({ | ||
parentContext: parent?.routeContext, | ||
context: parent?.context, | ||
params: this.params, | ||
search: this.state.search | ||
}) || {}; | ||
this.context = parent ? { | ||
...parent.context, | ||
...this.routeContext | ||
} : { | ||
...this.router?.options.context, | ||
...this.routeContext | ||
const routeSearch = validator?.(parentSearchInfo.search) ?? {}; | ||
const search = { | ||
...parentSearchInfo.search, | ||
...routeSearch | ||
}; | ||
return { | ||
routeSearch, | ||
search | ||
}; | ||
} catch (err) { | ||
@@ -95,6 +96,37 @@ console.error(err); | ||
error.code = 'INVALID_SEARCH_PARAMS'; | ||
throw error; | ||
} | ||
}; | ||
#resolveInfo = opts => { | ||
const { | ||
search, | ||
routeSearch | ||
} = this.#resolveSearchInfo(opts); | ||
const routeContext = this.route.options.getContext?.({ | ||
parentContext: this.parentMatch?.routeContext ?? {}, | ||
context: this.parentMatch?.context ?? this.router?.options.context ?? {}, | ||
params: this.params, | ||
search | ||
}) || {}; | ||
const context = { | ||
...(this.parentMatch?.context ?? this.router?.options.context), | ||
...routeContext | ||
}; | ||
return { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
}; | ||
}; | ||
__load = async opts => { | ||
this.parentMatch = opts.parentMatch; | ||
let info; | ||
try { | ||
info = this.#resolveInfo(opts); | ||
} catch (err) { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'error', | ||
error: error | ||
error: err | ||
})); | ||
@@ -105,14 +137,21 @@ | ||
} | ||
}; | ||
cancel = () => { | ||
this.abortController?.abort(); | ||
}; | ||
load = async opts => { | ||
const { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
} = info; | ||
componentTypes.map(async type => { | ||
const component = this.route.options[type]; | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component; | ||
} | ||
}); | ||
// If the match is invalid, errored or idle, trigger it to load | ||
if (this.state.status !== 'pending') { | ||
await this.fetch(opts); | ||
if (this.state.status === 'pending') { | ||
return; | ||
} | ||
}; | ||
#latestId = ''; | ||
fetch = async opts => { | ||
// TODO: Should load promises be tracked based on location? | ||
this.__loadPromise = Promise.resolve().then(async () => { | ||
@@ -125,13 +164,12 @@ const loadId = '' + Date.now() + Math.random(); | ||
let latestPromise; | ||
this.store.batch(() => { | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'pending' | ||
})); | ||
} | ||
}); | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'pending' | ||
})); | ||
} | ||
const componentsPromise = (async () => { | ||
@@ -152,7 +190,8 @@ // then run all component and data loaders in parallel | ||
params: this.params, | ||
search: this.state.search, | ||
routeSearch, | ||
search, | ||
signal: this.abortController.signal, | ||
preload: !!opts?.preload, | ||
routeContext: this.routeContext, | ||
context: this.context | ||
routeContext: routeContext, | ||
context: context | ||
}); | ||
@@ -185,2 +224,3 @@ } | ||
}; | ||
#latestId = ''; | ||
} | ||
@@ -187,0 +227,0 @@ |
@@ -183,3 +183,3 @@ /** | ||
try { | ||
await this.loadMatches(matches | ||
await this.loadMatches(matches, this.state.pendingLocation | ||
// opts | ||
@@ -236,2 +236,3 @@ ); | ||
}); | ||
const prevLocation = this.state.currentLocation; | ||
this.store.setState(s => ({ | ||
@@ -245,3 +246,8 @@ ...s, | ||
})); | ||
this.options.onRouteChange?.(); | ||
matches.forEach(match => { | ||
match.__commit(); | ||
}); | ||
if (prevLocation.href !== this.state.currentLocation.href) { | ||
this.options.onRouteChange?.(); | ||
} | ||
this.resolveNavigation(); | ||
@@ -259,3 +265,3 @@ }; | ||
}); | ||
await this.loadMatches(matches); | ||
await this.loadMatches(matches, next); | ||
return matches; | ||
@@ -268,3 +274,3 @@ }; | ||
}); | ||
await this.loadMatches(matches, { | ||
await this.loadMatches(matches, next, { | ||
preload: true | ||
@@ -341,5 +347,3 @@ }); | ||
}; | ||
loadMatches = async (resolvedMatches, opts) => { | ||
initMatches(resolvedMatches); | ||
loadMatches = async (resolvedMatches, location, opts) => { | ||
// Check each match middleware to see if the route can be accessed | ||
@@ -360,19 +364,12 @@ await Promise.all(resolvedMatches.map(async match => { | ||
const matchPromises = resolvedMatches.map(async (match, index) => { | ||
const prevMatch = resolvedMatches[1]; | ||
match.state.search; | ||
// if (opts?.filter && !opts.filter(match)) { | ||
// return | ||
// } | ||
match.load({ | ||
preload: opts?.preload | ||
const parentMatch = resolvedMatches[index - 1]; | ||
match.__load({ | ||
preload: opts?.preload, | ||
location, | ||
parentMatch | ||
}); | ||
if (match.state.status !== 'success' && match.__loadPromise) { | ||
// Wait for the first sign of activity from the match | ||
await match.__loadPromise; | ||
await match.__loadPromise; | ||
if (parentMatch) { | ||
await parentMatch.__loadPromise; | ||
} | ||
if (prevMatch) { | ||
await prevMatch.__loadPromise; | ||
} | ||
}); | ||
@@ -439,3 +436,2 @@ await Promise.all(matchPromises); | ||
if (opts?.includeSearch ?? true) { | ||
console.log(baseLocation.search, next.search, utils.partialDeepEqual(baseLocation.search, next.search)); | ||
return utils.partialDeepEqual(baseLocation.search, next.search) ? match : false; | ||
@@ -455,4 +451,2 @@ } | ||
preload, | ||
preloadMaxAge: userPreloadMaxAge, | ||
preloadGcMaxAge: userPreloadGcMaxAge, | ||
preloadDelay: userPreloadDelay, | ||
@@ -577,3 +571,2 @@ disabled | ||
}); | ||
initMatches(currentMatches); | ||
return { | ||
@@ -717,10 +710,2 @@ ...s, | ||
} | ||
function initMatches(matches) { | ||
matches.forEach((match, index) => { | ||
const parentMatch = matches[index - 1]; | ||
match.__init({ | ||
parentMatch | ||
}); | ||
}); | ||
} | ||
@@ -727,0 +712,0 @@ exports.Router = Router; |
@@ -582,4 +582,2 @@ /** | ||
// | ||
const componentTypes = ['component', 'errorComponent', 'pendingComponent']; | ||
@@ -618,37 +616,39 @@ class RouteMatch { | ||
}; | ||
__init = opts => { | ||
__commit = () => { | ||
const { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
} = this.#resolveInfo({ | ||
location: this.router.state.currentLocation | ||
}); | ||
this.context = context; | ||
this.routeContext = routeContext; | ||
this.store.setState(s => ({ | ||
...s, | ||
routeSearch: replaceEqualDeep(s.routeSearch, routeSearch), | ||
search: replaceEqualDeep(s.search, search) | ||
})); | ||
}; | ||
cancel = () => { | ||
this.abortController?.abort(); | ||
}; | ||
#resolveSearchInfo = opts => { | ||
// Validate the search params and stabilize them | ||
this.parentMatch = opts.parentMatch; | ||
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search; | ||
const parentSearchInfo = this.parentMatch ? this.parentMatch.#resolveSearchInfo(opts) : { | ||
search: opts.location.search, | ||
routeSearch: opts.location.search | ||
}; | ||
try { | ||
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch; | ||
let nextSearch = validator?.(parentSearch) ?? {}; | ||
this.store.setState(s => ({ | ||
...s, | ||
routeSearch: nextSearch, | ||
search: { | ||
...parentSearch, | ||
...nextSearch | ||
} | ||
})); | ||
componentTypes.map(async type => { | ||
const component = this.route.options[type]; | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component; | ||
} | ||
}); | ||
const parent = this.parentMatch; | ||
this.routeContext = this.route.options.getContext?.({ | ||
parentContext: parent?.routeContext, | ||
context: parent?.context, | ||
params: this.params, | ||
search: this.state.search | ||
}) || {}; | ||
this.context = parent ? { | ||
...parent.context, | ||
...this.routeContext | ||
} : { | ||
...this.router?.options.context, | ||
...this.routeContext | ||
const routeSearch = validator?.(parentSearchInfo.search) ?? {}; | ||
const search = { | ||
...parentSearchInfo.search, | ||
...routeSearch | ||
}; | ||
return { | ||
routeSearch, | ||
search | ||
}; | ||
} catch (err) { | ||
@@ -660,6 +660,37 @@ console.error(err); | ||
error.code = 'INVALID_SEARCH_PARAMS'; | ||
throw error; | ||
} | ||
}; | ||
#resolveInfo = opts => { | ||
const { | ||
search, | ||
routeSearch | ||
} = this.#resolveSearchInfo(opts); | ||
const routeContext = this.route.options.getContext?.({ | ||
parentContext: this.parentMatch?.routeContext ?? {}, | ||
context: this.parentMatch?.context ?? this.router?.options.context ?? {}, | ||
params: this.params, | ||
search | ||
}) || {}; | ||
const context = { | ||
...(this.parentMatch?.context ?? this.router?.options.context), | ||
...routeContext | ||
}; | ||
return { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
}; | ||
}; | ||
__load = async opts => { | ||
this.parentMatch = opts.parentMatch; | ||
let info; | ||
try { | ||
info = this.#resolveInfo(opts); | ||
} catch (err) { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'error', | ||
error: error | ||
error: err | ||
})); | ||
@@ -670,14 +701,21 @@ | ||
} | ||
}; | ||
cancel = () => { | ||
this.abortController?.abort(); | ||
}; | ||
load = async opts => { | ||
const { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
} = info; | ||
componentTypes.map(async type => { | ||
const component = this.route.options[type]; | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component; | ||
} | ||
}); | ||
// If the match is invalid, errored or idle, trigger it to load | ||
if (this.state.status !== 'pending') { | ||
await this.fetch(opts); | ||
if (this.state.status === 'pending') { | ||
return; | ||
} | ||
}; | ||
#latestId = ''; | ||
fetch = async opts => { | ||
// TODO: Should load promises be tracked based on location? | ||
this.__loadPromise = Promise.resolve().then(async () => { | ||
@@ -690,13 +728,12 @@ const loadId = '' + Date.now() + Math.random(); | ||
let latestPromise; | ||
this.store.batch(() => { | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'pending' | ||
})); | ||
} | ||
}); | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'pending' | ||
})); | ||
} | ||
const componentsPromise = (async () => { | ||
@@ -717,7 +754,8 @@ // then run all component and data loaders in parallel | ||
params: this.params, | ||
search: this.state.search, | ||
routeSearch, | ||
search, | ||
signal: this.abortController.signal, | ||
preload: !!opts?.preload, | ||
routeContext: this.routeContext, | ||
context: this.context | ||
routeContext: routeContext, | ||
context: context | ||
}); | ||
@@ -750,2 +788,3 @@ } | ||
}; | ||
#latestId = ''; | ||
} | ||
@@ -956,3 +995,3 @@ | ||
try { | ||
await this.loadMatches(matches | ||
await this.loadMatches(matches, this.state.pendingLocation | ||
// opts | ||
@@ -1009,2 +1048,3 @@ ); | ||
}); | ||
const prevLocation = this.state.currentLocation; | ||
this.store.setState(s => ({ | ||
@@ -1018,3 +1058,8 @@ ...s, | ||
})); | ||
this.options.onRouteChange?.(); | ||
matches.forEach(match => { | ||
match.__commit(); | ||
}); | ||
if (prevLocation.href !== this.state.currentLocation.href) { | ||
this.options.onRouteChange?.(); | ||
} | ||
this.resolveNavigation(); | ||
@@ -1032,3 +1077,3 @@ }; | ||
}); | ||
await this.loadMatches(matches); | ||
await this.loadMatches(matches, next); | ||
return matches; | ||
@@ -1041,3 +1086,3 @@ }; | ||
}); | ||
await this.loadMatches(matches, { | ||
await this.loadMatches(matches, next, { | ||
preload: true | ||
@@ -1114,5 +1159,3 @@ }); | ||
}; | ||
loadMatches = async (resolvedMatches, opts) => { | ||
initMatches(resolvedMatches); | ||
loadMatches = async (resolvedMatches, location, opts) => { | ||
// Check each match middleware to see if the route can be accessed | ||
@@ -1133,19 +1176,12 @@ await Promise.all(resolvedMatches.map(async match => { | ||
const matchPromises = resolvedMatches.map(async (match, index) => { | ||
const prevMatch = resolvedMatches[1]; | ||
match.state.search; | ||
// if (opts?.filter && !opts.filter(match)) { | ||
// return | ||
// } | ||
match.load({ | ||
preload: opts?.preload | ||
const parentMatch = resolvedMatches[index - 1]; | ||
match.__load({ | ||
preload: opts?.preload, | ||
location, | ||
parentMatch | ||
}); | ||
if (match.state.status !== 'success' && match.__loadPromise) { | ||
// Wait for the first sign of activity from the match | ||
await match.__loadPromise; | ||
await match.__loadPromise; | ||
if (parentMatch) { | ||
await parentMatch.__loadPromise; | ||
} | ||
if (prevMatch) { | ||
await prevMatch.__loadPromise; | ||
} | ||
}); | ||
@@ -1212,3 +1248,2 @@ await Promise.all(matchPromises); | ||
if (opts?.includeSearch ?? true) { | ||
console.log(baseLocation.search, next.search, partialDeepEqual(baseLocation.search, next.search)); | ||
return partialDeepEqual(baseLocation.search, next.search) ? match : false; | ||
@@ -1228,4 +1263,2 @@ } | ||
preload, | ||
preloadMaxAge: userPreloadMaxAge, | ||
preloadGcMaxAge: userPreloadGcMaxAge, | ||
preloadDelay: userPreloadDelay, | ||
@@ -1350,3 +1383,2 @@ disabled | ||
}); | ||
initMatches(currentMatches); | ||
return { | ||
@@ -1490,12 +1522,4 @@ ...s, | ||
} | ||
function initMatches(matches) { | ||
matches.forEach((match, index) => { | ||
const parentMatch = matches[index - 1]; | ||
match.__init({ | ||
parentMatch | ||
}); | ||
}); | ||
} | ||
export { RootRoute, Route, RouteMatch, Router, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultFetchServerDataFn, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning }; | ||
//# sourceMappingURL=index.js.map |
@@ -11,3 +11,3 @@ { | ||
"name": "node_modules/.pnpm/tiny-invariant@1.3.1/node_modules/tiny-invariant/dist/esm/tiny-invariant.js", | ||
"uid": "cf24-30" | ||
"uid": "8d6c-30" | ||
}, | ||
@@ -21,35 +21,35 @@ { | ||
{ | ||
"uid": "cf24-32", | ||
"uid": "8d6c-32", | ||
"name": "history.ts" | ||
}, | ||
{ | ||
"uid": "cf24-34", | ||
"uid": "8d6c-34", | ||
"name": "utils.ts" | ||
}, | ||
{ | ||
"uid": "cf24-36", | ||
"uid": "8d6c-36", | ||
"name": "path.ts" | ||
}, | ||
{ | ||
"uid": "cf24-38", | ||
"uid": "8d6c-38", | ||
"name": "qss.ts" | ||
}, | ||
{ | ||
"uid": "cf24-40", | ||
"uid": "8d6c-40", | ||
"name": "route.ts" | ||
}, | ||
{ | ||
"uid": "cf24-44", | ||
"uid": "8d6c-44", | ||
"name": "routeMatch.ts" | ||
}, | ||
{ | ||
"uid": "cf24-46", | ||
"uid": "8d6c-46", | ||
"name": "searchParams.ts" | ||
}, | ||
{ | ||
"uid": "cf24-48", | ||
"uid": "8d6c-48", | ||
"name": "router.ts" | ||
}, | ||
{ | ||
"uid": "cf24-50", | ||
"uid": "8d6c-50", | ||
"name": "index.ts" | ||
@@ -61,3 +61,3 @@ } | ||
"name": "store/build/esm/index.js", | ||
"uid": "cf24-42" | ||
"uid": "8d6c-42" | ||
} | ||
@@ -72,74 +72,74 @@ ] | ||
"nodeParts": { | ||
"cf24-30": { | ||
"8d6c-30": { | ||
"renderedLength": 199, | ||
"gzipLength": 134, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-29" | ||
"mainUid": "8d6c-29" | ||
}, | ||
"cf24-32": { | ||
"8d6c-32": { | ||
"renderedLength": 4236, | ||
"gzipLength": 1085, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-31" | ||
"mainUid": "8d6c-31" | ||
}, | ||
"cf24-34": { | ||
"8d6c-34": { | ||
"renderedLength": 3046, | ||
"gzipLength": 1062, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-33" | ||
"mainUid": "8d6c-33" | ||
}, | ||
"cf24-36": { | ||
"8d6c-36": { | ||
"renderedLength": 5601, | ||
"gzipLength": 1328, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-35" | ||
"mainUid": "8d6c-35" | ||
}, | ||
"cf24-38": { | ||
"8d6c-38": { | ||
"renderedLength": 1395, | ||
"gzipLength": 558, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-37" | ||
"mainUid": "8d6c-37" | ||
}, | ||
"cf24-40": { | ||
"8d6c-40": { | ||
"renderedLength": 2963, | ||
"gzipLength": 847, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-39" | ||
"mainUid": "8d6c-39" | ||
}, | ||
"cf24-42": { | ||
"8d6c-42": { | ||
"renderedLength": 1384, | ||
"gzipLength": 502, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-41" | ||
"mainUid": "8d6c-41" | ||
}, | ||
"cf24-44": { | ||
"renderedLength": 5448, | ||
"gzipLength": 1470, | ||
"8d6c-44": { | ||
"renderedLength": 6383, | ||
"gzipLength": 1646, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-43" | ||
"mainUid": "8d6c-43" | ||
}, | ||
"cf24-46": { | ||
"8d6c-46": { | ||
"renderedLength": 1387, | ||
"gzipLength": 483, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-45" | ||
"mainUid": "8d6c-45" | ||
}, | ||
"cf24-48": { | ||
"renderedLength": 23450, | ||
"gzipLength": 5468, | ||
"8d6c-48": { | ||
"renderedLength": 23024, | ||
"gzipLength": 5366, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-47" | ||
"mainUid": "8d6c-47" | ||
}, | ||
"cf24-50": { | ||
"8d6c-50": { | ||
"renderedLength": 0, | ||
"gzipLength": 0, | ||
"brotliLength": 0, | ||
"mainUid": "cf24-49" | ||
"mainUid": "8d6c-49" | ||
} | ||
}, | ||
"nodeMetas": { | ||
"cf24-29": { | ||
"8d6c-29": { | ||
"id": "/node_modules/.pnpm/tiny-invariant@1.3.1/node_modules/tiny-invariant/dist/esm/tiny-invariant.js", | ||
"moduleParts": { | ||
"index.production.js": "cf24-30" | ||
"index.production.js": "8d6c-30" | ||
}, | ||
@@ -149,16 +149,16 @@ "imported": [], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-39" | ||
"uid": "8d6c-39" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-31": { | ||
"8d6c-31": { | ||
"id": "/packages/router/src/history.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-32" | ||
"index.production.js": "8d6c-32" | ||
}, | ||
@@ -168,13 +168,13 @@ "imported": [], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-33": { | ||
"8d6c-33": { | ||
"id": "/packages/router/src/utils.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-34" | ||
"index.production.js": "8d6c-34" | ||
}, | ||
@@ -184,20 +184,23 @@ "imported": [], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-35" | ||
"uid": "8d6c-35" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-43" | ||
}, | ||
{ | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-35": { | ||
"8d6c-35": { | ||
"id": "/packages/router/src/path.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-36" | ||
"index.production.js": "8d6c-36" | ||
}, | ||
"imported": [ | ||
{ | ||
"uid": "cf24-33" | ||
"uid": "8d6c-33" | ||
} | ||
@@ -207,16 +210,16 @@ ], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-39" | ||
"uid": "8d6c-39" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-37": { | ||
"8d6c-37": { | ||
"id": "/packages/router/src/qss.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-38" | ||
"index.production.js": "8d6c-38" | ||
}, | ||
@@ -226,20 +229,20 @@ "imported": [], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-45" | ||
"uid": "8d6c-45" | ||
} | ||
] | ||
}, | ||
"cf24-39": { | ||
"8d6c-39": { | ||
"id": "/packages/router/src/route.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-40" | ||
"index.production.js": "8d6c-40" | ||
}, | ||
"imported": [ | ||
{ | ||
"uid": "cf24-29" | ||
"uid": "8d6c-29" | ||
}, | ||
{ | ||
"uid": "cf24-35" | ||
"uid": "8d6c-35" | ||
} | ||
@@ -249,10 +252,10 @@ ], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
} | ||
] | ||
}, | ||
"cf24-41": { | ||
"8d6c-41": { | ||
"id": "/packages/store/build/esm/index.js", | ||
"moduleParts": { | ||
"index.production.js": "cf24-42" | ||
"index.production.js": "8d6c-42" | ||
}, | ||
@@ -262,17 +265,20 @@ "imported": [], | ||
{ | ||
"uid": "cf24-43" | ||
"uid": "8d6c-43" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-43": { | ||
"8d6c-43": { | ||
"id": "/packages/router/src/routeMatch.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-44" | ||
"index.production.js": "8d6c-44" | ||
}, | ||
"imported": [ | ||
{ | ||
"uid": "cf24-41" | ||
"uid": "8d6c-41" | ||
}, | ||
{ | ||
"uid": "8d6c-33" | ||
} | ||
@@ -282,17 +288,17 @@ ], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-45": { | ||
"8d6c-45": { | ||
"id": "/packages/router/src/searchParams.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-46" | ||
"index.production.js": "8d6c-46" | ||
}, | ||
"imported": [ | ||
{ | ||
"uid": "cf24-37" | ||
"uid": "8d6c-37" | ||
} | ||
@@ -302,35 +308,35 @@ ], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
} | ||
] | ||
}, | ||
"cf24-47": { | ||
"8d6c-47": { | ||
"id": "/packages/router/src/router.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-48" | ||
"index.production.js": "8d6c-48" | ||
}, | ||
"imported": [ | ||
{ | ||
"uid": "cf24-41" | ||
"uid": "8d6c-41" | ||
}, | ||
{ | ||
"uid": "cf24-29" | ||
"uid": "8d6c-29" | ||
}, | ||
{ | ||
"uid": "cf24-35" | ||
"uid": "8d6c-35" | ||
}, | ||
{ | ||
"uid": "cf24-43" | ||
"uid": "8d6c-43" | ||
}, | ||
{ | ||
"uid": "cf24-45" | ||
"uid": "8d6c-45" | ||
}, | ||
{ | ||
"uid": "cf24-33" | ||
"uid": "8d6c-33" | ||
}, | ||
{ | ||
"uid": "cf24-31" | ||
"uid": "8d6c-31" | ||
} | ||
@@ -340,47 +346,47 @@ ], | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
} | ||
] | ||
}, | ||
"cf24-49": { | ||
"8d6c-49": { | ||
"id": "/packages/router/src/index.ts", | ||
"moduleParts": { | ||
"index.production.js": "cf24-50" | ||
"index.production.js": "8d6c-50" | ||
}, | ||
"imported": [ | ||
{ | ||
"uid": "cf24-29" | ||
"uid": "8d6c-29" | ||
}, | ||
{ | ||
"uid": "cf24-31" | ||
"uid": "8d6c-31" | ||
}, | ||
{ | ||
"uid": "cf24-51" | ||
"uid": "8d6c-51" | ||
}, | ||
{ | ||
"uid": "cf24-52" | ||
"uid": "8d6c-52" | ||
}, | ||
{ | ||
"uid": "cf24-35" | ||
"uid": "8d6c-35" | ||
}, | ||
{ | ||
"uid": "cf24-37" | ||
"uid": "8d6c-37" | ||
}, | ||
{ | ||
"uid": "cf24-39" | ||
"uid": "8d6c-39" | ||
}, | ||
{ | ||
"uid": "cf24-53" | ||
"uid": "8d6c-53" | ||
}, | ||
{ | ||
"uid": "cf24-43" | ||
"uid": "8d6c-43" | ||
}, | ||
{ | ||
"uid": "cf24-47" | ||
"uid": "8d6c-47" | ||
}, | ||
{ | ||
"uid": "cf24-45" | ||
"uid": "8d6c-45" | ||
}, | ||
{ | ||
"uid": "cf24-33" | ||
"uid": "8d6c-33" | ||
} | ||
@@ -391,3 +397,3 @@ ], | ||
}, | ||
"cf24-51": { | ||
"8d6c-51": { | ||
"id": "/packages/router/src/frameworks.ts", | ||
@@ -398,7 +404,7 @@ "moduleParts": {}, | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
} | ||
] | ||
}, | ||
"cf24-52": { | ||
"8d6c-52": { | ||
"id": "/packages/router/src/link.ts", | ||
@@ -409,7 +415,7 @@ "moduleParts": {}, | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
} | ||
] | ||
}, | ||
"cf24-53": { | ||
"8d6c-53": { | ||
"id": "/packages/router/src/routeInfo.ts", | ||
@@ -420,3 +426,3 @@ "moduleParts": {}, | ||
{ | ||
"uid": "cf24-49" | ||
"uid": "8d6c-49" | ||
} | ||
@@ -423,0 +429,0 @@ ] |
@@ -244,3 +244,3 @@ /** | ||
}) => AnyRouteMatch[]; | ||
loadMatches: (resolvedMatches: RouteMatch[], opts?: { | ||
loadMatches: (resolvedMatches: RouteMatch[], location: ParsedLocation, opts?: { | ||
preload?: boolean; | ||
@@ -252,3 +252,3 @@ }) => Promise<void>; | ||
matchRoute: <TFrom extends ValidFromPath<TRoutesInfo> = "/", TTo extends string = ".", TResolved extends string = ResolveRelativePath<TFrom, NoInfer<TTo>>>(location: ToOptions<TRoutesInfo, TFrom, TTo, ResolveRelativePath<TFrom, NoInfer<TTo>>>, opts?: MatchRouteOptions) => false | TRoutesInfo["routesById"][TResolved]["__types"]["allParams"]; | ||
buildLink: <TFrom extends ValidFromPath<TRoutesInfo> = "/", TTo extends string = ".">({ from, to, search, params, hash, target, replace, activeOptions, preload, preloadMaxAge: userPreloadMaxAge, preloadGcMaxAge: userPreloadGcMaxAge, preloadDelay: userPreloadDelay, disabled, }: LinkOptions<TRoutesInfo, TFrom, TTo>) => LinkInfo; | ||
buildLink: <TFrom extends ValidFromPath<TRoutesInfo> = "/", TTo extends string = ".">({ from, to, search, params, hash, target, replace, activeOptions, preload, preloadDelay: userPreloadDelay, disabled, }: LinkOptions<TRoutesInfo, TFrom, TTo>) => LinkInfo; | ||
dehydrate: () => DehydratedRouter; | ||
@@ -265,2 +265,7 @@ hydrate: (dehydratedRouter: DehydratedRouter) => void; | ||
} | ||
interface PendingRouteMatchInfo { | ||
state: RouteMatchStore<any, any>; | ||
routeContext: {}; | ||
context: {}; | ||
} | ||
interface AnyRouteMatch extends RouteMatch<any, any> { | ||
@@ -285,2 +290,3 @@ } | ||
parentMatch?: RouteMatch; | ||
pendingInfo?: PendingRouteMatchInfo; | ||
__loadPromise?: Promise<void>; | ||
@@ -296,12 +302,9 @@ __onExit?: void | ((matchContext: { | ||
}); | ||
__init: (opts: { | ||
parentMatch?: RouteMatch; | ||
}) => void; | ||
__commit: () => void; | ||
cancel: () => void; | ||
load: (opts?: { | ||
__load: (opts: { | ||
parentMatch: RouteMatch | undefined; | ||
preload?: boolean; | ||
location: ParsedLocation; | ||
}) => Promise<void>; | ||
fetch: (opts?: { | ||
preload?: boolean; | ||
}) => Promise<void>; | ||
} | ||
@@ -338,3 +341,3 @@ | ||
}) => Promise<void> | void; | ||
onLoad?: OnLoadFn<TFullSearchSchema, TAllParams, TRouteContext, TContext>; | ||
onLoad?: OnLoadFn<TSearchSchema, TFullSearchSchema, TAllParams, TRouteContext, TContext>; | ||
onLoadError?: (err: any) => void; | ||
@@ -381,5 +384,6 @@ onLoaded?: (matchContext: { | ||
}; | ||
type OnLoadFn<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TContext extends AnyContext = AnyContext, TAllContext extends AnyContext = AnyContext> = (loaderContext: LoaderContext<TFullSearchSchema, TAllParams, TContext, TAllContext>) => Promise<any> | void; | ||
interface LoaderContext<TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TContext extends AnyContext = AnyContext, TAllContext extends AnyContext = AnyContext> { | ||
type OnLoadFn<TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TContext extends AnyContext = AnyContext, TAllContext extends AnyContext = AnyContext> = (loaderContext: LoaderContext<TSearchSchema, TFullSearchSchema, TAllParams, TContext, TAllContext>) => Promise<any> | void; | ||
interface LoaderContext<TSearchSchema extends AnySearchSchema = {}, TFullSearchSchema extends AnySearchSchema = {}, TAllParams extends AnyPathParams = {}, TContext extends AnyContext = AnyContext, TAllContext extends AnyContext = AnyContext> { | ||
params: TAllParams; | ||
routeSearch: TSearchSchema; | ||
search: TFullSearchSchema; | ||
@@ -595,4 +599,2 @@ signal?: AbortSignal; | ||
preload?: false | 'intent'; | ||
preloadMaxAge?: number; | ||
preloadGcMaxAge?: number; | ||
preloadDelay?: number; | ||
@@ -641,2 +643,2 @@ disabled?: boolean; | ||
export { ActiveOptions, AnyContext, AnyLoaderData, AnyPathParams, AnyRootRoute, AnyRoute, AnyRouteMatch, AnyRouter, AnyRoutesInfo, AnySearchSchema, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, DeepAwaited, DefaultRoutesInfo, DefinedPathParamWarning, DehydratedRouter, DehydratedRouterState, Expand, FilterRoutesFn, FrameworkGenerics, FrameworkRouteOptions, FromLocation, GetFrameworkGeneric, InferFullSearchSchema, IsAny, IsAnyBoolean, IsKnown, LinkInfo, LinkOptions, ListenerFn, LoaderContext, LoaderState, LocationState, MatchCache, MatchCacheEntry, MatchLocation, MatchRouteOptions, NavigateOptions, NoInfer, OnLoadFn, ParentParams, ParsePathParams, ParseRoute, ParseRouteChild, ParseRouteChildren, ParsedLocation, ParsedPath, PathParamMask, PathParamOptions, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, Register, RegisteredRouter, RegisteredRoutesInfo, RelativeToPathAutoComplete, ResolveFullSearchSchema, ResolveRelativePath, RootRoute, RootRouteId, Route, RouteById, RouteByPath, RouteMatch, RouteMatchStore, RouteMeta, RouteOptions, RouteOptionsBase, RouteOptionsBaseIntersection, Router, RouterContext, RouterHistory, RouterLocation, RouterOptions, RouterStore, RoutesById, RoutesInfo, RoutesInfoInner, SearchFilter, SearchParamOptions, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, Timeout, ToIdOption, ToOptions, ToPathOption, UnionToIntersection, UnloaderFn, Updater, ValidFromPath, ValueKeys, Values, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultFetchServerDataFn, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning }; | ||
export { ActiveOptions, AnyContext, AnyLoaderData, AnyPathParams, AnyRootRoute, AnyRoute, AnyRouteMatch, AnyRouter, AnyRoutesInfo, AnySearchSchema, BuildNextOptions, CheckId, CheckIdError, CheckPath, CheckPathError, CheckRelativePath, DeepAwaited, DefaultRoutesInfo, DefinedPathParamWarning, DehydratedRouter, DehydratedRouterState, Expand, FilterRoutesFn, FrameworkGenerics, FrameworkRouteOptions, FromLocation, GetFrameworkGeneric, InferFullSearchSchema, IsAny, IsAnyBoolean, IsKnown, LinkInfo, LinkOptions, ListenerFn, LoaderContext, LoaderState, LocationState, MatchCache, MatchCacheEntry, MatchLocation, MatchRouteOptions, NavigateOptions, NoInfer, OnLoadFn, ParentParams, ParsePathParams, ParseRoute, ParseRouteChild, ParseRouteChildren, ParsedLocation, ParsedPath, PathParamMask, PathParamOptions, PendingRouteMatchInfo, PickAsPartial, PickAsRequired, PickExclude, PickExtra, PickExtract, PickRequired, PickUnsafe, Register, RegisteredRouter, RegisteredRoutesInfo, RelativeToPathAutoComplete, ResolveFullSearchSchema, ResolveRelativePath, RootRoute, RootRouteId, Route, RouteById, RouteByPath, RouteMatch, RouteMatchStore, RouteMeta, RouteOptions, RouteOptionsBase, RouteOptionsBaseIntersection, Router, RouterContext, RouterHistory, RouterLocation, RouterOptions, RouterStore, RoutesById, RoutesInfo, RoutesInfoInner, SearchFilter, SearchParamOptions, SearchParser, SearchSchemaValidator, SearchSchemaValidatorFn, SearchSchemaValidatorObj, SearchSerializer, Segment, Split, Timeout, ToIdOption, ToOptions, ToPathOption, UnionToIntersection, UnloaderFn, Updater, ValidFromPath, ValueKeys, Values, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, decode, defaultFetchServerDataFn, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, isPlainObject, joinPaths, last, matchByPath, matchPathname, parsePathname, parseSearchWith, partialDeepEqual, pick, replaceEqualDeep, resolvePath, rootRouteId, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, warning }; |
@@ -643,4 +643,2 @@ /** | ||
// | ||
const componentTypes = ['component', 'errorComponent', 'pendingComponent']; | ||
@@ -679,37 +677,39 @@ class RouteMatch { | ||
}; | ||
__init = opts => { | ||
__commit = () => { | ||
const { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
} = this.#resolveInfo({ | ||
location: this.router.state.currentLocation | ||
}); | ||
this.context = context; | ||
this.routeContext = routeContext; | ||
this.store.setState(s => ({ | ||
...s, | ||
routeSearch: replaceEqualDeep(s.routeSearch, routeSearch), | ||
search: replaceEqualDeep(s.search, search) | ||
})); | ||
}; | ||
cancel = () => { | ||
this.abortController?.abort(); | ||
}; | ||
#resolveSearchInfo = opts => { | ||
// Validate the search params and stabilize them | ||
this.parentMatch = opts.parentMatch; | ||
const parentSearch = this.parentMatch?.state.search ?? this.router.state.latestLocation.search; | ||
const parentSearchInfo = this.parentMatch ? this.parentMatch.#resolveSearchInfo(opts) : { | ||
search: opts.location.search, | ||
routeSearch: opts.location.search | ||
}; | ||
try { | ||
const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch; | ||
let nextSearch = validator?.(parentSearch) ?? {}; | ||
this.store.setState(s => ({ | ||
...s, | ||
routeSearch: nextSearch, | ||
search: { | ||
...parentSearch, | ||
...nextSearch | ||
} | ||
})); | ||
componentTypes.map(async type => { | ||
const component = this.route.options[type]; | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component; | ||
} | ||
}); | ||
const parent = this.parentMatch; | ||
this.routeContext = this.route.options.getContext?.({ | ||
parentContext: parent?.routeContext, | ||
context: parent?.context, | ||
params: this.params, | ||
search: this.state.search | ||
}) || {}; | ||
this.context = parent ? { | ||
...parent.context, | ||
...this.routeContext | ||
} : { | ||
...this.router?.options.context, | ||
...this.routeContext | ||
const routeSearch = validator?.(parentSearchInfo.search) ?? {}; | ||
const search = { | ||
...parentSearchInfo.search, | ||
...routeSearch | ||
}; | ||
return { | ||
routeSearch, | ||
search | ||
}; | ||
} catch (err) { | ||
@@ -721,6 +721,37 @@ console.error(err); | ||
error.code = 'INVALID_SEARCH_PARAMS'; | ||
throw error; | ||
} | ||
}; | ||
#resolveInfo = opts => { | ||
const { | ||
search, | ||
routeSearch | ||
} = this.#resolveSearchInfo(opts); | ||
const routeContext = this.route.options.getContext?.({ | ||
parentContext: this.parentMatch?.routeContext ?? {}, | ||
context: this.parentMatch?.context ?? this.router?.options.context ?? {}, | ||
params: this.params, | ||
search | ||
}) || {}; | ||
const context = { | ||
...(this.parentMatch?.context ?? this.router?.options.context), | ||
...routeContext | ||
}; | ||
return { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
}; | ||
}; | ||
__load = async opts => { | ||
this.parentMatch = opts.parentMatch; | ||
let info; | ||
try { | ||
info = this.#resolveInfo(opts); | ||
} catch (err) { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'error', | ||
error: error | ||
error: err | ||
})); | ||
@@ -731,14 +762,21 @@ | ||
} | ||
}; | ||
cancel = () => { | ||
this.abortController?.abort(); | ||
}; | ||
load = async opts => { | ||
const { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext | ||
} = info; | ||
componentTypes.map(async type => { | ||
const component = this.route.options[type]; | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component; | ||
} | ||
}); | ||
// If the match is invalid, errored or idle, trigger it to load | ||
if (this.state.status !== 'pending') { | ||
await this.fetch(opts); | ||
if (this.state.status === 'pending') { | ||
return; | ||
} | ||
}; | ||
#latestId = ''; | ||
fetch = async opts => { | ||
// TODO: Should load promises be tracked based on location? | ||
this.__loadPromise = Promise.resolve().then(async () => { | ||
@@ -751,13 +789,12 @@ const loadId = '' + Date.now() + Math.random(); | ||
let latestPromise; | ||
this.store.batch(() => { | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'pending' | ||
})); | ||
} | ||
}); | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState(s => ({ | ||
...s, | ||
status: 'pending' | ||
})); | ||
} | ||
const componentsPromise = (async () => { | ||
@@ -778,7 +815,8 @@ // then run all component and data loaders in parallel | ||
params: this.params, | ||
search: this.state.search, | ||
routeSearch, | ||
search, | ||
signal: this.abortController.signal, | ||
preload: !!opts?.preload, | ||
routeContext: this.routeContext, | ||
context: this.context | ||
routeContext: routeContext, | ||
context: context | ||
}); | ||
@@ -811,2 +849,3 @@ } | ||
}; | ||
#latestId = ''; | ||
} | ||
@@ -1017,3 +1056,3 @@ | ||
try { | ||
await this.loadMatches(matches | ||
await this.loadMatches(matches, this.state.pendingLocation | ||
// opts | ||
@@ -1070,2 +1109,3 @@ ); | ||
}); | ||
const prevLocation = this.state.currentLocation; | ||
this.store.setState(s => ({ | ||
@@ -1079,3 +1119,8 @@ ...s, | ||
})); | ||
this.options.onRouteChange?.(); | ||
matches.forEach(match => { | ||
match.__commit(); | ||
}); | ||
if (prevLocation.href !== this.state.currentLocation.href) { | ||
this.options.onRouteChange?.(); | ||
} | ||
this.resolveNavigation(); | ||
@@ -1093,3 +1138,3 @@ }; | ||
}); | ||
await this.loadMatches(matches); | ||
await this.loadMatches(matches, next); | ||
return matches; | ||
@@ -1102,3 +1147,3 @@ }; | ||
}); | ||
await this.loadMatches(matches, { | ||
await this.loadMatches(matches, next, { | ||
preload: true | ||
@@ -1175,5 +1220,3 @@ }); | ||
}; | ||
loadMatches = async (resolvedMatches, opts) => { | ||
initMatches(resolvedMatches); | ||
loadMatches = async (resolvedMatches, location, opts) => { | ||
// Check each match middleware to see if the route can be accessed | ||
@@ -1194,19 +1237,12 @@ await Promise.all(resolvedMatches.map(async match => { | ||
const matchPromises = resolvedMatches.map(async (match, index) => { | ||
const prevMatch = resolvedMatches[1]; | ||
match.state.search; | ||
// if (opts?.filter && !opts.filter(match)) { | ||
// return | ||
// } | ||
match.load({ | ||
preload: opts?.preload | ||
const parentMatch = resolvedMatches[index - 1]; | ||
match.__load({ | ||
preload: opts?.preload, | ||
location, | ||
parentMatch | ||
}); | ||
if (match.state.status !== 'success' && match.__loadPromise) { | ||
// Wait for the first sign of activity from the match | ||
await match.__loadPromise; | ||
await match.__loadPromise; | ||
if (parentMatch) { | ||
await parentMatch.__loadPromise; | ||
} | ||
if (prevMatch) { | ||
await prevMatch.__loadPromise; | ||
} | ||
}); | ||
@@ -1273,3 +1309,2 @@ await Promise.all(matchPromises); | ||
if (opts?.includeSearch ?? true) { | ||
console.log(baseLocation.search, next.search, partialDeepEqual(baseLocation.search, next.search)); | ||
return partialDeepEqual(baseLocation.search, next.search) ? match : false; | ||
@@ -1289,4 +1324,2 @@ } | ||
preload, | ||
preloadMaxAge: userPreloadMaxAge, | ||
preloadGcMaxAge: userPreloadGcMaxAge, | ||
preloadDelay: userPreloadDelay, | ||
@@ -1411,3 +1444,2 @@ disabled | ||
}); | ||
initMatches(currentMatches); | ||
return { | ||
@@ -1551,10 +1583,2 @@ ...s, | ||
} | ||
function initMatches(matches) { | ||
matches.forEach((match, index) => { | ||
const parentMatch = matches[index - 1]; | ||
match.__init({ | ||
parentMatch | ||
}); | ||
}); | ||
} | ||
@@ -1561,0 +1585,0 @@ exports.RootRoute = RootRoute; |
@@ -11,3 +11,3 @@ /** | ||
*/ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).RouterCore={})}(this,(function(t){"use strict";function e(t,e){if(!t)throw new Error("Invariant failed")}const s="popstate";function a(t){let e=t.getLocation(),s=()=>{},a=new Set;const o=()=>{e=t.getLocation(),a.forEach((t=>t()))};return{get location(){return e},listen:e=>(0===a.size&&(s=t.listener(o)),a.add(e),()=>{a.delete(e),0===a.size&&s()}),push:(e,s)=>{t.pushState(e,s),o()},replace:(e,s)=>{t.replaceState(e,s),o()},go:e=>{t.go(e),o()},back:()=>{t.back(),o()},forward:()=>{t.forward(),o()}}}function o(t){const e=t?.getHref??(()=>`${window.location.pathname}${window.location.hash}${window.location.search}`),o=t?.createHref??(t=>t);return a({getLocation:()=>i(e(),history.state),listener:t=>(window.addEventListener(s,t),()=>{window.removeEventListener(s,t)}),pushState:(t,e)=>{window.history.pushState({...e,key:n()},"",o(t))},replaceState:(t,e)=>{window.history.replaceState({...e,key:n()},"",o(t))},back:()=>window.history.back(),forward:()=>window.history.forward(),go:t=>window.history.go(t)})}function r(t={initialEntries:["/"]}){const e=t.initialEntries;let s=t.initialIndex??e.length-1,o={};return a({getLocation:()=>i(e[s],o),listener:()=>()=>{},pushState:(t,a)=>{o={...a,key:n()},e.push(t),s++},replaceState:(t,a)=>{o={...a,key:n()},e[s]=t},back:()=>{s--},forward:()=>{s=Math.min(s+1,e.length-1)},go:t=>window.history.go(t)})}function i(t,e){let s=t.indexOf("#"),a=t.indexOf("?");return{href:t,pathname:t.substring(0,s>0?a>0?Math.min(s,a):s:a>0?a:t.length),hash:s>-1?t.substring(s,a):"",search:a>-1?t.substring(a):"",state:e}}function n(){return(Math.random()+1).toString(36).substring(7)}function h(t){return t[t.length-1]}function c(t,e){return"function"==typeof t?t(e):t}function u(t,e){return e.reduce(((e,s)=>(e[s]=t[s],e)),{})}function l(t,e){if(t===e)return t;const s=e,a=Array.isArray(t)&&Array.isArray(s);if(a||p(t)&&p(s)){const e=a?t.length:Object.keys(t).length,o=a?s:Object.keys(s),r=o.length,i=a?[]:{};let n=0;for(let e=0;e<r;e++){const r=a?e:o[e];i[r]=l(t[r],s[r]),i[r]===t[r]&&n++}return e===r&&n===e?t:i}return s}function p(t){if(!d(t))return!1;const e=t.constructor;if(void 0===e)return!0;const s=e.prototype;return!!d(s)&&!!s.hasOwnProperty("isPrototypeOf")}function d(t){return"[object Object]"===Object.prototype.toString.call(t)}function f(t,e){return t===e||typeof t==typeof e&&(p(t)&&p(e)?!Object.keys(e).some((s=>!f(t[s],e[s]))):!(!Array.isArray(t)||!Array.isArray(e))&&(t.length===e.length&&t.every(((t,s)=>f(t,e[s])))))}function m(t){return g(t.filter(Boolean).join("/"))}function g(t){return t.replace(/\/{2,}/g,"/")}function y(t){return"/"===t?t:t.replace(/^\/{1,}/,"")}function w(t){return"/"===t?t:t.replace(/\/{1,}$/,"")}function v(t){return w(y(t))}function b(t,e,s){e=e.replace(new RegExp(`^${t}`),"/"),s=s.replace(new RegExp(`^${t}`),"/");let a=L(e);const o=L(s);o.forEach(((t,e)=>{if("/"===t.value)e?e===o.length-1&&a.push(t):a=[t];else if(".."===t.value)a.length>1&&"/"===h(a)?.value&&a.pop(),a.pop();else{if("."===t.value)return;a.push(t)}}));return g(m([t,...a.map((t=>t.value))]))}function L(t){if(!t)return[];const e=[];if("/"===(t=g(t)).slice(0,1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),!t)return e;const s=t.split("/").filter(Boolean);return e.push(...s.map((t=>t.startsWith("*")?{type:"wildcard",value:t}:"$"===t.charAt(0)?{type:"param",value:t}:{type:"pathname",value:t}))),"/"===t.slice(-1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),e}function S(t,e,s){return m(L(t).map((t=>"*"!==t.value||s?"param"===t.type?e[t.value.substring(1)]??"":t.value:"")))}function P(t,e,s){const a=_(t,e,s);if(!s.to||a)return a??{}}function _(t,e,s){if(!e.startsWith(t))return;const a=L(e="/"!=t?e.substring(t.length):e),o=L(`${s.to??"*"}`),r={};return(()=>{for(let t=0;t<Math.max(a.length,o.length);t++){const e=a[t],i=o[t],n=t===o.length-1,h=t===a.length-1;if(i){if("wildcard"===i.type)return!!e?.value&&(r["*"]=m(a.slice(t).map((t=>t.value))),!0);if("pathname"===i.type){if("/"===i.value&&!e?.value)return!0;if(e)if(s.caseSensitive){if(i.value!==e.value)return!1}else if(i.value.toLowerCase()!==e.value.toLowerCase())return!1}if(!e)return!1;if("param"===i.type){if("/"===e?.value)return!1;"$"!==e.value.charAt(0)&&(r[i.value.substring(1)]=e.value)}}if(n&&!h)return!!s.fuzzy}return!0})()?r:void 0}function x(t,e){var s,a,o,r="";for(s in t)if(void 0!==(o=t[s]))if(Array.isArray(o))for(a=0;a<o.length;a++)r&&(r+="&"),r+=encodeURIComponent(s)+"="+encodeURIComponent(o[a]);else r&&(r+="&"),r+=encodeURIComponent(s)+"="+encodeURIComponent(o);return(e||"")+r}function E(t){if(!t)return"";var e=decodeURIComponent(t);return"false"!==e&&("true"===e||("0"===e.charAt(0)?e:0*+e==0?+e:e))}function R(t){for(var e,s,a={},o=t.split("&");e=o.shift();)void 0!==a[s=(e=e.split("=")).shift()]?a[s]=[].concat(a[s],E(e.shift())):a[s]=E(e.shift());return a}const M="__root__";class C{constructor(t){this.options=t||{},this.isRoot=!t?.getParentRoute}init=t=>{this.originalIndex=t.originalIndex,this.router=t.router;const s=this.options,a=!s?.path&&!s?.id,o=this.options?.getParentRoute?.();a?this.path=M:e(o);let r=a?M:s.path;r&&"/"!==r&&(r=v(r));const i=s?.id||r;let n=a?M:m([o.id===M?"":o.id,i]);r===M&&(r="/"),n!==M&&(n=m(["/",n]));const h=n===M?"/":w(m([o.fullPath,r]));this.path=r,this.id=n,this.fullPath=h};addChildren=t=>(this.children=t,this);generate=t=>{e(!1)}}class A extends C{constructor(t){super(t)}static withRouterContext=()=>t=>new A(t)} | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).RouterCore={})}(this,(function(t){"use strict";function e(t,e){if(!t)throw new Error("Invariant failed")}const s="popstate";function a(t){let e=t.getLocation(),s=()=>{},a=new Set;const r=()=>{e=t.getLocation(),a.forEach((t=>t()))};return{get location(){return e},listen:e=>(0===a.size&&(s=t.listener(r)),a.add(e),()=>{a.delete(e),0===a.size&&s()}),push:(e,s)=>{t.pushState(e,s),r()},replace:(e,s)=>{t.replaceState(e,s),r()},go:e=>{t.go(e),r()},back:()=>{t.back(),r()},forward:()=>{t.forward(),r()}}}function r(t){const e=t?.getHref??(()=>`${window.location.pathname}${window.location.hash}${window.location.search}`),r=t?.createHref??(t=>t);return a({getLocation:()=>n(e(),history.state),listener:t=>(window.addEventListener(s,t),()=>{window.removeEventListener(s,t)}),pushState:(t,e)=>{window.history.pushState({...e,key:i()},"",r(t))},replaceState:(t,e)=>{window.history.replaceState({...e,key:i()},"",r(t))},back:()=>window.history.back(),forward:()=>window.history.forward(),go:t=>window.history.go(t)})}function o(t={initialEntries:["/"]}){const e=t.initialEntries;let s=t.initialIndex??e.length-1,r={};return a({getLocation:()=>n(e[s],r),listener:()=>()=>{},pushState:(t,a)=>{r={...a,key:i()},e.push(t),s++},replaceState:(t,a)=>{r={...a,key:i()},e[s]=t},back:()=>{s--},forward:()=>{s=Math.min(s+1,e.length-1)},go:t=>window.history.go(t)})}function n(t,e){let s=t.indexOf("#"),a=t.indexOf("?");return{href:t,pathname:t.substring(0,s>0?a>0?Math.min(s,a):s:a>0?a:t.length),hash:s>-1?t.substring(s,a):"",search:a>-1?t.substring(a):"",state:e}}function i(){return(Math.random()+1).toString(36).substring(7)}function h(t){return t[t.length-1]}function c(t,e){return"function"==typeof t?t(e):t}function u(t,e){return e.reduce(((e,s)=>(e[s]=t[s],e)),{})}function l(t,e){if(t===e)return t;const s=e,a=Array.isArray(t)&&Array.isArray(s);if(a||p(t)&&p(s)){const e=a?t.length:Object.keys(t).length,r=a?s:Object.keys(s),o=r.length,n=a?[]:{};let i=0;for(let e=0;e<o;e++){const o=a?e:r[e];n[o]=l(t[o],s[o]),n[o]===t[o]&&i++}return e===o&&i===e?t:n}return s}function p(t){if(!d(t))return!1;const e=t.constructor;if(void 0===e)return!0;const s=e.prototype;return!!d(s)&&!!s.hasOwnProperty("isPrototypeOf")}function d(t){return"[object Object]"===Object.prototype.toString.call(t)}function f(t,e){return t===e||typeof t==typeof e&&(p(t)&&p(e)?!Object.keys(e).some((s=>!f(t[s],e[s]))):!(!Array.isArray(t)||!Array.isArray(e))&&(t.length===e.length&&t.every(((t,s)=>f(t,e[s])))))}function m(t){return y(t.filter(Boolean).join("/"))}function y(t){return t.replace(/\/{2,}/g,"/")}function g(t){return"/"===t?t:t.replace(/^\/{1,}/,"")}function w(t){return"/"===t?t:t.replace(/\/{1,}$/,"")}function v(t){return w(g(t))}function S(t,e,s){e=e.replace(new RegExp(`^${t}`),"/"),s=s.replace(new RegExp(`^${t}`),"/");let a=b(e);const r=b(s);r.forEach(((t,e)=>{if("/"===t.value)e?e===r.length-1&&a.push(t):a=[t];else if(".."===t.value)a.length>1&&"/"===h(a)?.value&&a.pop(),a.pop();else{if("."===t.value)return;a.push(t)}}));return y(m([t,...a.map((t=>t.value))]))}function b(t){if(!t)return[];const e=[];if("/"===(t=y(t)).slice(0,1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),!t)return e;const s=t.split("/").filter(Boolean);return e.push(...s.map((t=>t.startsWith("*")?{type:"wildcard",value:t}:"$"===t.charAt(0)?{type:"param",value:t}:{type:"pathname",value:t}))),"/"===t.slice(-1)&&(t=t.substring(1),e.push({type:"pathname",value:"/"})),e}function L(t,e,s){return m(b(t).map((t=>"*"!==t.value||s?"param"===t.type?e[t.value.substring(1)]??"":t.value:"")))}function P(t,e,s){const a=_(t,e,s);if(!s.to||a)return a??{}}function _(t,e,s){if(!e.startsWith(t))return;const a=b(e="/"!=t?e.substring(t.length):e),r=b(`${s.to??"*"}`),o={};return(()=>{for(let t=0;t<Math.max(a.length,r.length);t++){const e=a[t],n=r[t],i=t===r.length-1,h=t===a.length-1;if(n){if("wildcard"===n.type)return!!e?.value&&(o["*"]=m(a.slice(t).map((t=>t.value))),!0);if("pathname"===n.type){if("/"===n.value&&!e?.value)return!0;if(e)if(s.caseSensitive){if(n.value!==e.value)return!1}else if(n.value.toLowerCase()!==e.value.toLowerCase())return!1}if(!e)return!1;if("param"===n.type){if("/"===e?.value)return!1;"$"!==e.value.charAt(0)&&(o[n.value.substring(1)]=e.value)}}if(i&&!h)return!!s.fuzzy}return!0})()?o:void 0}function x(t,e){var s,a,r,o="";for(s in t)if(void 0!==(r=t[s]))if(Array.isArray(r))for(a=0;a<r.length;a++)o&&(o+="&"),o+=encodeURIComponent(s)+"="+encodeURIComponent(r[a]);else o&&(o+="&"),o+=encodeURIComponent(s)+"="+encodeURIComponent(r);return(e||"")+o}function E(t){if(!t)return"";var e=decodeURIComponent(t);return"false"!==e&&("true"===e||("0"===e.charAt(0)?e:0*+e==0?+e:e))}function R(t){for(var e,s,a={},r=t.split("&");e=r.shift();)void 0!==a[s=(e=e.split("=")).shift()]?a[s]=[].concat(a[s],E(e.shift())):a[s]=E(e.shift());return a}const M="__root__";class C{constructor(t){this.options=t||{},this.isRoot=!t?.getParentRoute}init=t=>{this.originalIndex=t.originalIndex,this.router=t.router;const s=this.options,a=!s?.path&&!s?.id,r=this.options?.getParentRoute?.();a?this.path=M:e(r);let o=a?M:s.path;o&&"/"!==o&&(o=v(o));const n=s?.id||o;let i=a?M:m([r.id===M?"":r.id,n]);o===M&&(o="/"),i!==M&&(i=m(["/",i]));const h=i===M?"/":w(m([r.fullPath,o]));this.path=o,this.id=i,this.fullPath=h};addChildren=t=>(this.children=t,this);generate=t=>{e(!1)}}class I extends C{constructor(t){super(t)}static withRouterContext=()=>t=>new I(t)} | ||
/** | ||
@@ -22,3 +22,3 @@ * store | ||
* @license MIT | ||
*/class ${listeners=new Set;batching=!1;queue=[];constructor(t,e){this.state=t,this.options=e}subscribe=t=>{this.listeners.add(t);const e=this.options?.onSubscribe?.(t,this);return()=>{this.listeners.delete(t),e?.()}};setState=t=>{const e=this.state;this.state=this.options?.updateFn?this.options.updateFn(e)(t):t(e),this.state!==e&&(this.options?.onUpdate?.(this.state,e),this.queue.push((()=>{this.listeners.forEach((t=>t(this.state,e)))})),this.#t())};#t=()=>{this.batching||(this.queue.forEach((t=>t())),this.queue=[])};batch=t=>{this.batching=!0,t(),this.batching=!1,this.#t()}}const k=["component","errorComponent","pendingComponent"];class F{abortController=new AbortController;onLoaderDataListeners=new Set;constructor(t,e,s){Object.assign(this,{route:e,router:t,id:s.id,pathname:s.pathname,params:s.params,store:new $({updatedAt:0,routeSearch:{},search:{},status:"idle"},{onUpdate:t=>{this.state=t}})}),this.state=this.store.state,this.#e()||this.store.setState((t=>({...t,status:"success"})))}#e=()=>!(!this.route.options.onLoad&&!k.some((t=>this.route.options[t]?.preload)));__init=t=>{this.parentMatch=t.parentMatch;const e=this.parentMatch?.state.search??this.router.state.latestLocation.search;try{let t=("object"==typeof this.route.options.validateSearch?this.route.options.validateSearch.parse:this.route.options.validateSearch)?.(e)??{};this.store.setState((s=>({...s,routeSearch:t,search:{...e,...t}}))),k.map((async t=>{const e=this.route.options[t];"function"!=typeof this[t]&&(this[t]=e)}));const s=this.parentMatch;this.routeContext=this.route.options.getContext?.({parentContext:s?.routeContext,context:s?.context,params:this.params,search:this.state.search})||{},this.context=s?{...s.context,...this.routeContext}:{...this.router?.options.context,...this.routeContext}}catch(t){console.error(t);const e=new Error("Invalid search params found",{cause:t});return e.code="INVALID_SEARCH_PARAMS",void this.store.setState((t=>({...t,status:"error",error:e})))}};cancel=()=>{this.abortController?.abort()};load=async t=>{"pending"!==this.state.status&&await this.fetch(t)};#s="";fetch=async t=>(this.__loadPromise=Promise.resolve().then((async()=>{const e=""+Date.now()+Math.random();this.#s=e;const s=()=>e!==this.#s?this.__loadPromise:void 0;let a;this.store.batch((()=>{"idle"===this.state.status&&this.store.setState((t=>({...t,status:"pending"})))}));const o=(async()=>{await Promise.all(k.map((async t=>{const e=this.route.options[t];this[t]?.preload&&(this[t]=await this.router.options.loadComponent(e))})))})(),r=Promise.resolve().then((()=>{if(this.route.options.onLoad)return this.route.options.onLoad({params:this.params,search:this.state.search,signal:this.abortController.signal,preload:!!t?.preload,routeContext:this.routeContext,context:this.context})}));try{if(await o,await r,a=s())return await a;this.store.setState((t=>({...t,error:void 0,status:"success",updatedAt:Date.now()})))}catch(t){this.store.setState((e=>({...e,error:t,status:"error",updatedAt:Date.now()})))}finally{delete this.__loadPromise}})),this.__loadPromise)}const I=j(JSON.parse),T=D(JSON.stringify);function j(t){return e=>{"?"===e.substring(0,1)&&(e=e.substring(1));let s=R(e);for(let e in s){const a=s[e];if("string"==typeof a)try{s[e]=t(a)}catch(t){}}return s}}function D(t){return e=>{(e={...e})&&Object.keys(e).forEach((s=>{const a=e[s];if(void 0===a||void 0===a)delete e[s];else if(a&&"object"==typeof a&&null!==a)try{e[s]=t(a)}catch(t){}}));const s=x(e).toString();return s?`?${s}`:""}}const O=async({router:t,routeMatch:e})=>{const s=t.buildNext({to:".",search:t=>({...t??{},__data:{matchId:e.id}})}),a=await fetch(s.href,{method:"GET",signal:e.abortController.signal});if(a.ok)return a.json();throw new Error("Failed to fetch match data")};const H="undefined"==typeof window||!window.document.createElement;function N(){return{status:"idle",latestLocation:null,currentLocation:null,currentMatches:[],lastUpdated:Date.now()}}function U(t){t.forEach(((e,s)=>{const a=t[s-1];e.__init({parentMatch:a})}))}t.RootRoute=A,t.Route=C,t.RouteMatch=F,t.Router=class{#a;startedLoadingAt=Date.now();resolveNavigation=()=>{};constructor(t){this.options={defaultPreloadDelay:50,context:void 0,...t,stringifySearch:t?.stringifySearch??T,parseSearch:t?.parseSearch??I,fetchServerDataFn:t?.fetchServerDataFn??O},this.store=new $(N(),{onUpdate:t=>{this.state=t}}),this.state=this.store.state,this.basepath="",this.update(t),this.options.Router?.(this)}reset=()=>{this.store.setState((t=>Object.assign(t,N())))};mount=()=>{if(!H){this.state.currentMatches.length||this.load();const t="visibilitychange",e="focus";return window.addEventListener&&(window.addEventListener(t,this.#o,!1),window.addEventListener(e,this.#o,!1)),()=>{window.removeEventListener&&(window.removeEventListener(t,this.#o),window.removeEventListener(e,this.#o))}}return()=>{}};update=t=>{if(Object.assign(this.options,t),!this.history||this.options.history&&this.options.history!==this.history){this.#a&&this.#a(),this.history=this.options.history??(H?r():o());const t=this.#r();this.store.setState((e=>({...e,latestLocation:t,currentLocation:t}))),this.#a=this.history.listen((()=>{this.load({next:this.#r(this.state.latestLocation)})}))}const{basepath:e,routeTree:s}=this.options;return this.basepath=`/${v(e??"")??""}`,s&&(this.routesById={},this.routeTree=this.#i(s)),this};buildNext=t=>{const e=this.#n(t),s=this.matchRoutes(e.pathname),a=s.map((t=>t.route.options.preSearchFilters??[])).flat().filter(Boolean),o=s.map((t=>t.route.options.postSearchFilters??[])).flat().filter(Boolean);return this.#n({...t,__preSearchFilters:a,__postSearchFilters:o})};cancelMatches=()=>{[...this.state.currentMatches,...this.state.pendingMatches||[]].forEach((t=>{t.cancel()}))};load=async t=>{let s=Date.now();const a=s;let o;this.startedLoadingAt=a,this.cancelMatches(),this.store.batch((()=>{t?.next&&this.store.setState((e=>({...e,latestLocation:t.next}))),o=this.matchRoutes(this.state.latestLocation.pathname,{strictParseParams:!0}),this.store.setState((t=>({...t,status:"pending",pendingMatches:o,pendingLocation:this.state.latestLocation})))}));try{await this.loadMatches(o)}catch(t){console.warn(t),e(!1)}if(this.startedLoadingAt!==a)return this.navigationPromise;const r=this.state.currentMatches,i=[],n=[];r.forEach((t=>{o.find((e=>e.id===t.id))?n.push(t):i.push(t)}));const h=o.filter((t=>!r.find((e=>e.id===t.id))));s=Date.now(),i.forEach((t=>{t.__onExit?.({params:t.params,search:t.state.routeSearch}),"error"===t.state.status&&this.store.setState((t=>({...t,status:"idle",error:void 0})))})),n.forEach((t=>{t.route.options.onTransition?.({params:t.params,search:t.state.routeSearch})})),h.forEach((t=>{t.__onExit=t.route.options.onLoaded?.({params:t.params,search:t.state.search})})),this.store.setState((t=>({...t,status:"idle",currentLocation:this.state.latestLocation,currentMatches:o,pendingLocation:void 0,pendingMatches:void 0}))),this.options.onRouteChange?.(),this.resolveNavigation()};getRoute=t=>{const s=this.routesById[t];return e(s),s};loadRoute=async(t=this.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s),s};preloadRoute=async(t=this.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s,{preload:!0}),s};matchRoutes=(t,e)=>{const s=[];if(!this.routeTree)return s;const a=[...this.state.currentMatches,...this.state.pendingMatches??[]],o=async r=>{let i=h(s)?.params??{};const n=this.options.filterRoutes?.(r)??r;let c=[];const u=(s,a)=>(a.some((a=>{const o=a.children;if(!a.path&&o?.length)return u([...c,a],o);const r=!("/"===a.path&&!o?.length),n=P(this.basepath,t,{to:a.fullPath,fuzzy:r,caseSensitive:a.options.caseSensitive??this.options.caseSensitive});if(n){let t;try{t=a.options.parseParams?.(n)??n}catch(t){if(e?.strictParseParams)throw t}i={...i,...t}}return n&&(c=[...s,a]),!!c.length})),!!c.length);if(u([],n),!c.length)return;c.forEach((t=>{const e=S(t.path,i),o=S(t.id,i,!0),r=a.find((t=>t.id===o))||new F(this,t,{id:o,params:i,pathname:m([this.basepath,e])});s.push(r)}));const l=h(c).children;l?.length&&o(l)};return o([this.routeTree]),s};loadMatches=async(t,e)=>{U(t),await Promise.all(t.map((async t=>{try{await(t.route.options.beforeLoad?.({router:this,match:t}))}catch(s){throw e?.preload||t.route.options.onLoadError?.(s),s}})));const s=t.map((async(s,a)=>{const o=t[1];s.state.search,s.load({preload:e?.preload}),"success"!==s.state.status&&s.__loadPromise&&await s.__loadPromise,o&&await o.__loadPromise}));await Promise.all(s)};reload=()=>{this.navigate({fromCurrent:!0,replace:!0,search:!0})};resolvePath=(t,e)=>b(this.basepath,t,g(e));navigate=async({from:t,to:s="",search:a,hash:o,replace:r,params:i})=>{const n=String(s),h=void 0===t?t:String(t);let c;try{new URL(`${n}`),c=!0}catch(t){}return e(!c),this.#h({from:h,to:n,search:a,hash:o,replace:r,params:i})};matchRoute=(t,e)=>{t={...t,to:t.to?this.resolvePath(t.from??"",t.to):void 0};const s=this.buildNext(t),a=e?.pending?this.state.pendingLocation:this.state.currentLocation;if(!a)return!1;const o=P(this.basepath,a.pathname,{...e,to:s.pathname});return!!o&&(e?.includeSearch??1?(console.log(a.search,s.search,f(a.search,s.search)),!!f(a.search,s.search)&&o):o)};buildLink=({from:t,to:e=".",search:s,params:a,hash:o,target:r,replace:i,activeOptions:n,preload:h,preloadMaxAge:c,preloadGcMaxAge:u,preloadDelay:l,disabled:p})=>{try{return new URL(`${e}`),{type:"external",href:e}}catch(t){}const d={from:t,to:e,search:s,params:a,hash:o,replace:i},m=this.buildNext(d);h=h??this.options.defaultPreload;const g=l??this.options.defaultPreloadDelay??0,y=this.state.currentLocation.pathname.split("/"),w=m.pathname.split("/").every(((t,e)=>t===y[e])),v=n?.exact?this.state.currentLocation.pathname===m.pathname:w,b=!n?.includeHash||this.state.currentLocation.hash===m.hash,L=!(n?.includeSearch??1)||f(this.state.currentLocation.search,m.search);return{type:"internal",next:m,handleFocus:t=>{h&&this.preloadRoute(d).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))},handleClick:t=>{p||function(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}(t)||t.defaultPrevented||r&&"_self"!==r||0!==t.button||(t.preventDefault(),this.#h(d))},handleEnter:t=>{const e=t.target||{};if(h){if(e.preloadTimeout)return;e.preloadTimeout=setTimeout((()=>{e.preloadTimeout=null,this.preloadRoute(d).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))}),g)}},handleLeave:t=>{const e=t.target||{};e.preloadTimeout&&(clearTimeout(e.preloadTimeout),e.preloadTimeout=null)},isActive:v&&b&&L,disabled:p}};dehydrate=()=>({state:{...u(this.state,["latestLocation","currentLocation","status","lastUpdated"]),currentMatches:this.state.currentMatches.map((t=>({id:t.id,state:{status:t.state.status}})))}});hydrate=t=>{this.store.setState((s=>{const a=this.matchRoutes(t.state.latestLocation.pathname,{strictParseParams:!0});return a.forEach(((s,a)=>{const o=t.state.currentMatches[a];e(o&&o.id===s.id),s.store.setState((t=>({...t,...o.state})))})),U(a),{...s,...t.state,currentMatches:a}}))};#i=t=>{const e=t=>{t.forEach(((t,s)=>{t.init({originalIndex:s,router:this});if(this.routesById[t.id])throw new Error;this.routesById[t.id]=t;const a=t.children;a?.length&&e(a)}))};return e([t]),t};#r=t=>{let{pathname:e,search:s,hash:a,state:o}=this.history.location;const r=this.options.parseSearch(s);return{pathname:e,searchStr:s,search:l(t?.search,r),hash:a.split("#").reverse()[0]??"",href:`${e}${s}${a}`,state:o,key:o?.key||"__init__"}};#o=()=>{this.load()};#n=(t={})=>{t.fromCurrent=t.fromCurrent??""===t.to;const e=t.fromCurrent?this.state.latestLocation.pathname:t.from??this.state.latestLocation.pathname;let s=b(this.basepath??"/",e,`${t.to??""}`);const a=this.matchRoutes(this.state.latestLocation.pathname,{strictParseParams:!0}),o=this.matchRoutes(s),r={...h(a)?.params};let i=!0===(t.params??!0)?r:c(t.params,r);i&&o.map((t=>t.route.options.stringifyParams)).filter(Boolean).forEach((t=>{Object.assign({},i,t(i))})),s=S(s,i??{});const n=t.__preSearchFilters?.length?t.__preSearchFilters?.reduce(((t,e)=>e(t)),this.state.latestLocation.search):this.state.latestLocation.search,u=!0===t.search?n:t.search?c(t.search,n)??{}:t.__preSearchFilters?.length?n:{},p=t.__postSearchFilters?.length?t.__postSearchFilters.reduce(((t,e)=>e(t)),u):u,d=l(this.state.latestLocation.search,p),f=this.options.stringifySearch(d);let m=!0===t.hash?this.state.latestLocation.hash:c(t.hash,this.state.latestLocation.hash);return m=m?`#${m}`:"",{pathname:s,search:d,searchStr:f,state:this.state.latestLocation.state,hash:m,href:`${s}${f}${m}`,key:t.key}};#h=t=>{const e=this.buildNext(t),s=""+Date.now()+Math.random();this.navigateTimeout&&clearTimeout(this.navigateTimeout);let a="replace";t.replace||(a="push");this.state.latestLocation.href===e.href&&!e.key&&(a="replace");const o=`${e.pathname}${e.searchStr}${e.hash?`#${e.hash}`:""}`;return this.history["push"===a?"push":"replace"](o,{id:s,...e.state}),this.navigationPromise=new Promise((t=>{const e=this.resolveNavigation;this.resolveNavigation=()=>{e(),t()}}))}},t.cleanPath=g,t.createBrowserHistory=o,t.createHashHistory=function(){return o({getHref:()=>window.location.hash.substring(1),createHref:t=>`#${t}`})},t.createMemoryHistory=r,t.decode=R,t.defaultFetchServerDataFn=O,t.defaultParseSearch=I,t.defaultStringifySearch=T,t.encode=x,t.functionalUpdate=c,t.interpolatePath=S,t.invariant=e,t.isPlainObject=p,t.joinPaths=m,t.last=h,t.matchByPath=_,t.matchPathname=P,t.parsePathname=L,t.parseSearchWith=j,t.partialDeepEqual=f,t.pick=u,t.replaceEqualDeep=l,t.resolvePath=b,t.rootRouteId=M,t.stringifySearchWith=D,t.trimPath=v,t.trimPathLeft=y,t.trimPathRight=w,t.warning=function(t,e){if(t){"undefined"!=typeof console&&console.warn(e);try{throw new Error(e)}catch{}}return!0},Object.defineProperty(t,"__esModule",{value:!0})})); | ||
*/class ${listeners=new Set;batching=!1;queue=[];constructor(t,e){this.state=t,this.options=e}subscribe=t=>{this.listeners.add(t);const e=this.options?.onSubscribe?.(t,this);return()=>{this.listeners.delete(t),e?.()}};setState=t=>{const e=this.state;this.state=this.options?.updateFn?this.options.updateFn(e)(t):t(e),this.state!==e&&(this.options?.onUpdate?.(this.state,e),this.queue.push((()=>{this.listeners.forEach((t=>t(this.state,e)))})),this.#t())};#t=()=>{this.batching||(this.queue.forEach((t=>t())),this.queue=[])};batch=t=>{this.batching=!0,t(),this.batching=!1,this.#t()}}const A=["component","errorComponent","pendingComponent"];class k{abortController=new AbortController;onLoaderDataListeners=new Set;constructor(t,e,s){Object.assign(this,{route:e,router:t,id:s.id,pathname:s.pathname,params:s.params,store:new $({updatedAt:0,routeSearch:{},search:{},status:"idle"},{onUpdate:t=>{this.state=t}})}),this.state=this.store.state,this.#e()||this.store.setState((t=>({...t,status:"success"})))}#e=()=>!(!this.route.options.onLoad&&!A.some((t=>this.route.options[t]?.preload)));__commit=()=>{const{routeSearch:t,search:e,context:s,routeContext:a}=this.#s({location:this.router.state.currentLocation});this.context=s,this.routeContext=a,this.store.setState((s=>({...s,routeSearch:l(s.routeSearch,t),search:l(s.search,e)})))};cancel=()=>{this.abortController?.abort()};#a=t=>{const e=this.parentMatch?this.parentMatch.#a(t):{search:t.location.search,routeSearch:t.location.search};try{const t=("object"==typeof this.route.options.validateSearch?this.route.options.validateSearch.parse:this.route.options.validateSearch)?.(e.search)??{};return{routeSearch:t,search:{...e.search,...t}}}catch(t){console.error(t);const e=new Error("Invalid search params found",{cause:t});throw e.code="INVALID_SEARCH_PARAMS",e}};#s=t=>{const{search:e,routeSearch:s}=this.#a(t),a=this.route.options.getContext?.({parentContext:this.parentMatch?.routeContext??{},context:this.parentMatch?.context??this.router?.options.context??{},params:this.params,search:e})||{};return{routeSearch:s,search:e,context:{...this.parentMatch?.context??this.router?.options.context,...a},routeContext:a}};__load=async t=>{let e;this.parentMatch=t.parentMatch;try{e=this.#s(t)}catch(t){return void this.store.setState((e=>({...e,status:"error",error:t})))}const{routeSearch:s,search:a,context:r,routeContext:o}=e;if(A.map((async t=>{const e=this.route.options[t];"function"!=typeof this[t]&&(this[t]=e)})),"pending"!==this.state.status)return this.__loadPromise=Promise.resolve().then((async()=>{const e=""+Date.now()+Math.random();this.#r=e;const n=()=>e!==this.#r?this.__loadPromise:void 0;let i;"idle"===this.state.status&&this.store.setState((t=>({...t,status:"pending"})));const h=(async()=>{await Promise.all(A.map((async t=>{const e=this.route.options[t];this[t]?.preload&&(this[t]=await this.router.options.loadComponent(e))})))})(),c=Promise.resolve().then((()=>{if(this.route.options.onLoad)return this.route.options.onLoad({params:this.params,routeSearch:s,search:a,signal:this.abortController.signal,preload:!!t?.preload,routeContext:o,context:r})}));try{if(await h,await c,i=n())return await i;this.store.setState((t=>({...t,error:void 0,status:"success",updatedAt:Date.now()})))}catch(t){this.store.setState((e=>({...e,error:t,status:"error",updatedAt:Date.now()})))}finally{delete this.__loadPromise}})),this.__loadPromise};#r=""}const F=j(JSON.parse),T=D(JSON.stringify);function j(t){return e=>{"?"===e.substring(0,1)&&(e=e.substring(1));let s=R(e);for(let e in s){const a=s[e];if("string"==typeof a)try{s[e]=t(a)}catch(t){}}return s}}function D(t){return e=>{(e={...e})&&Object.keys(e).forEach((s=>{const a=e[s];if(void 0===a||void 0===a)delete e[s];else if(a&&"object"==typeof a&&null!==a)try{e[s]=t(a)}catch(t){}}));const s=x(e).toString();return s?`?${s}`:""}}const O=async({router:t,routeMatch:e})=>{const s=t.buildNext({to:".",search:t=>({...t??{},__data:{matchId:e.id}})}),a=await fetch(s.href,{method:"GET",signal:e.abortController.signal});if(a.ok)return a.json();throw new Error("Failed to fetch match data")};const H="undefined"==typeof window||!window.document.createElement;function N(){return{status:"idle",latestLocation:null,currentLocation:null,currentMatches:[],lastUpdated:Date.now()}}t.RootRoute=I,t.Route=C,t.RouteMatch=k,t.Router=class{#o;startedLoadingAt=Date.now();resolveNavigation=()=>{};constructor(t){this.options={defaultPreloadDelay:50,context:void 0,...t,stringifySearch:t?.stringifySearch??T,parseSearch:t?.parseSearch??F,fetchServerDataFn:t?.fetchServerDataFn??O},this.store=new $(N(),{onUpdate:t=>{this.state=t}}),this.state=this.store.state,this.basepath="",this.update(t),this.options.Router?.(this)}reset=()=>{this.store.setState((t=>Object.assign(t,N())))};mount=()=>{if(!H){this.state.currentMatches.length||this.load();const t="visibilitychange",e="focus";return window.addEventListener&&(window.addEventListener(t,this.#n,!1),window.addEventListener(e,this.#n,!1)),()=>{window.removeEventListener&&(window.removeEventListener(t,this.#n),window.removeEventListener(e,this.#n))}}return()=>{}};update=t=>{if(Object.assign(this.options,t),!this.history||this.options.history&&this.options.history!==this.history){this.#o&&this.#o(),this.history=this.options.history??(H?o():r());const t=this.#i();this.store.setState((e=>({...e,latestLocation:t,currentLocation:t}))),this.#o=this.history.listen((()=>{this.load({next:this.#i(this.state.latestLocation)})}))}const{basepath:e,routeTree:s}=this.options;return this.basepath=`/${v(e??"")??""}`,s&&(this.routesById={},this.routeTree=this.#h(s)),this};buildNext=t=>{const e=this.#c(t),s=this.matchRoutes(e.pathname),a=s.map((t=>t.route.options.preSearchFilters??[])).flat().filter(Boolean),r=s.map((t=>t.route.options.postSearchFilters??[])).flat().filter(Boolean);return this.#c({...t,__preSearchFilters:a,__postSearchFilters:r})};cancelMatches=()=>{[...this.state.currentMatches,...this.state.pendingMatches||[]].forEach((t=>{t.cancel()}))};load=async t=>{let s=Date.now();const a=s;let r;this.startedLoadingAt=a,this.cancelMatches(),this.store.batch((()=>{t?.next&&this.store.setState((e=>({...e,latestLocation:t.next}))),r=this.matchRoutes(this.state.latestLocation.pathname,{strictParseParams:!0}),this.store.setState((t=>({...t,status:"pending",pendingMatches:r,pendingLocation:this.state.latestLocation})))}));try{await this.loadMatches(r,this.state.pendingLocation)}catch(t){console.warn(t),e(!1)}if(this.startedLoadingAt!==a)return this.navigationPromise;const o=this.state.currentMatches,n=[],i=[];o.forEach((t=>{r.find((e=>e.id===t.id))?i.push(t):n.push(t)}));const h=r.filter((t=>!o.find((e=>e.id===t.id))));s=Date.now(),n.forEach((t=>{t.__onExit?.({params:t.params,search:t.state.routeSearch}),"error"===t.state.status&&this.store.setState((t=>({...t,status:"idle",error:void 0})))})),i.forEach((t=>{t.route.options.onTransition?.({params:t.params,search:t.state.routeSearch})})),h.forEach((t=>{t.__onExit=t.route.options.onLoaded?.({params:t.params,search:t.state.search})}));const c=this.state.currentLocation;this.store.setState((t=>({...t,status:"idle",currentLocation:this.state.latestLocation,currentMatches:r,pendingLocation:void 0,pendingMatches:void 0}))),r.forEach((t=>{t.__commit()})),c.href!==this.state.currentLocation.href&&this.options.onRouteChange?.(),this.resolveNavigation()};getRoute=t=>{const s=this.routesById[t];return e(s),s};loadRoute=async(t=this.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s,e),s};preloadRoute=async(t=this.state.latestLocation)=>{const e=this.buildNext(t),s=this.matchRoutes(e.pathname,{strictParseParams:!0});return await this.loadMatches(s,e,{preload:!0}),s};matchRoutes=(t,e)=>{const s=[];if(!this.routeTree)return s;const a=[...this.state.currentMatches,...this.state.pendingMatches??[]],r=async o=>{let n=h(s)?.params??{};const i=this.options.filterRoutes?.(o)??o;let c=[];const u=(s,a)=>(a.some((a=>{const r=a.children;if(!a.path&&r?.length)return u([...c,a],r);const o=!("/"===a.path&&!r?.length),i=P(this.basepath,t,{to:a.fullPath,fuzzy:o,caseSensitive:a.options.caseSensitive??this.options.caseSensitive});if(i){let t;try{t=a.options.parseParams?.(i)??i}catch(t){if(e?.strictParseParams)throw t}n={...n,...t}}return i&&(c=[...s,a]),!!c.length})),!!c.length);if(u([],i),!c.length)return;c.forEach((t=>{const e=L(t.path,n),r=L(t.id,n,!0),o=a.find((t=>t.id===r))||new k(this,t,{id:r,params:n,pathname:m([this.basepath,e])});s.push(o)}));const l=h(c).children;l?.length&&r(l)};return r([this.routeTree]),s};loadMatches=async(t,e,s)=>{await Promise.all(t.map((async t=>{try{await(t.route.options.beforeLoad?.({router:this,match:t}))}catch(e){throw s?.preload||t.route.options.onLoadError?.(e),e}})));const a=t.map((async(a,r)=>{const o=t[r-1];a.__load({preload:s?.preload,location:e,parentMatch:o}),await a.__loadPromise,o&&await o.__loadPromise}));await Promise.all(a)};reload=()=>{this.navigate({fromCurrent:!0,replace:!0,search:!0})};resolvePath=(t,e)=>S(this.basepath,t,y(e));navigate=async({from:t,to:s="",search:a,hash:r,replace:o,params:n})=>{const i=String(s),h=void 0===t?t:String(t);let c;try{new URL(`${i}`),c=!0}catch(t){}return e(!c),this.#u({from:h,to:i,search:a,hash:r,replace:o,params:n})};matchRoute=(t,e)=>{t={...t,to:t.to?this.resolvePath(t.from??"",t.to):void 0};const s=this.buildNext(t),a=e?.pending?this.state.pendingLocation:this.state.currentLocation;if(!a)return!1;const r=P(this.basepath,a.pathname,{...e,to:s.pathname});return!!r&&(e?.includeSearch??1?!!f(a.search,s.search)&&r:r)};buildLink=({from:t,to:e=".",search:s,params:a,hash:r,target:o,replace:n,activeOptions:i,preload:h,preloadDelay:c,disabled:u})=>{try{return new URL(`${e}`),{type:"external",href:e}}catch(t){}const l={from:t,to:e,search:s,params:a,hash:r,replace:n},p=this.buildNext(l);h=h??this.options.defaultPreload;const d=c??this.options.defaultPreloadDelay??0,m=this.state.currentLocation.pathname.split("/"),y=p.pathname.split("/").every(((t,e)=>t===m[e])),g=i?.exact?this.state.currentLocation.pathname===p.pathname:y,w=!i?.includeHash||this.state.currentLocation.hash===p.hash,v=!(i?.includeSearch??1)||f(this.state.currentLocation.search,p.search);return{type:"internal",next:p,handleFocus:t=>{h&&this.preloadRoute(l).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))},handleClick:t=>{u||function(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}(t)||t.defaultPrevented||o&&"_self"!==o||0!==t.button||(t.preventDefault(),this.#u(l))},handleEnter:t=>{const e=t.target||{};if(h){if(e.preloadTimeout)return;e.preloadTimeout=setTimeout((()=>{e.preloadTimeout=null,this.preloadRoute(l).catch((t=>{console.warn(t),console.warn("Error preloading route! ☝️")}))}),d)}},handleLeave:t=>{const e=t.target||{};e.preloadTimeout&&(clearTimeout(e.preloadTimeout),e.preloadTimeout=null)},isActive:g&&w&&v,disabled:u}};dehydrate=()=>({state:{...u(this.state,["latestLocation","currentLocation","status","lastUpdated"]),currentMatches:this.state.currentMatches.map((t=>({id:t.id,state:{status:t.state.status}})))}});hydrate=t=>{this.store.setState((s=>{const a=this.matchRoutes(t.state.latestLocation.pathname,{strictParseParams:!0});return a.forEach(((s,a)=>{const r=t.state.currentMatches[a];e(r&&r.id===s.id),s.store.setState((t=>({...t,...r.state})))})),{...s,...t.state,currentMatches:a}}))};#h=t=>{const e=t=>{t.forEach(((t,s)=>{t.init({originalIndex:s,router:this});if(this.routesById[t.id])throw new Error;this.routesById[t.id]=t;const a=t.children;a?.length&&e(a)}))};return e([t]),t};#i=t=>{let{pathname:e,search:s,hash:a,state:r}=this.history.location;const o=this.options.parseSearch(s);return{pathname:e,searchStr:s,search:l(t?.search,o),hash:a.split("#").reverse()[0]??"",href:`${e}${s}${a}`,state:r,key:r?.key||"__init__"}};#n=()=>{this.load()};#c=(t={})=>{t.fromCurrent=t.fromCurrent??""===t.to;const e=t.fromCurrent?this.state.latestLocation.pathname:t.from??this.state.latestLocation.pathname;let s=S(this.basepath??"/",e,`${t.to??""}`);const a=this.matchRoutes(this.state.latestLocation.pathname,{strictParseParams:!0}),r=this.matchRoutes(s),o={...h(a)?.params};let n=!0===(t.params??!0)?o:c(t.params,o);n&&r.map((t=>t.route.options.stringifyParams)).filter(Boolean).forEach((t=>{Object.assign({},n,t(n))})),s=L(s,n??{});const i=t.__preSearchFilters?.length?t.__preSearchFilters?.reduce(((t,e)=>e(t)),this.state.latestLocation.search):this.state.latestLocation.search,u=!0===t.search?i:t.search?c(t.search,i)??{}:t.__preSearchFilters?.length?i:{},p=t.__postSearchFilters?.length?t.__postSearchFilters.reduce(((t,e)=>e(t)),u):u,d=l(this.state.latestLocation.search,p),f=this.options.stringifySearch(d);let m=!0===t.hash?this.state.latestLocation.hash:c(t.hash,this.state.latestLocation.hash);return m=m?`#${m}`:"",{pathname:s,search:d,searchStr:f,state:this.state.latestLocation.state,hash:m,href:`${s}${f}${m}`,key:t.key}};#u=t=>{const e=this.buildNext(t),s=""+Date.now()+Math.random();this.navigateTimeout&&clearTimeout(this.navigateTimeout);let a="replace";t.replace||(a="push");this.state.latestLocation.href===e.href&&!e.key&&(a="replace");const r=`${e.pathname}${e.searchStr}${e.hash?`#${e.hash}`:""}`;return this.history["push"===a?"push":"replace"](r,{id:s,...e.state}),this.navigationPromise=new Promise((t=>{const e=this.resolveNavigation;this.resolveNavigation=()=>{e(),t()}}))}},t.cleanPath=y,t.createBrowserHistory=r,t.createHashHistory=function(){return r({getHref:()=>window.location.hash.substring(1),createHref:t=>`#${t}`})},t.createMemoryHistory=o,t.decode=R,t.defaultFetchServerDataFn=O,t.defaultParseSearch=F,t.defaultStringifySearch=T,t.encode=x,t.functionalUpdate=c,t.interpolatePath=L,t.invariant=e,t.isPlainObject=p,t.joinPaths=m,t.last=h,t.matchByPath=_,t.matchPathname=P,t.parsePathname=b,t.parseSearchWith=j,t.partialDeepEqual=f,t.pick=u,t.replaceEqualDeep=l,t.resolvePath=S,t.rootRouteId=M,t.stringifySearchWith=D,t.trimPath=v,t.trimPathLeft=g,t.trimPathRight=w,t.warning=function(t,e){if(t){"undefined"!=typeof console&&console.warn(e);try{throw new Error(e)}catch{}}return!0},Object.defineProperty(t,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=index.production.js.map |
{ | ||
"name": "@tanstack/router", | ||
"author": "Tanner Linsley", | ||
"version": "0.0.1-beta.63", | ||
"version": "0.0.1-beta.64", | ||
"license": "MIT", | ||
@@ -6,0 +6,0 @@ "repository": "tanstack/router", |
@@ -255,6 +255,2 @@ import { AnyRoutesInfo, DefaultRoutesInfo, RouteByPath } from './routeInfo' | ||
preload?: false | 'intent' | ||
// When preloaded, the preloaded result will be considered "fresh" for this duration in milliseconds | ||
preloadMaxAge?: number | ||
// When preloaded and subsequently inactive, the preloaded result will remain in memory for this duration in milliseconds | ||
preloadGcMaxAge?: number | ||
// Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled. | ||
@@ -261,0 +257,0 @@ preloadDelay?: number |
@@ -83,3 +83,9 @@ import { GetFrameworkGeneric } from './frameworks' | ||
// An asynchronous function responsible for preparing or fetching data for the route before it is rendered | ||
onLoad?: OnLoadFn<TFullSearchSchema, TAllParams, TRouteContext, TContext> | ||
onLoad?: OnLoadFn< | ||
TSearchSchema, | ||
TFullSearchSchema, | ||
TAllParams, | ||
TRouteContext, | ||
TContext | ||
> | ||
@@ -168,2 +174,3 @@ // This function will be called if the route's loader throws an error **during an attempted navigation**. | ||
export type OnLoadFn< | ||
TSearchSchema extends AnySearchSchema = {}, | ||
TFullSearchSchema extends AnySearchSchema = {}, | ||
@@ -175,2 +182,3 @@ TAllParams extends AnyPathParams = {}, | ||
loaderContext: LoaderContext< | ||
TSearchSchema, | ||
TFullSearchSchema, | ||
@@ -184,2 +192,3 @@ TAllParams, | ||
export interface LoaderContext< | ||
TSearchSchema extends AnySearchSchema = {}, | ||
TFullSearchSchema extends AnySearchSchema = {}, | ||
@@ -191,2 +200,3 @@ TAllParams extends AnyPathParams = {}, | ||
params: TAllParams | ||
routeSearch: TSearchSchema | ||
search: TFullSearchSchema | ||
@@ -193,0 +203,0 @@ signal?: AbortSignal |
import { Store } from '@tanstack/store' | ||
// | ||
import { GetFrameworkGeneric } from './frameworks' | ||
import { AnyRoute, Route } from './route' | ||
import { AnyRoute, AnySearchSchema, Route } from './route' | ||
import { AnyRoutesInfo, DefaultRoutesInfo } from './routeInfo' | ||
import { AnyRouter, Router } from './router' | ||
import { Expand, pick } from './utils' | ||
import { AnyRouter, ParsedLocation, Router } from './router' | ||
import { Expand, pick, replaceEqualDeep } from './utils' | ||
@@ -27,2 +27,8 @@ export interface RouteMatchStore< | ||
export interface PendingRouteMatchInfo { | ||
state: RouteMatchStore<any, any> | ||
routeContext: {} | ||
context: {} | ||
} | ||
export interface AnyRouteMatch extends RouteMatch<any, any> {} | ||
@@ -50,2 +56,3 @@ | ||
parentMatch?: RouteMatch | ||
pendingInfo?: PendingRouteMatchInfo | ||
@@ -107,9 +114,27 @@ __loadPromise?: Promise<void> | ||
__init = (opts: { parentMatch?: RouteMatch }) => { | ||
__commit = () => { | ||
const { routeSearch, search, context, routeContext } = this.#resolveInfo({ | ||
location: this.router.state.currentLocation, | ||
}) | ||
this.context = context | ||
this.routeContext = routeContext | ||
this.store.setState((s) => ({ | ||
...s, | ||
routeSearch: replaceEqualDeep(s.routeSearch, routeSearch), | ||
search: replaceEqualDeep(s.search, search), | ||
})) | ||
} | ||
cancel = () => { | ||
this.abortController?.abort() | ||
} | ||
#resolveSearchInfo = (opts: { | ||
location: ParsedLocation | ||
}): { routeSearch: {}; search: {} } => { | ||
// Validate the search params and stabilize them | ||
this.parentMatch = opts.parentMatch | ||
const parentSearchInfo = this.parentMatch | ||
? this.parentMatch.#resolveSearchInfo(opts) | ||
: { search: opts.location.search, routeSearch: opts.location.search } | ||
const parentSearch = | ||
this.parentMatch?.state.search ?? this.router.state.latestLocation.search | ||
try { | ||
@@ -121,36 +146,13 @@ const validator = | ||
let nextSearch = validator?.(parentSearch) ?? {} | ||
const routeSearch = validator?.(parentSearchInfo.search) ?? {} | ||
this.store.setState((s) => ({ | ||
...s, | ||
routeSearch: nextSearch, | ||
search: { | ||
...parentSearch, | ||
...nextSearch, | ||
} as any, | ||
})) | ||
const search = { | ||
...parentSearchInfo.search, | ||
...routeSearch, | ||
} | ||
componentTypes.map(async (type) => { | ||
const component = this.route.options[type] | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component | ||
} | ||
}) | ||
const parent = this.parentMatch | ||
this.routeContext = | ||
this.route.options.getContext?.({ | ||
parentContext: parent?.routeContext, | ||
context: parent?.context, | ||
params: this.params, | ||
search: this.state.search, | ||
}) || ({} as any) | ||
this.context = ( | ||
parent | ||
? { ...parent.context, ...this.routeContext } | ||
: { ...this.router?.options.context, ...this.routeContext } | ||
) as any | ||
return { | ||
routeSearch, | ||
search, | ||
} | ||
} catch (err: any) { | ||
@@ -163,6 +165,47 @@ console.error(err) | ||
throw error | ||
} | ||
} | ||
#resolveInfo = (opts: { location: ParsedLocation }) => { | ||
const { search, routeSearch } = this.#resolveSearchInfo(opts) | ||
const routeContext = | ||
this.route.options.getContext?.({ | ||
parentContext: this.parentMatch?.routeContext ?? {}, | ||
context: | ||
this.parentMatch?.context ?? this.router?.options.context ?? {}, | ||
params: this.params, | ||
search, | ||
}) || ({} as any) | ||
const context = { | ||
...(this.parentMatch?.context ?? this.router?.options.context), | ||
...routeContext, | ||
} as any | ||
return { | ||
routeSearch, | ||
search, | ||
context, | ||
routeContext, | ||
} | ||
} | ||
__load = async (opts: { | ||
parentMatch: RouteMatch | undefined | ||
preload?: boolean | ||
location: ParsedLocation | ||
}): Promise<void> => { | ||
this.parentMatch = opts.parentMatch | ||
let info | ||
try { | ||
info = this.#resolveInfo(opts) | ||
} catch (err) { | ||
this.store.setState((s) => ({ | ||
...s, | ||
status: 'error', | ||
error: error, | ||
error: err, | ||
})) | ||
@@ -173,18 +216,19 @@ | ||
} | ||
} | ||
cancel = () => { | ||
this.abortController?.abort() | ||
} | ||
const { routeSearch, search, context, routeContext } = info | ||
load = async (opts?: { preload?: boolean }): Promise<void> => { | ||
componentTypes.map(async (type) => { | ||
const component = this.route.options[type] | ||
if (typeof this[type] !== 'function') { | ||
this[type] = component | ||
} | ||
}) | ||
// If the match is invalid, errored or idle, trigger it to load | ||
if (this.state.status !== 'pending') { | ||
await this.fetch(opts) | ||
if (this.state.status === 'pending') { | ||
return | ||
} | ||
} | ||
#latestId = '' | ||
fetch = async (opts?: { preload?: boolean }): Promise<void> => { | ||
// TODO: Should load promises be tracked based on location? | ||
this.__loadPromise = Promise.resolve().then(async () => { | ||
@@ -200,13 +244,11 @@ const loadId = '' + Date.now() + Math.random() | ||
this.store.batch(() => { | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState((s) => ({ | ||
...s, | ||
status: 'pending', | ||
})) | ||
} | ||
}) | ||
// If the match was in an error state, set it | ||
// to a loading state again. Otherwise, keep it | ||
// as loading or resolved | ||
if (this.state.status === 'idle') { | ||
this.store.setState((s) => ({ | ||
...s, | ||
status: 'pending', | ||
})) | ||
} | ||
@@ -232,7 +274,8 @@ const componentsPromise = (async () => { | ||
params: this.params, | ||
search: this.state.search, | ||
routeSearch, | ||
search, | ||
signal: this.abortController.signal, | ||
preload: !!opts?.preload, | ||
routeContext: this.routeContext, | ||
context: this.context, | ||
routeContext: routeContext, | ||
context: context, | ||
}) | ||
@@ -267,2 +310,4 @@ } | ||
} | ||
#latestId = '' | ||
} |
@@ -450,2 +450,3 @@ import { Store } from '@tanstack/store' | ||
matches, | ||
this.state.pendingLocation!, | ||
// opts | ||
@@ -515,2 +516,4 @@ ) | ||
const prevLocation = this.state.currentLocation | ||
this.store.setState((s) => ({ | ||
@@ -525,4 +528,10 @@ ...s, | ||
this.options.onRouteChange?.() | ||
matches.forEach((match) => { | ||
match.__commit() | ||
}) | ||
if (prevLocation!.href !== this.state.currentLocation.href) { | ||
this.options.onRouteChange?.() | ||
} | ||
this.resolveNavigation() | ||
@@ -548,3 +557,3 @@ } | ||
}) | ||
await this.loadMatches(matches) | ||
await this.loadMatches(matches, next) | ||
return matches | ||
@@ -561,3 +570,3 @@ } | ||
await this.loadMatches(matches, { | ||
await this.loadMatches(matches, next, { | ||
preload: true, | ||
@@ -674,2 +683,3 @@ }) | ||
resolvedMatches: RouteMatch[], | ||
location: ParsedLocation, | ||
opts?: { | ||
@@ -680,4 +690,2 @@ preload?: boolean | ||
) => { | ||
initMatches(resolvedMatches) | ||
// Check each match middleware to see if the route can be accessed | ||
@@ -702,19 +710,11 @@ await Promise.all( | ||
const matchPromises = resolvedMatches.map(async (match, index) => { | ||
const prevMatch = resolvedMatches[(index = 1)] | ||
const search = match.state.search as { __data?: any } | ||
const parentMatch = resolvedMatches[index - 1] | ||
// if (opts?.filter && !opts.filter(match)) { | ||
// return | ||
// } | ||
match.__load({ preload: opts?.preload, location, parentMatch }) | ||
match.load({ preload: opts?.preload }) | ||
await match.__loadPromise | ||
if (match.state.status !== 'success' && match.__loadPromise) { | ||
// Wait for the first sign of activity from the match | ||
await match.__loadPromise | ||
if (parentMatch) { | ||
await parentMatch.__loadPromise | ||
} | ||
if (prevMatch) { | ||
await prevMatch.__loadPromise | ||
} | ||
}) | ||
@@ -811,7 +811,2 @@ | ||
if (opts?.includeSearch ?? true) { | ||
console.log( | ||
baseLocation.search, | ||
next.search, | ||
partialDeepEqual(baseLocation.search, next.search), | ||
) | ||
return partialDeepEqual(baseLocation.search, next.search) ? match : false | ||
@@ -836,4 +831,2 @@ } | ||
preload, | ||
preloadMaxAge: userPreloadMaxAge, | ||
preloadGcMaxAge: userPreloadGcMaxAge, | ||
preloadDelay: userPreloadDelay, | ||
@@ -998,4 +991,2 @@ disabled, | ||
initMatches(currentMatches) | ||
return { | ||
@@ -1199,8 +1190,1 @@ ...s, | ||
} | ||
function initMatches(matches: RouteMatch<any, any>[]) { | ||
matches.forEach((match, index) => { | ||
const parentMatch = matches[index - 1] | ||
match.__init({ parentMatch }) | ||
}) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
952102
8714