@tanstack/react-router 0.0.1-beta.226 → 0.0.1-beta.227
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/Matches.js +8 -6
- package/build/cjs/Matches.js.map +1 -1
- package/build/cjs/RouterProvider.js +0 -25
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/fileRoute.js.map +1 -1
- package/build/cjs/route.js.map +1 -1
- package/build/cjs/router.js +45 -50
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +52 -81
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +293 -287
- package/build/types/Matches.d.ts +0 -1
- package/build/types/fileRoute.d.ts +2 -2
- package/build/types/route.d.ts +6 -2
- package/build/umd/index.development.js +52 -82
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.tsx +21 -23
- package/src/RouterProvider.tsx +4 -71
- package/src/fileRoute.ts +7 -6
- package/src/route.ts +3 -2
- package/src/router.ts +75 -75
package/build/types/Matches.d.ts
CHANGED
|
@@ -20,7 +20,6 @@ export interface RouteMatch<TRouteTree extends AnyRoute = AnyRoute, TRouteId ext
|
|
|
20
20
|
loaderData?: RouteById<TRouteTree, TRouteId>['types']['loaderData'];
|
|
21
21
|
__resolveLoadPromise?: () => void;
|
|
22
22
|
context: RouteById<TRouteTree, TRouteId>['types']['allContext'];
|
|
23
|
-
routeSearch: RouteById<TRouteTree, TRouteId>['types']['searchSchema'];
|
|
24
23
|
search: FullSearchSchema<TRouteTree> & RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema'];
|
|
25
24
|
fetchedAt: number;
|
|
26
25
|
shouldReloadDeps: any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ParsePathParams } from './link';
|
|
2
|
-
import { AnyRoute, ResolveFullPath, ResolveFullSearchSchema, MergeFromFromParent, RouteContext, AnyContext, RouteOptions, UpdatableRouteOptions, Route,
|
|
2
|
+
import { AnyRoute, ResolveFullPath, ResolveFullSearchSchema, MergeFromFromParent, RouteContext, AnyContext, RouteOptions, UpdatableRouteOptions, Route, RootRouteId, TrimPathLeft, RouteConstraints } from './route';
|
|
3
3
|
import { Assign, Expand, IsAny } from './utils';
|
|
4
4
|
export interface FileRoutesByPath {
|
|
5
5
|
}
|
|
@@ -13,7 +13,7 @@ export type FileRoutePath<TParentRoute extends AnyRoute, TFilePath extends strin
|
|
|
13
13
|
export declare class FileRoute<TFilePath extends keyof FileRoutesByPath, TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'], TId extends RouteConstraints['TId'] = TFilePath, TPath extends RouteConstraints['TPath'] = FileRoutePath<TParentRoute, TFilePath>, TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<TParentRoute, RemoveUnderScores<TPath>>> {
|
|
14
14
|
path: TFilePath;
|
|
15
15
|
constructor(path: TFilePath);
|
|
16
|
-
createRoute: <TSearchSchema extends import("./route").AnySearchSchema = {}, TFullSearchSchema extends import("./route").AnySearchSchema = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends Record<string, any> =
|
|
16
|
+
createRoute: <TSearchSchema extends import("./route").AnySearchSchema = {}, TFullSearchSchema extends import("./route").AnySearchSchema = ResolveFullSearchSchema<TParentRoute, TSearchSchema>, TParams extends Record<string, any> = Expand<Record<ParsePathParams<TPath>, string>>, TAllParams extends Record<string, any> = MergeFromFromParent<TParentRoute["types"]["allParams"], TParams>, TRouteContext extends RouteContext = RouteContext, TContext extends Expand<Assign<IsAny<TParentRoute["types"]["allContext"], {}>, TRouteContext>> = Expand<Assign<IsAny<TParentRoute["types"]["allContext"], {}>, TRouteContext>>, TRouterContext extends AnyContext = AnyContext, TLoaderData extends unknown = unknown, TChildren extends unknown = unknown, TRouteTree extends AnyRoute = AnyRoute>(options?: (Omit<RouteOptions<TParentRoute, string, TPath, TSearchSchema, TFullSearchSchema, TParams, TAllParams, TRouteContext, TContext, TLoaderData>, "path" | "id" | "getParentRoute"> & {
|
|
17
17
|
meta?: import("./route").RouteMeta | undefined;
|
|
18
18
|
} & {
|
|
19
19
|
caseSensitive?: boolean | undefined;
|
package/build/types/route.d.ts
CHANGED
|
@@ -40,7 +40,11 @@ export type BaseRouteOptions<TParentRoute extends AnyRoute = AnyRoute, TCustomId
|
|
|
40
40
|
} : {
|
|
41
41
|
beforeLoad: BeforeLoadFn<TFullSearchSchema, TParentRoute, TAllParams, TRouteContext>;
|
|
42
42
|
}) & {
|
|
43
|
-
|
|
43
|
+
key?: (opts: {
|
|
44
|
+
search: TFullSearchSchema;
|
|
45
|
+
location: ParsedLocation;
|
|
46
|
+
}) => any;
|
|
47
|
+
loader?: RouteLoaderFn<TAllParams, TFullSearchSchema, NoInfer<TAllContext>, NoInfer<TRouteContext>, TLoaderData>;
|
|
44
48
|
} & ({
|
|
45
49
|
parseParams?: (rawParams: IsAny<TPath, any, Record<ParsePathParams<TPath>, string>>) => TParams extends Record<ParsePathParams<TPath>, any> ? TParams : 'parseParams must return an object';
|
|
46
50
|
stringifyParams?: (params: NoInfer<ParamsFallback<TPath, TParams>>) => Record<ParsePathParams<TPath>, string>;
|
|
@@ -87,7 +91,7 @@ export type DefinedPathParamWarning = 'Path params cannot be redefined by child
|
|
|
87
91
|
export type ParentParams<TParentParams> = AnyPathParams extends TParentParams ? {} : {
|
|
88
92
|
[Key in keyof TParentParams]?: DefinedPathParamWarning;
|
|
89
93
|
};
|
|
90
|
-
export type
|
|
94
|
+
export type RouteLoaderFn<TAllParams = {}, TFullSearchSchema extends Record<string, any> = {}, TAllContext extends Record<string, any> = AnyContext, TRouteContext extends Record<string, any> = AnyContext, TLoaderData extends any = unknown> = (match: LoaderFnContext<TAllParams, TFullSearchSchema, TAllContext, TRouteContext>) => Promise<TLoaderData> | TLoaderData;
|
|
91
95
|
export interface LoaderFnContext<TAllParams = {}, TFullSearchSchema extends Record<string, any> = {}, TAllContext extends Record<string, any> = AnyContext, TRouteContext extends Record<string, any> = AnyContext> {
|
|
92
96
|
abortController: AbortController;
|
|
93
97
|
preload: boolean;
|
|
@@ -169,7 +169,6 @@
|
|
|
169
169
|
* @returns A history instance
|
|
170
170
|
*/
|
|
171
171
|
function createBrowserHistory(opts) {
|
|
172
|
-
console.log('hello');
|
|
173
172
|
const getHref = opts?.getHref ?? (() => `${window.location.pathname}${window.location.search}${window.location.hash}`);
|
|
174
173
|
const createHref = opts?.createHref ?? (path => path);
|
|
175
174
|
let currentLocation = parseLocation(getHref(), window.history.state);
|
|
@@ -964,7 +963,6 @@
|
|
|
964
963
|
matches: matches
|
|
965
964
|
}) : null));
|
|
966
965
|
}
|
|
967
|
-
const defaultPending = () => null;
|
|
968
966
|
function SafeFragment(props) {
|
|
969
967
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.children);
|
|
970
968
|
}
|
|
@@ -979,9 +977,9 @@
|
|
|
979
977
|
const routeId = match?.routeId;
|
|
980
978
|
const route = routesById[routeId];
|
|
981
979
|
const locationKey = useRouterState().location.state?.key;
|
|
982
|
-
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent
|
|
980
|
+
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent;
|
|
983
981
|
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
984
|
-
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ? React__namespace.Suspense : SafeFragment;
|
|
982
|
+
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? PendingComponent ? React__namespace.Suspense : SafeFragment;
|
|
985
983
|
const errorComponent = routeErrorComponent ? React__namespace.useCallback(props => {
|
|
986
984
|
return /*#__PURE__*/React__namespace.createElement(routeErrorComponent, {
|
|
987
985
|
...props,
|
|
@@ -991,6 +989,7 @@
|
|
|
991
989
|
useParams: route.useParams
|
|
992
990
|
});
|
|
993
991
|
}, [route]) : undefined;
|
|
992
|
+
const ResolvedCatchBoundary = errorComponent ? CatchBoundary : SafeFragment;
|
|
994
993
|
return /*#__PURE__*/React__namespace.createElement(matchesContext.Provider, {
|
|
995
994
|
value: matches
|
|
996
995
|
}, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
|
|
@@ -1000,7 +999,7 @@
|
|
|
1000
999
|
useSearch: route.useSearch,
|
|
1001
1000
|
useParams: route.useParams
|
|
1002
1001
|
})
|
|
1003
|
-
},
|
|
1002
|
+
}, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
|
|
1004
1003
|
resetKey: locationKey,
|
|
1005
1004
|
errorComponent: errorComponent,
|
|
1006
1005
|
onCatch: () => {
|
|
@@ -1008,8 +1007,6 @@
|
|
|
1008
1007
|
}
|
|
1009
1008
|
}, /*#__PURE__*/React__namespace.createElement(MatchInner, {
|
|
1010
1009
|
match: match
|
|
1011
|
-
})) : /*#__PURE__*/React__namespace.createElement(SafeFragment, null, /*#__PURE__*/React__namespace.createElement(MatchInner, {
|
|
1012
|
-
match: match
|
|
1013
1010
|
}))));
|
|
1014
1011
|
}
|
|
1015
1012
|
function MatchInner({
|
|
@@ -1020,6 +1017,9 @@
|
|
|
1020
1017
|
routesById
|
|
1021
1018
|
} = useRouter();
|
|
1022
1019
|
const route = routesById[match.routeId];
|
|
1020
|
+
if (match.id.split('/').length === 4) {
|
|
1021
|
+
console.log(match.id, pick(match, ['status', 'cause', 'isFetching']));
|
|
1022
|
+
}
|
|
1023
1023
|
if (match.status === 'error') {
|
|
1024
1024
|
throw match.error;
|
|
1025
1025
|
}
|
|
@@ -1113,31 +1113,6 @@
|
|
|
1113
1113
|
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
1114
1114
|
}
|
|
1115
1115
|
|
|
1116
|
-
// export type RouterContext<
|
|
1117
|
-
// TRouteTree extends AnyRoute,
|
|
1118
|
-
// // TDehydrated extends Record<string, any>,
|
|
1119
|
-
// > = {
|
|
1120
|
-
// buildLink: BuildLinkFn<TRouteTree>
|
|
1121
|
-
// state: RouterState<TRouteTree>
|
|
1122
|
-
// navigate: NavigateFn<TRouteTree>
|
|
1123
|
-
// matchRoute: MatchRouteFn<TRouteTree>
|
|
1124
|
-
// routeTree: TRouteTree
|
|
1125
|
-
// routesById: RoutesById<TRouteTree>
|
|
1126
|
-
// options: RouterOptions<TRouteTree>
|
|
1127
|
-
// history: RouterHistory
|
|
1128
|
-
// load: LoadFn
|
|
1129
|
-
// buildLocation: BuildLocationFn<TRouteTree>
|
|
1130
|
-
// subscribe: Router<TRouteTree>['subscribe']
|
|
1131
|
-
// resetNextScrollRef: React.MutableRefObject<boolean>
|
|
1132
|
-
// injectedHtmlRef: React.MutableRefObject<InjectedHtmlEntry[]>
|
|
1133
|
-
// injectHtml: (entry: InjectedHtmlEntry) => void
|
|
1134
|
-
// dehydrateData: <T>(
|
|
1135
|
-
// key: any,
|
|
1136
|
-
// getData: T | (() => Promise<T> | T),
|
|
1137
|
-
// ) => () => void
|
|
1138
|
-
// hydrateData: <T>(key: any) => T | undefined
|
|
1139
|
-
// }
|
|
1140
|
-
|
|
1141
1116
|
const routerContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
1142
1117
|
if (typeof document !== 'undefined') {
|
|
1143
1118
|
window.__TSR_ROUTER_CONTEXT__ = routerContext;
|
|
@@ -1811,38 +1786,66 @@
|
|
|
1811
1786
|
}
|
|
1812
1787
|
return;
|
|
1813
1788
|
});
|
|
1814
|
-
const matches =
|
|
1789
|
+
const matches = [];
|
|
1790
|
+
matchedRoutes.forEach((route, index) => {
|
|
1791
|
+
// Take each matched route and resolve + validate its search params
|
|
1792
|
+
// This has to happen serially because each route's search params
|
|
1793
|
+
// can depend on the parent route's search params
|
|
1794
|
+
// It must also happen before we create the match so that we can
|
|
1795
|
+
// pass the search params to the route's potential key function
|
|
1796
|
+
// which is used to uniquely identify the route match in state
|
|
1797
|
+
|
|
1798
|
+
const parentMatch = matches[index - 1];
|
|
1799
|
+
const [preMatchSearch, searchError] = (() => {
|
|
1800
|
+
// Validate the search params and stabilize them
|
|
1801
|
+
const parentSearch = parentMatch?.search ?? locationSearch;
|
|
1802
|
+
try {
|
|
1803
|
+
const validator = typeof route.options.validateSearch === 'object' ? route.options.validateSearch.parse : route.options.validateSearch;
|
|
1804
|
+
let search = validator?.(parentSearch) ?? {};
|
|
1805
|
+
return [{
|
|
1806
|
+
...parentSearch,
|
|
1807
|
+
...search
|
|
1808
|
+
}, undefined];
|
|
1809
|
+
} catch (err) {
|
|
1810
|
+
const searchError = new SearchParamError(err.message, {
|
|
1811
|
+
cause: err
|
|
1812
|
+
});
|
|
1813
|
+
if (opts?.throwOnError) {
|
|
1814
|
+
throw searchError;
|
|
1815
|
+
}
|
|
1816
|
+
return [parentSearch, searchError];
|
|
1817
|
+
}
|
|
1818
|
+
})();
|
|
1815
1819
|
const interpolatedPath = interpolatePath(route.path, routeParams);
|
|
1816
|
-
const matchId = interpolatePath(route.id, routeParams, true)
|
|
1820
|
+
const matchId = interpolatePath(route.id, routeParams, true) + (route.options.key?.({
|
|
1821
|
+
search: preMatchSearch,
|
|
1822
|
+
location: this.state.location
|
|
1823
|
+
}) ?? '');
|
|
1817
1824
|
|
|
1818
1825
|
// Waste not, want not. If we already have a match for this route,
|
|
1819
1826
|
// reuse it. This is important for layout routes, which might stick
|
|
1820
1827
|
// around between navigation actions that only change leaf routes.
|
|
1821
1828
|
const existingMatch = getRouteMatch(this.state, matchId);
|
|
1822
1829
|
const cause = this.state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
|
|
1823
|
-
if (existingMatch) {
|
|
1824
|
-
return {
|
|
1825
|
-
...existingMatch,
|
|
1826
|
-
cause
|
|
1827
|
-
};
|
|
1828
|
-
}
|
|
1829
1830
|
|
|
1830
1831
|
// Create a fresh route match
|
|
1831
1832
|
const hasLoaders = !!(route.options.loader || componentTypes.some(d => route.options[d]?.preload));
|
|
1832
|
-
const
|
|
1833
|
+
const match = existingMatch ? {
|
|
1834
|
+
...existingMatch,
|
|
1835
|
+
cause
|
|
1836
|
+
} : {
|
|
1833
1837
|
id: matchId,
|
|
1834
1838
|
routeId: route.id,
|
|
1835
1839
|
params: routeParams,
|
|
1836
1840
|
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1837
1841
|
updatedAt: Date.now(),
|
|
1838
|
-
routeSearch: {},
|
|
1839
1842
|
search: {},
|
|
1843
|
+
searchError: undefined,
|
|
1840
1844
|
status: hasLoaders ? 'pending' : 'success',
|
|
1841
1845
|
isFetching: false,
|
|
1842
1846
|
invalid: false,
|
|
1843
1847
|
error: undefined,
|
|
1844
1848
|
paramsError: parseErrors[index],
|
|
1845
|
-
searchError: undefined,
|
|
1846
1849
|
loadPromise: Promise.resolve(),
|
|
1847
1850
|
context: undefined,
|
|
1848
1851
|
abortController: new AbortController(),
|
|
@@ -1850,46 +1853,13 @@
|
|
|
1850
1853
|
fetchedAt: 0,
|
|
1851
1854
|
cause
|
|
1852
1855
|
};
|
|
1853
|
-
return routeMatch;
|
|
1854
|
-
});
|
|
1855
1856
|
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
const searchInfo = (() => {
|
|
1863
|
-
// Validate the search params and stabilize them
|
|
1864
|
-
const parentSearchInfo = {
|
|
1865
|
-
search: parentMatch?.search ?? locationSearch,
|
|
1866
|
-
routeSearch: parentMatch?.routeSearch ?? locationSearch
|
|
1867
|
-
};
|
|
1868
|
-
try {
|
|
1869
|
-
const validator = typeof route.options.validateSearch === 'object' ? route.options.validateSearch.parse : route.options.validateSearch;
|
|
1870
|
-
let routeSearch = validator?.(parentSearchInfo.search) ?? {};
|
|
1871
|
-
let search = {
|
|
1872
|
-
...parentSearchInfo.search,
|
|
1873
|
-
...routeSearch
|
|
1874
|
-
};
|
|
1875
|
-
routeSearch = replaceEqualDeep(match.routeSearch, routeSearch);
|
|
1876
|
-
search = replaceEqualDeep(match.search, search);
|
|
1877
|
-
return {
|
|
1878
|
-
routeSearch,
|
|
1879
|
-
search,
|
|
1880
|
-
searchDidChange: match.routeSearch !== routeSearch
|
|
1881
|
-
};
|
|
1882
|
-
} catch (err) {
|
|
1883
|
-
match.searchError = new SearchParamError(err.message, {
|
|
1884
|
-
cause: err
|
|
1885
|
-
});
|
|
1886
|
-
if (opts?.throwOnError) {
|
|
1887
|
-
throw match.searchError;
|
|
1888
|
-
}
|
|
1889
|
-
return parentSearchInfo;
|
|
1890
|
-
}
|
|
1891
|
-
})();
|
|
1892
|
-
Object.assign(match, searchInfo);
|
|
1857
|
+
// Regardless of whether we're reusing an existing match or creating
|
|
1858
|
+
// a new one, we need to update the match's search params
|
|
1859
|
+
match.search = replaceEqualDeep(match.search, preMatchSearch);
|
|
1860
|
+
// And also update the searchError if there is one
|
|
1861
|
+
match.searchError = searchError;
|
|
1862
|
+
matches.push(match);
|
|
1893
1863
|
});
|
|
1894
1864
|
return matches;
|
|
1895
1865
|
};
|