@tanstack/react-router 0.0.1-beta.222 → 0.0.1-beta.224
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.map +1 -1
- package/build/cjs/RouterProvider.js +56 -955
- 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 +953 -39
- package/build/cjs/router.js.map +1 -1
- package/build/cjs/scroll-restoration.js +5 -9
- package/build/cjs/scroll-restoration.js.map +1 -1
- package/build/cjs/useSearch.js.map +1 -1
- package/build/cjs/utils.js.map +1 -1
- package/build/esm/index.js +895 -889
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +369 -363
- package/build/types/Matches.d.ts +25 -2
- package/build/types/RouterProvider.d.ts +4 -45
- package/build/types/fileRoute.d.ts +5 -5
- package/build/types/route.d.ts +3 -1
- package/build/types/router.d.ts +50 -5
- package/build/umd/index.development.js +895 -889
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +2 -2
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.tsx +38 -2
- package/src/RouterProvider.tsx +58 -1342
- package/src/fileRoute.ts +1 -1
- package/src/route.ts +24 -1
- package/src/router.ts +1320 -45
- package/src/scroll-restoration.tsx +5 -5
- package/src/useSearch.tsx +1 -1
- package/src/utils.ts +1 -1
package/build/esm/index.js
CHANGED
|
@@ -779,274 +779,34 @@ function useLoaderData(opts) {
|
|
|
779
779
|
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
780
780
|
}
|
|
781
781
|
|
|
782
|
-
//
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
//
|
|
793
|
-
|
|
794
|
-
//
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
807
|
-
}
|
|
808
|
-
} else {
|
|
809
|
-
str && (str += '&');
|
|
810
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
return (pfx || '') + str;
|
|
815
|
-
}
|
|
816
|
-
function toValue(mix) {
|
|
817
|
-
if (!mix) return '';
|
|
818
|
-
var str = decodeURIComponent(mix);
|
|
819
|
-
if (str === 'false') return false;
|
|
820
|
-
if (str === 'true') return true;
|
|
821
|
-
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
822
|
-
}
|
|
823
|
-
function decode(str) {
|
|
824
|
-
var tmp,
|
|
825
|
-
k,
|
|
826
|
-
out = {},
|
|
827
|
-
arr = str.split('&');
|
|
828
|
-
while (tmp = arr.shift()) {
|
|
829
|
-
tmp = tmp.split('=');
|
|
830
|
-
k = tmp.shift();
|
|
831
|
-
if (out[k] !== void 0) {
|
|
832
|
-
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
833
|
-
} else {
|
|
834
|
-
out[k] = toValue(tmp.shift());
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
return out;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
841
|
-
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
842
|
-
function parseSearchWith(parser) {
|
|
843
|
-
return searchStr => {
|
|
844
|
-
if (searchStr.substring(0, 1) === '?') {
|
|
845
|
-
searchStr = searchStr.substring(1);
|
|
846
|
-
}
|
|
847
|
-
let query = decode(searchStr);
|
|
848
|
-
|
|
849
|
-
// Try to parse any query params that might be json
|
|
850
|
-
for (let key in query) {
|
|
851
|
-
const value = query[key];
|
|
852
|
-
if (typeof value === 'string') {
|
|
853
|
-
try {
|
|
854
|
-
query[key] = parser(value);
|
|
855
|
-
} catch (err) {
|
|
856
|
-
//
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
return query;
|
|
861
|
-
};
|
|
862
|
-
}
|
|
863
|
-
function stringifySearchWith(stringify, parser) {
|
|
864
|
-
function stringifyValue(val) {
|
|
865
|
-
if (typeof val === 'object' && val !== null) {
|
|
866
|
-
try {
|
|
867
|
-
return stringify(val);
|
|
868
|
-
} catch (err) {
|
|
869
|
-
// silent
|
|
870
|
-
}
|
|
871
|
-
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
872
|
-
try {
|
|
873
|
-
// Check if it's a valid parseable string.
|
|
874
|
-
// If it is, then stringify it again.
|
|
875
|
-
parser(val);
|
|
876
|
-
return stringify(val);
|
|
877
|
-
} catch (err) {
|
|
878
|
-
// silent
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
return val;
|
|
882
|
-
}
|
|
883
|
-
return search => {
|
|
884
|
-
search = {
|
|
885
|
-
...search
|
|
886
|
-
};
|
|
887
|
-
if (search) {
|
|
888
|
-
Object.keys(search).forEach(key => {
|
|
889
|
-
const val = search[key];
|
|
890
|
-
if (typeof val === 'undefined' || val === undefined) {
|
|
891
|
-
delete search[key];
|
|
892
|
-
} else {
|
|
893
|
-
search[key] = stringifyValue(val);
|
|
894
|
-
}
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
const searchStr = encode(search).toString();
|
|
898
|
-
return searchStr ? `?${searchStr}` : '';
|
|
899
|
-
};
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
//
|
|
903
|
-
|
|
904
|
-
//
|
|
905
|
-
|
|
906
|
-
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
907
|
-
class Router {
|
|
908
|
-
// dehydratedData?: TDehydrated
|
|
909
|
-
// resetNextScroll = false
|
|
910
|
-
// tempLocationKey = `${Math.round(Math.random() * 10000000)}`
|
|
911
|
-
constructor(options) {
|
|
912
|
-
this.options = {
|
|
913
|
-
defaultPreloadDelay: 50,
|
|
914
|
-
context: undefined,
|
|
915
|
-
...options,
|
|
916
|
-
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
917
|
-
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
918
|
-
};
|
|
919
|
-
this.routeTree = this.options.routeTree;
|
|
920
|
-
}
|
|
921
|
-
subscribers = new Set();
|
|
922
|
-
subscribe = (eventType, fn) => {
|
|
923
|
-
const listener = {
|
|
924
|
-
eventType,
|
|
925
|
-
fn
|
|
926
|
-
};
|
|
927
|
-
this.subscribers.add(listener);
|
|
928
|
-
return () => {
|
|
929
|
-
this.subscribers.delete(listener);
|
|
930
|
-
};
|
|
931
|
-
};
|
|
932
|
-
emit = routerEvent => {
|
|
933
|
-
this.subscribers.forEach(listener => {
|
|
934
|
-
if (listener.eventType === routerEvent.type) {
|
|
935
|
-
listener.fn(routerEvent);
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
};
|
|
939
|
-
|
|
940
|
-
// dehydrate = (): DehydratedRouter => {
|
|
941
|
-
// return {
|
|
942
|
-
// state: {
|
|
943
|
-
// dehydratedMatches: state.matches.map((d) =>
|
|
944
|
-
// pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
|
|
945
|
-
// ),
|
|
946
|
-
// },
|
|
947
|
-
// }
|
|
948
|
-
// }
|
|
949
|
-
|
|
950
|
-
// hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
|
|
951
|
-
// let _ctx = __do_not_use_server_ctx
|
|
952
|
-
// // Client hydrates from window
|
|
953
|
-
// if (typeof document !== 'undefined') {
|
|
954
|
-
// _ctx = window.__TSR_DEHYDRATED__
|
|
955
|
-
// }
|
|
956
|
-
|
|
957
|
-
// invariant(
|
|
958
|
-
// _ctx,
|
|
959
|
-
// 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
|
|
960
|
-
// )
|
|
961
|
-
|
|
962
|
-
// const ctx = _ctx
|
|
963
|
-
// this.dehydratedData = ctx.payload as any
|
|
964
|
-
// this.options.hydrate?.(ctx.payload as any)
|
|
965
|
-
// const dehydratedState = ctx.router.state
|
|
966
|
-
|
|
967
|
-
// let matches = this.matchRoutes(
|
|
968
|
-
// state.location.pathname,
|
|
969
|
-
// state.location.search,
|
|
970
|
-
// ).map((match) => {
|
|
971
|
-
// const dehydratedMatch = dehydratedState.dehydratedMatches.find(
|
|
972
|
-
// (d) => d.id === match.id,
|
|
973
|
-
// )
|
|
974
|
-
|
|
975
|
-
// invariant(
|
|
976
|
-
// dehydratedMatch,
|
|
977
|
-
// `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
978
|
-
// )
|
|
979
|
-
|
|
980
|
-
// if (dehydratedMatch) {
|
|
981
|
-
// return {
|
|
982
|
-
// ...match,
|
|
983
|
-
// ...dehydratedMatch,
|
|
984
|
-
// }
|
|
985
|
-
// }
|
|
986
|
-
// return match
|
|
987
|
-
// })
|
|
988
|
-
|
|
989
|
-
// this.setState((s) => {
|
|
990
|
-
// return {
|
|
991
|
-
// ...s,
|
|
992
|
-
// matches: dehydratedState.dehydratedMatches as any,
|
|
993
|
-
// }
|
|
994
|
-
// })
|
|
995
|
-
// }
|
|
996
|
-
|
|
997
|
-
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
998
|
-
// state.matches
|
|
999
|
-
// .find((d) => d.id === matchId)
|
|
1000
|
-
// ?.__promisesByKey[key]?.resolve(value)
|
|
1001
|
-
// }
|
|
1002
|
-
|
|
1003
|
-
// setRouteMatch = (
|
|
1004
|
-
// id: string,
|
|
1005
|
-
// pending: boolean,
|
|
1006
|
-
// updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
|
|
1007
|
-
// ) => {
|
|
1008
|
-
// const key = pending ? 'pendingMatches' : 'matches'
|
|
1009
|
-
|
|
1010
|
-
// this.setState((prev) => {
|
|
1011
|
-
// return {
|
|
1012
|
-
// ...prev,
|
|
1013
|
-
// [key]: prev[key].map((d) => {
|
|
1014
|
-
// if (d.id === id) {
|
|
1015
|
-
// return functionalUpdate(updater, d)
|
|
1016
|
-
// }
|
|
1017
|
-
|
|
1018
|
-
// return d
|
|
1019
|
-
// }),
|
|
1020
|
-
// }
|
|
1021
|
-
// })
|
|
1022
|
-
// }
|
|
1023
|
-
|
|
1024
|
-
// setPendingRouteMatch = (
|
|
1025
|
-
// id: string,
|
|
1026
|
-
// updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
|
|
1027
|
-
// ) => {
|
|
1028
|
-
// this.setRouteMatch(id, true, updater)
|
|
1029
|
-
// }
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// A function that takes an import() argument which is a function and returns a new function that will
|
|
1033
|
-
// proxy arguments from the caller to the imported function, retaining all type
|
|
1034
|
-
// information along the way
|
|
1035
|
-
function lazyFn(fn, key) {
|
|
1036
|
-
return async (...args) => {
|
|
1037
|
-
const imported = await fn();
|
|
1038
|
-
return imported[key || 'default'](...args);
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
|
-
|
|
782
|
+
// export type RouterContext<
|
|
783
|
+
// TRouteTree extends AnyRoute,
|
|
784
|
+
// // TDehydrated extends Record<string, any>,
|
|
785
|
+
// > = {
|
|
786
|
+
// buildLink: BuildLinkFn<TRouteTree>
|
|
787
|
+
// state: RouterState<TRouteTree>
|
|
788
|
+
// navigate: NavigateFn<TRouteTree>
|
|
789
|
+
// matchRoute: MatchRouteFn<TRouteTree>
|
|
790
|
+
// routeTree: TRouteTree
|
|
791
|
+
// routesById: RoutesById<TRouteTree>
|
|
792
|
+
// options: RouterOptions<TRouteTree>
|
|
793
|
+
// history: RouterHistory
|
|
794
|
+
// load: LoadFn
|
|
795
|
+
// buildLocation: BuildLocationFn<TRouteTree>
|
|
796
|
+
// subscribe: Router<TRouteTree>['subscribe']
|
|
797
|
+
// resetNextScrollRef: React.MutableRefObject<boolean>
|
|
798
|
+
// injectedHtmlRef: React.MutableRefObject<InjectedHtmlEntry[]>
|
|
799
|
+
// injectHtml: (entry: InjectedHtmlEntry) => void
|
|
800
|
+
// dehydrateData: <T>(
|
|
801
|
+
// key: any,
|
|
802
|
+
// getData: T | (() => Promise<T> | T),
|
|
803
|
+
// ) => () => void
|
|
804
|
+
// hydrateData: <T>(key: any) => T | undefined
|
|
805
|
+
// }
|
|
1042
806
|
const routerContext = /*#__PURE__*/React.createContext(null);
|
|
1043
807
|
if (typeof document !== 'undefined') {
|
|
1044
808
|
window.__TSR_ROUTER_CONTEXT__ = routerContext;
|
|
1045
809
|
}
|
|
1046
|
-
const preloadWarning = 'Error preloading route! ☝️';
|
|
1047
|
-
function isCtrlEvent(e) {
|
|
1048
|
-
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
1049
|
-
}
|
|
1050
810
|
class SearchParamError extends Error {}
|
|
1051
811
|
class PathParamError extends Error {}
|
|
1052
812
|
function getInitialRouterState(location) {
|
|
@@ -1063,66 +823,55 @@ function RouterProvider({
|
|
|
1063
823
|
router,
|
|
1064
824
|
...rest
|
|
1065
825
|
}) {
|
|
1066
|
-
|
|
826
|
+
// Allow the router to update options on the router instance
|
|
827
|
+
router.updateOptions({
|
|
1067
828
|
...router.options,
|
|
1068
829
|
...rest,
|
|
1069
830
|
context: {
|
|
1070
831
|
...router.options.context,
|
|
1071
832
|
...rest?.context
|
|
1072
833
|
}
|
|
1073
|
-
};
|
|
1074
|
-
const history = React.useState(() => options.history ?? createBrowserHistory())[0];
|
|
1075
|
-
const tempLocationKeyRef = React.useRef(`${Math.round(Math.random() * 10000000)}`);
|
|
1076
|
-
const resetNextScrollRef = React.useRef(true);
|
|
1077
|
-
const navigateTimeoutRef = React.useRef(null);
|
|
1078
|
-
const latestLoadPromiseRef = React.useRef(Promise.resolve());
|
|
1079
|
-
const checkLatest = promise => {
|
|
1080
|
-
return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
|
|
1081
|
-
};
|
|
1082
|
-
const parseLocation = useStableCallback(previousLocation => {
|
|
1083
|
-
const parse = ({
|
|
1084
|
-
pathname,
|
|
1085
|
-
search,
|
|
1086
|
-
hash,
|
|
1087
|
-
state
|
|
1088
|
-
}) => {
|
|
1089
|
-
const parsedSearch = options.parseSearch(search);
|
|
1090
|
-
return {
|
|
1091
|
-
pathname: pathname,
|
|
1092
|
-
searchStr: search,
|
|
1093
|
-
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1094
|
-
hash: hash.split('#').reverse()[0] ?? '',
|
|
1095
|
-
href: `${pathname}${search}${hash}`,
|
|
1096
|
-
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1097
|
-
};
|
|
1098
|
-
};
|
|
1099
|
-
const location = parse(history.location);
|
|
1100
|
-
let {
|
|
1101
|
-
__tempLocation,
|
|
1102
|
-
__tempKey
|
|
1103
|
-
} = location.state;
|
|
1104
|
-
if (__tempLocation && (!__tempKey || __tempKey === tempLocationKeyRef.current)) {
|
|
1105
|
-
// Sync up the location keys
|
|
1106
|
-
const parsedTempLocation = parse(__tempLocation);
|
|
1107
|
-
parsedTempLocation.state.key = location.state.key;
|
|
1108
|
-
delete parsedTempLocation.state.__tempLocation;
|
|
1109
|
-
return {
|
|
1110
|
-
...parsedTempLocation,
|
|
1111
|
-
maskedLocation: location
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
return location;
|
|
1115
834
|
});
|
|
1116
|
-
const
|
|
1117
|
-
const [preState, setState] = React.useState(() => getInitialRouterState(latestLocationRef.current));
|
|
835
|
+
const [preState, setState] = React.useState(() => router.state);
|
|
1118
836
|
const [isTransitioning, startReactTransition] = React.useTransition();
|
|
1119
|
-
const pendingMatchesRef = React.useRef([]);
|
|
1120
837
|
const state = React.useMemo(() => ({
|
|
1121
838
|
...preState,
|
|
1122
839
|
status: isTransitioning ? 'pending' : 'idle',
|
|
1123
|
-
location: isTransitioning ?
|
|
1124
|
-
pendingMatches:
|
|
840
|
+
location: isTransitioning ? router.latestLocation : preState.location,
|
|
841
|
+
pendingMatches: router.pendingMatches
|
|
1125
842
|
}), [preState, isTransitioning]);
|
|
843
|
+
router.setState = setState;
|
|
844
|
+
router.state = state;
|
|
845
|
+
router.startReactTransition = startReactTransition;
|
|
846
|
+
React.useLayoutEffect(() => {
|
|
847
|
+
const unsub = router.history.subscribe(() => {
|
|
848
|
+
router.latestLocation = router.parseLocation(router.latestLocation);
|
|
849
|
+
if (state.location !== router.latestLocation) {
|
|
850
|
+
startReactTransition(() => {
|
|
851
|
+
try {
|
|
852
|
+
router.load();
|
|
853
|
+
} catch (err) {
|
|
854
|
+
console.error(err);
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
const nextLocation = router.buildLocation({
|
|
860
|
+
search: true,
|
|
861
|
+
params: true,
|
|
862
|
+
hash: true,
|
|
863
|
+
state: true
|
|
864
|
+
});
|
|
865
|
+
if (state.location.href !== nextLocation.href) {
|
|
866
|
+
router.commitLocation({
|
|
867
|
+
...nextLocation,
|
|
868
|
+
replace: true
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
return () => {
|
|
872
|
+
unsub();
|
|
873
|
+
};
|
|
874
|
+
}, [history]);
|
|
1126
875
|
React.useLayoutEffect(() => {
|
|
1127
876
|
if (!isTransitioning && state.resolvedLocation !== state.location) {
|
|
1128
877
|
router.emit({
|
|
@@ -1131,135 +880,592 @@ function RouterProvider({
|
|
|
1131
880
|
toLocation: state.location,
|
|
1132
881
|
pathChanged: state.location.href !== state.resolvedLocation?.href
|
|
1133
882
|
});
|
|
1134
|
-
|
|
883
|
+
router.pendingMatches = [];
|
|
1135
884
|
setState(s => ({
|
|
1136
885
|
...s,
|
|
1137
886
|
resolvedLocation: s.location
|
|
1138
887
|
}));
|
|
1139
888
|
}
|
|
1140
889
|
});
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
const routesByPath = {};
|
|
1148
|
-
const recurseRoutes = routes => {
|
|
1149
|
-
routes.forEach((route, i) => {
|
|
1150
|
-
route.init({
|
|
1151
|
-
originalIndex: i
|
|
1152
|
-
});
|
|
1153
|
-
const existingRoute = routesById[route.id];
|
|
1154
|
-
invariant(!existingRoute, `Duplicate routes found with id: ${String(route.id)}`);
|
|
1155
|
-
routesById[route.id] = route;
|
|
1156
|
-
if (!route.isRoot && route.path) {
|
|
1157
|
-
const trimmedFullPath = trimPathRight(route.fullPath);
|
|
1158
|
-
if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {
|
|
1159
|
-
routesByPath[trimmedFullPath] = route;
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
const children = route.children;
|
|
1163
|
-
if (children?.length) {
|
|
1164
|
-
recurseRoutes(children);
|
|
1165
|
-
}
|
|
1166
|
-
});
|
|
1167
|
-
};
|
|
1168
|
-
recurseRoutes([router.routeTree]);
|
|
1169
|
-
return [routesById, routesByPath];
|
|
1170
|
-
}, []);
|
|
1171
|
-
const looseRoutesById = routesById;
|
|
1172
|
-
const flatRoutes = React.useMemo(() => Object.values(routesByPath).map((d, i) => {
|
|
1173
|
-
const trimmed = trimPath(d.fullPath);
|
|
1174
|
-
const parsed = parsePathname(trimmed);
|
|
1175
|
-
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1176
|
-
parsed.shift();
|
|
1177
|
-
}
|
|
1178
|
-
const score = parsed.map(d => {
|
|
1179
|
-
if (d.type === 'param') {
|
|
1180
|
-
return 0.5;
|
|
1181
|
-
}
|
|
1182
|
-
if (d.type === 'wildcard') {
|
|
1183
|
-
return 0.25;
|
|
890
|
+
React.useLayoutEffect(() => {
|
|
891
|
+
startReactTransition(() => {
|
|
892
|
+
try {
|
|
893
|
+
router.load();
|
|
894
|
+
} catch (err) {
|
|
895
|
+
console.error(err);
|
|
1184
896
|
}
|
|
1185
|
-
return 1;
|
|
1186
897
|
});
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
898
|
+
}, []);
|
|
899
|
+
return /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
900
|
+
value: router
|
|
901
|
+
}, /*#__PURE__*/React.createElement(Matches, null));
|
|
902
|
+
}
|
|
903
|
+
function getRouteMatch(state, id) {
|
|
904
|
+
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
905
|
+
}
|
|
906
|
+
function useRouterState(opts) {
|
|
907
|
+
const {
|
|
908
|
+
state
|
|
909
|
+
} = useRouter();
|
|
910
|
+
// return useStore(router.__store, opts?.select as any)
|
|
911
|
+
return opts?.select ? opts.select(state) : state;
|
|
912
|
+
}
|
|
913
|
+
function useRouter() {
|
|
914
|
+
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
915
|
+
const value = React.useContext(resolvedContext);
|
|
916
|
+
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
917
|
+
return value;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
function defer(_promise) {
|
|
921
|
+
const promise = _promise;
|
|
922
|
+
if (!promise.__deferredState) {
|
|
923
|
+
promise.__deferredState = {
|
|
924
|
+
uid: Math.random().toString(36).slice(2),
|
|
925
|
+
status: 'pending'
|
|
1193
926
|
};
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
927
|
+
const state = promise.__deferredState;
|
|
928
|
+
promise.then(data => {
|
|
929
|
+
state.status = 'success';
|
|
930
|
+
state.data = data;
|
|
931
|
+
}).catch(error => {
|
|
932
|
+
state.status = 'error';
|
|
933
|
+
state.error = error;
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
return promise;
|
|
937
|
+
}
|
|
938
|
+
function isDehydratedDeferred(obj) {
|
|
939
|
+
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
940
|
+
}
|
|
1203
941
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
942
|
+
function useAwaited({
|
|
943
|
+
promise
|
|
944
|
+
}) {
|
|
945
|
+
const router = useRouter();
|
|
946
|
+
let state = promise.__deferredState;
|
|
947
|
+
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
948
|
+
if (isDehydratedDeferred(promise)) {
|
|
949
|
+
state = router.hydrateData(key);
|
|
950
|
+
promise = Promise.resolve(state.data);
|
|
951
|
+
promise.__deferredState = state;
|
|
952
|
+
}
|
|
953
|
+
if (state.status === 'pending') {
|
|
954
|
+
throw promise;
|
|
955
|
+
}
|
|
956
|
+
if (state.status === 'error') {
|
|
957
|
+
throw state.error;
|
|
958
|
+
}
|
|
959
|
+
router.dehydrateData(key, state);
|
|
960
|
+
return [state.data];
|
|
961
|
+
}
|
|
962
|
+
function Await(props) {
|
|
963
|
+
const awaited = useAwaited(props);
|
|
964
|
+
return props.children(...awaited);
|
|
965
|
+
}
|
|
1210
966
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
967
|
+
class FileRoute {
|
|
968
|
+
constructor(path) {
|
|
969
|
+
this.path = path;
|
|
970
|
+
}
|
|
971
|
+
createRoute = options => {
|
|
972
|
+
const route = new Route(options);
|
|
973
|
+
route.isRoot = false;
|
|
974
|
+
return route;
|
|
975
|
+
};
|
|
976
|
+
}
|
|
1217
977
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
978
|
+
function lazyRouteComponent(importer, exportName) {
|
|
979
|
+
let loadPromise;
|
|
980
|
+
const load = () => {
|
|
981
|
+
if (!loadPromise) {
|
|
982
|
+
loadPromise = importer();
|
|
1221
983
|
}
|
|
984
|
+
return loadPromise;
|
|
985
|
+
};
|
|
986
|
+
const lazyComp = /*#__PURE__*/React.lazy(async () => {
|
|
987
|
+
const moduleExports = await load();
|
|
988
|
+
const comp = moduleExports[exportName ?? 'default'];
|
|
989
|
+
return {
|
|
990
|
+
default: comp
|
|
991
|
+
};
|
|
992
|
+
});
|
|
993
|
+
lazyComp.preload = load;
|
|
994
|
+
return lazyComp;
|
|
995
|
+
}
|
|
1222
996
|
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
let foundRoute = flatRoutes.find(route => {
|
|
1232
|
-
const matchedParams = matchPathname(basepath, trimPathRight(pathname), {
|
|
1233
|
-
to: route.fullPath,
|
|
1234
|
-
caseSensitive: route.options.caseSensitive ?? options.caseSensitive,
|
|
1235
|
-
fuzzy: false
|
|
1236
|
-
});
|
|
1237
|
-
if (matchedParams) {
|
|
1238
|
-
routeParams = matchedParams;
|
|
1239
|
-
return true;
|
|
997
|
+
function _extends() {
|
|
998
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
999
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1000
|
+
var source = arguments[i];
|
|
1001
|
+
for (var key in source) {
|
|
1002
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1003
|
+
target[key] = source[key];
|
|
1004
|
+
}
|
|
1240
1005
|
}
|
|
1241
|
-
return false;
|
|
1242
|
-
});
|
|
1243
|
-
let routeCursor = foundRoute || routesById['__root__'];
|
|
1244
|
-
let matchedRoutes = [routeCursor];
|
|
1245
|
-
// let includingLayouts = true
|
|
1246
|
-
while (routeCursor?.parentRoute) {
|
|
1247
|
-
routeCursor = routeCursor.parentRoute;
|
|
1248
|
-
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1249
1006
|
}
|
|
1007
|
+
return target;
|
|
1008
|
+
};
|
|
1009
|
+
return _extends.apply(this, arguments);
|
|
1010
|
+
}
|
|
1250
1011
|
|
|
1251
|
-
|
|
1252
|
-
|
|
1012
|
+
function useLinkProps(options) {
|
|
1013
|
+
const {
|
|
1014
|
+
buildLink
|
|
1015
|
+
} = useRouter();
|
|
1016
|
+
const match = useMatch({
|
|
1017
|
+
strict: false
|
|
1018
|
+
});
|
|
1019
|
+
const {
|
|
1020
|
+
// custom props
|
|
1021
|
+
type,
|
|
1022
|
+
children,
|
|
1023
|
+
target,
|
|
1024
|
+
activeProps = () => ({
|
|
1025
|
+
className: 'active'
|
|
1026
|
+
}),
|
|
1027
|
+
inactiveProps = () => ({}),
|
|
1028
|
+
activeOptions,
|
|
1029
|
+
disabled,
|
|
1030
|
+
hash,
|
|
1031
|
+
search,
|
|
1032
|
+
params,
|
|
1033
|
+
to,
|
|
1034
|
+
state,
|
|
1035
|
+
mask,
|
|
1036
|
+
preload,
|
|
1037
|
+
preloadDelay,
|
|
1038
|
+
replace,
|
|
1039
|
+
startTransition,
|
|
1040
|
+
resetScroll,
|
|
1041
|
+
// element props
|
|
1042
|
+
style,
|
|
1043
|
+
className,
|
|
1044
|
+
onClick,
|
|
1045
|
+
onFocus,
|
|
1046
|
+
onMouseEnter,
|
|
1047
|
+
onMouseLeave,
|
|
1048
|
+
onTouchStart,
|
|
1049
|
+
...rest
|
|
1050
|
+
} = options;
|
|
1051
|
+
const linkInfo = buildLink({
|
|
1052
|
+
from: options.to ? match.pathname : undefined,
|
|
1053
|
+
...options
|
|
1054
|
+
});
|
|
1055
|
+
if (linkInfo.type === 'external') {
|
|
1056
|
+
const {
|
|
1057
|
+
href
|
|
1058
|
+
} = linkInfo;
|
|
1059
|
+
return {
|
|
1060
|
+
href
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
const {
|
|
1064
|
+
handleClick,
|
|
1065
|
+
handleFocus,
|
|
1066
|
+
handleEnter,
|
|
1067
|
+
handleLeave,
|
|
1068
|
+
handleTouchStart,
|
|
1069
|
+
isActive,
|
|
1070
|
+
next
|
|
1071
|
+
} = linkInfo;
|
|
1072
|
+
const composeHandlers = handlers => e => {
|
|
1073
|
+
if (e.persist) e.persist();
|
|
1074
|
+
handlers.filter(Boolean).forEach(handler => {
|
|
1075
|
+
if (e.defaultPrevented) return;
|
|
1076
|
+
handler(e);
|
|
1077
|
+
});
|
|
1078
|
+
};
|
|
1253
1079
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1080
|
+
// Get the active props
|
|
1081
|
+
const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
|
|
1082
|
+
|
|
1083
|
+
// Get the inactive props
|
|
1084
|
+
const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
|
|
1085
|
+
return {
|
|
1086
|
+
...resolvedActiveProps,
|
|
1087
|
+
...resolvedInactiveProps,
|
|
1088
|
+
...rest,
|
|
1089
|
+
href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
|
|
1090
|
+
onClick: composeHandlers([onClick, handleClick]),
|
|
1091
|
+
onFocus: composeHandlers([onFocus, handleFocus]),
|
|
1092
|
+
onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
|
|
1093
|
+
onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
|
|
1094
|
+
onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
|
|
1095
|
+
target,
|
|
1096
|
+
style: {
|
|
1097
|
+
...style,
|
|
1098
|
+
...resolvedActiveProps.style,
|
|
1099
|
+
...resolvedInactiveProps.style
|
|
1100
|
+
},
|
|
1101
|
+
className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
|
|
1102
|
+
...(disabled ? {
|
|
1103
|
+
role: 'link',
|
|
1104
|
+
'aria-disabled': true
|
|
1105
|
+
} : undefined),
|
|
1106
|
+
['data-status']: isActive ? 'active' : undefined
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
const Link = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1110
|
+
const linkProps = useLinkProps(props);
|
|
1111
|
+
return /*#__PURE__*/React.createElement("a", _extends({
|
|
1112
|
+
ref: ref
|
|
1113
|
+
}, linkProps, {
|
|
1114
|
+
children: typeof props.children === 'function' ? props.children({
|
|
1115
|
+
isActive: linkProps['data-status'] === 'active'
|
|
1116
|
+
}) : props.children
|
|
1117
|
+
}));
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
// @ts-nocheck
|
|
1121
|
+
|
|
1122
|
+
// qss has been slightly modified and inlined here for our use cases (and compression's sake). We've included it as a hard dependency for MIT license attribution.
|
|
1123
|
+
|
|
1124
|
+
function encode(obj, pfx) {
|
|
1125
|
+
var k,
|
|
1126
|
+
i,
|
|
1127
|
+
tmp,
|
|
1128
|
+
str = '';
|
|
1129
|
+
for (k in obj) {
|
|
1130
|
+
if ((tmp = obj[k]) !== void 0) {
|
|
1131
|
+
if (Array.isArray(tmp)) {
|
|
1132
|
+
for (i = 0; i < tmp.length; i++) {
|
|
1133
|
+
str && (str += '&');
|
|
1134
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
1135
|
+
}
|
|
1136
|
+
} else {
|
|
1137
|
+
str && (str += '&');
|
|
1138
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return (pfx || '') + str;
|
|
1143
|
+
}
|
|
1144
|
+
function toValue(mix) {
|
|
1145
|
+
if (!mix) return '';
|
|
1146
|
+
var str = decodeURIComponent(mix);
|
|
1147
|
+
if (str === 'false') return false;
|
|
1148
|
+
if (str === 'true') return true;
|
|
1149
|
+
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
1150
|
+
}
|
|
1151
|
+
function decode(str) {
|
|
1152
|
+
var tmp,
|
|
1153
|
+
k,
|
|
1154
|
+
out = {},
|
|
1155
|
+
arr = str.split('&');
|
|
1156
|
+
while (tmp = arr.shift()) {
|
|
1157
|
+
tmp = tmp.split('=');
|
|
1158
|
+
k = tmp.shift();
|
|
1159
|
+
if (out[k] !== void 0) {
|
|
1160
|
+
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
1161
|
+
} else {
|
|
1162
|
+
out[k] = toValue(tmp.shift());
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return out;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// Detect if we're in the DOM
|
|
1169
|
+
|
|
1170
|
+
function redirect(opts) {
|
|
1171
|
+
opts.isRedirect = true;
|
|
1172
|
+
return opts;
|
|
1173
|
+
}
|
|
1174
|
+
function isRedirect(obj) {
|
|
1175
|
+
return !!obj?.isRedirect;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
1179
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
1180
|
+
function parseSearchWith(parser) {
|
|
1181
|
+
return searchStr => {
|
|
1182
|
+
if (searchStr.substring(0, 1) === '?') {
|
|
1183
|
+
searchStr = searchStr.substring(1);
|
|
1184
|
+
}
|
|
1185
|
+
let query = decode(searchStr);
|
|
1186
|
+
|
|
1187
|
+
// Try to parse any query params that might be json
|
|
1188
|
+
for (let key in query) {
|
|
1189
|
+
const value = query[key];
|
|
1190
|
+
if (typeof value === 'string') {
|
|
1191
|
+
try {
|
|
1192
|
+
query[key] = parser(value);
|
|
1193
|
+
} catch (err) {
|
|
1194
|
+
//
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return query;
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
function stringifySearchWith(stringify, parser) {
|
|
1202
|
+
function stringifyValue(val) {
|
|
1203
|
+
if (typeof val === 'object' && val !== null) {
|
|
1204
|
+
try {
|
|
1205
|
+
return stringify(val);
|
|
1206
|
+
} catch (err) {
|
|
1207
|
+
// silent
|
|
1208
|
+
}
|
|
1209
|
+
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
1210
|
+
try {
|
|
1211
|
+
// Check if it's a valid parseable string.
|
|
1212
|
+
// If it is, then stringify it again.
|
|
1213
|
+
parser(val);
|
|
1214
|
+
return stringify(val);
|
|
1215
|
+
} catch (err) {
|
|
1216
|
+
// silent
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
return val;
|
|
1220
|
+
}
|
|
1221
|
+
return search => {
|
|
1222
|
+
search = {
|
|
1223
|
+
...search
|
|
1224
|
+
};
|
|
1225
|
+
if (search) {
|
|
1226
|
+
Object.keys(search).forEach(key => {
|
|
1227
|
+
const val = search[key];
|
|
1228
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
1229
|
+
delete search[key];
|
|
1230
|
+
} else {
|
|
1231
|
+
search[key] = stringifyValue(val);
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
const searchStr = encode(search).toString();
|
|
1236
|
+
return searchStr ? `?${searchStr}` : '';
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
//
|
|
1241
|
+
|
|
1242
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
1243
|
+
const preloadWarning = 'Error preloading route! ☝️';
|
|
1244
|
+
class Router {
|
|
1245
|
+
// Option-independent properties
|
|
1246
|
+
tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
|
|
1247
|
+
resetNextScroll = true;
|
|
1248
|
+
navigateTimeout = null;
|
|
1249
|
+
latestLoadPromise = Promise.resolve();
|
|
1250
|
+
subscribers = new Set();
|
|
1251
|
+
pendingMatches = [];
|
|
1252
|
+
injectedHtml = [];
|
|
1253
|
+
|
|
1254
|
+
// Must build in constructor
|
|
1255
|
+
|
|
1256
|
+
constructor(options) {
|
|
1257
|
+
this.updateOptions({
|
|
1258
|
+
defaultPreloadDelay: 50,
|
|
1259
|
+
context: undefined,
|
|
1260
|
+
...options,
|
|
1261
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
1262
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
startReactTransition = () => {
|
|
1266
|
+
warning(false, 'startReactTransition implementation is missing. If you see this, please file an issue.');
|
|
1267
|
+
};
|
|
1268
|
+
setState = () => {
|
|
1269
|
+
warning(false, 'setState implementation is missing. If you see this, please file an issue.');
|
|
1270
|
+
};
|
|
1271
|
+
updateOptions = newOptions => {
|
|
1272
|
+
this.options;
|
|
1273
|
+
this.options = {
|
|
1274
|
+
...this.options,
|
|
1275
|
+
...newOptions
|
|
1276
|
+
};
|
|
1277
|
+
this.basepath = `/${trimPath(newOptions.basepath ?? '') ?? ''}`;
|
|
1278
|
+
if (!this.history || this.options.history && this.options.history !== this.history) {
|
|
1279
|
+
this.history = this.options.history ?? createBrowserHistory();
|
|
1280
|
+
this.latestLocation = this.parseLocation();
|
|
1281
|
+
}
|
|
1282
|
+
if (this.options.routeTree !== this.routeTree) {
|
|
1283
|
+
this.routeTree = this.options.routeTree;
|
|
1284
|
+
this.buildRouteTree();
|
|
1285
|
+
}
|
|
1286
|
+
if (!this.state) {
|
|
1287
|
+
this.state = getInitialRouterState(this.latestLocation);
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
buildRouteTree = () => {
|
|
1291
|
+
this.routesById = {};
|
|
1292
|
+
this.routesByPath = {};
|
|
1293
|
+
const recurseRoutes = childRoutes => {
|
|
1294
|
+
childRoutes.forEach((childRoute, i) => {
|
|
1295
|
+
// if (typeof childRoute === 'function') {
|
|
1296
|
+
// childRoute = (childRoute as any)()
|
|
1297
|
+
// }
|
|
1298
|
+
childRoute.init({
|
|
1299
|
+
originalIndex: i
|
|
1300
|
+
});
|
|
1301
|
+
const existingRoute = this.routesById[childRoute.id];
|
|
1302
|
+
invariant(!existingRoute, `Duplicate routes found with id: ${String(childRoute.id)}`);
|
|
1303
|
+
this.routesById[childRoute.id] = childRoute;
|
|
1304
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
1305
|
+
const trimmedFullPath = trimPathRight(childRoute.fullPath);
|
|
1306
|
+
if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith('/')) {
|
|
1307
|
+
this.routesByPath[trimmedFullPath] = childRoute;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
const children = childRoute.children;
|
|
1311
|
+
if (children?.length) {
|
|
1312
|
+
recurseRoutes(children);
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
};
|
|
1316
|
+
recurseRoutes([this.routeTree]);
|
|
1317
|
+
this.flatRoutes = Object.values(this.routesByPath).map((d, i) => {
|
|
1318
|
+
const trimmed = trimPath(d.fullPath);
|
|
1319
|
+
const parsed = parsePathname(trimmed);
|
|
1320
|
+
while (parsed.length > 1 && parsed[0]?.value === '/') {
|
|
1321
|
+
parsed.shift();
|
|
1322
|
+
}
|
|
1323
|
+
const score = parsed.map(d => {
|
|
1324
|
+
if (d.type === 'param') {
|
|
1325
|
+
return 0.5;
|
|
1326
|
+
}
|
|
1327
|
+
if (d.type === 'wildcard') {
|
|
1328
|
+
return 0.25;
|
|
1329
|
+
}
|
|
1330
|
+
return 1;
|
|
1331
|
+
});
|
|
1332
|
+
return {
|
|
1333
|
+
child: d,
|
|
1334
|
+
trimmed,
|
|
1335
|
+
parsed,
|
|
1336
|
+
index: i,
|
|
1337
|
+
score
|
|
1338
|
+
};
|
|
1339
|
+
}).sort((a, b) => {
|
|
1340
|
+
let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
|
|
1341
|
+
if (isIndex !== 0) return isIndex;
|
|
1342
|
+
const length = Math.min(a.score.length, b.score.length);
|
|
1343
|
+
|
|
1344
|
+
// Sort by length of score
|
|
1345
|
+
if (a.score.length !== b.score.length) {
|
|
1346
|
+
return b.score.length - a.score.length;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// Sort by min available score
|
|
1350
|
+
for (let i = 0; i < length; i++) {
|
|
1351
|
+
if (a.score[i] !== b.score[i]) {
|
|
1352
|
+
return b.score[i] - a.score[i];
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// Sort by min available parsed value
|
|
1357
|
+
for (let i = 0; i < length; i++) {
|
|
1358
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
1359
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// Sort by length of trimmed full path
|
|
1364
|
+
if (a.trimmed !== b.trimmed) {
|
|
1365
|
+
return a.trimmed > b.trimmed ? 1 : -1;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// Sort by original index
|
|
1369
|
+
return a.index - b.index;
|
|
1370
|
+
}).map((d, i) => {
|
|
1371
|
+
d.child.rank = i;
|
|
1372
|
+
return d.child;
|
|
1373
|
+
});
|
|
1374
|
+
};
|
|
1375
|
+
subscribe = (eventType, fn) => {
|
|
1376
|
+
const listener = {
|
|
1377
|
+
eventType,
|
|
1378
|
+
fn
|
|
1379
|
+
};
|
|
1380
|
+
this.subscribers.add(listener);
|
|
1381
|
+
return () => {
|
|
1382
|
+
this.subscribers.delete(listener);
|
|
1383
|
+
};
|
|
1384
|
+
};
|
|
1385
|
+
emit = routerEvent => {
|
|
1386
|
+
this.subscribers.forEach(listener => {
|
|
1387
|
+
if (listener.eventType === routerEvent.type) {
|
|
1388
|
+
listener.fn(routerEvent);
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
};
|
|
1392
|
+
checkLatest = promise => {
|
|
1393
|
+
return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
|
|
1394
|
+
};
|
|
1395
|
+
parseLocation = previousLocation => {
|
|
1396
|
+
const parse = ({
|
|
1397
|
+
pathname,
|
|
1398
|
+
search,
|
|
1399
|
+
hash,
|
|
1400
|
+
state
|
|
1401
|
+
}) => {
|
|
1402
|
+
const parsedSearch = this.options.parseSearch(search);
|
|
1403
|
+
return {
|
|
1404
|
+
pathname: pathname,
|
|
1405
|
+
searchStr: search,
|
|
1406
|
+
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
1407
|
+
hash: hash.split('#').reverse()[0] ?? '',
|
|
1408
|
+
href: `${pathname}${search}${hash}`,
|
|
1409
|
+
state: replaceEqualDeep(previousLocation?.state, state)
|
|
1410
|
+
};
|
|
1411
|
+
};
|
|
1412
|
+
const location = parse(this.history.location);
|
|
1413
|
+
let {
|
|
1414
|
+
__tempLocation,
|
|
1415
|
+
__tempKey
|
|
1416
|
+
} = location.state;
|
|
1417
|
+
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
1418
|
+
// Sync up the location keys
|
|
1419
|
+
const parsedTempLocation = parse(__tempLocation);
|
|
1420
|
+
parsedTempLocation.state.key = location.state.key;
|
|
1421
|
+
delete parsedTempLocation.state.__tempLocation;
|
|
1422
|
+
return {
|
|
1423
|
+
...parsedTempLocation,
|
|
1424
|
+
maskedLocation: location
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
return location;
|
|
1428
|
+
};
|
|
1429
|
+
resolvePathWithBase = (from, path) => {
|
|
1430
|
+
return resolvePath(this.basepath, from, cleanPath(path));
|
|
1431
|
+
};
|
|
1432
|
+
get looseRoutesById() {
|
|
1433
|
+
return this.routesById;
|
|
1434
|
+
}
|
|
1435
|
+
matchRoutes = (pathname, locationSearch, opts) => {
|
|
1436
|
+
let routeParams = {};
|
|
1437
|
+
let foundRoute = this.flatRoutes.find(route => {
|
|
1438
|
+
const matchedParams = matchPathname(this.basepath, trimPathRight(pathname), {
|
|
1439
|
+
to: route.fullPath,
|
|
1440
|
+
caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
|
|
1441
|
+
fuzzy: false
|
|
1442
|
+
});
|
|
1443
|
+
if (matchedParams) {
|
|
1444
|
+
routeParams = matchedParams;
|
|
1445
|
+
return true;
|
|
1446
|
+
}
|
|
1447
|
+
return false;
|
|
1448
|
+
});
|
|
1449
|
+
let routeCursor = foundRoute || this.routesById['__root__'];
|
|
1450
|
+
let matchedRoutes = [routeCursor];
|
|
1451
|
+
// let includingLayouts = true
|
|
1452
|
+
while (routeCursor?.parentRoute) {
|
|
1453
|
+
routeCursor = routeCursor.parentRoute;
|
|
1454
|
+
if (routeCursor) matchedRoutes.unshift(routeCursor);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
// Existing matches are matches that are already loaded along with
|
|
1458
|
+
// pending matches that are still loading
|
|
1459
|
+
|
|
1460
|
+
const parseErrors = matchedRoutes.map(route => {
|
|
1461
|
+
let parsedParamsError;
|
|
1462
|
+
if (route.options.parseParams) {
|
|
1463
|
+
try {
|
|
1464
|
+
const parsedParams = route.options.parseParams(routeParams);
|
|
1465
|
+
// Add the parsed params to the accumulated params bag
|
|
1466
|
+
Object.assign(routeParams, parsedParams);
|
|
1467
|
+
} catch (err) {
|
|
1468
|
+
parsedParamsError = new PathParamError(err.message, {
|
|
1263
1469
|
cause: err
|
|
1264
1470
|
});
|
|
1265
1471
|
if (opts?.throwOnError) {
|
|
@@ -1277,10 +1483,12 @@ function RouterProvider({
|
|
|
1277
1483
|
// Waste not, want not. If we already have a match for this route,
|
|
1278
1484
|
// reuse it. This is important for layout routes, which might stick
|
|
1279
1485
|
// around between navigation actions that only change leaf routes.
|
|
1280
|
-
const existingMatch = getRouteMatch(state, matchId);
|
|
1486
|
+
const existingMatch = getRouteMatch(this.state, matchId);
|
|
1487
|
+
const cause = this.state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
|
|
1281
1488
|
if (existingMatch) {
|
|
1282
1489
|
return {
|
|
1283
|
-
...existingMatch
|
|
1490
|
+
...existingMatch,
|
|
1491
|
+
cause
|
|
1284
1492
|
};
|
|
1285
1493
|
}
|
|
1286
1494
|
|
|
@@ -1290,7 +1498,7 @@ function RouterProvider({
|
|
|
1290
1498
|
id: matchId,
|
|
1291
1499
|
routeId: route.id,
|
|
1292
1500
|
params: routeParams,
|
|
1293
|
-
pathname: joinPaths([basepath, interpolatedPath]),
|
|
1501
|
+
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
1294
1502
|
updatedAt: Date.now(),
|
|
1295
1503
|
routeSearch: {},
|
|
1296
1504
|
search: {},
|
|
@@ -1304,7 +1512,8 @@ function RouterProvider({
|
|
|
1304
1512
|
context: undefined,
|
|
1305
1513
|
abortController: new AbortController(),
|
|
1306
1514
|
shouldReloadDeps: undefined,
|
|
1307
|
-
fetchedAt: 0
|
|
1515
|
+
fetchedAt: 0,
|
|
1516
|
+
cause
|
|
1308
1517
|
};
|
|
1309
1518
|
return routeMatch;
|
|
1310
1519
|
});
|
|
@@ -1314,7 +1523,7 @@ function RouterProvider({
|
|
|
1314
1523
|
// so that we can use the parent match's search params and context
|
|
1315
1524
|
matches.forEach((match, i) => {
|
|
1316
1525
|
const parentMatch = matches[i - 1];
|
|
1317
|
-
const route = looseRoutesById[match.routeId];
|
|
1526
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1318
1527
|
const searchInfo = (() => {
|
|
1319
1528
|
// Validate the search params and stabilize them
|
|
1320
1529
|
const parentSearchInfo = {
|
|
@@ -1348,28 +1557,28 @@ function RouterProvider({
|
|
|
1348
1557
|
Object.assign(match, searchInfo);
|
|
1349
1558
|
});
|
|
1350
1559
|
return matches;
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
getRouteMatch(state, id)?.abortController?.abort();
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
state.matches.forEach(match => {
|
|
1357
|
-
cancelMatch(match.id);
|
|
1560
|
+
};
|
|
1561
|
+
cancelMatch = id => {
|
|
1562
|
+
getRouteMatch(this.state, id)?.abortController?.abort();
|
|
1563
|
+
};
|
|
1564
|
+
cancelMatches = () => {
|
|
1565
|
+
this.state.matches.forEach(match => {
|
|
1566
|
+
this.cancelMatch(match.id);
|
|
1358
1567
|
});
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1568
|
+
};
|
|
1569
|
+
buildLocation = opts => {
|
|
1361
1570
|
const build = (dest = {}, matches) => {
|
|
1362
|
-
const from =
|
|
1571
|
+
const from = this.latestLocation;
|
|
1363
1572
|
const fromPathname = dest.from ?? from.pathname;
|
|
1364
|
-
let pathname = resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
|
|
1365
|
-
const fromMatches = matchRoutes(fromPathname, from.search);
|
|
1573
|
+
let pathname = this.resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
|
|
1574
|
+
const fromMatches = this.matchRoutes(fromPathname, from.search);
|
|
1366
1575
|
const stayingMatches = matches?.filter(d => fromMatches?.find(e => e.routeId === d.routeId));
|
|
1367
1576
|
const prevParams = {
|
|
1368
1577
|
...last(fromMatches)?.params
|
|
1369
1578
|
};
|
|
1370
1579
|
let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
|
|
1371
1580
|
if (nextParams) {
|
|
1372
|
-
matches?.map(d => looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1581
|
+
matches?.map(d => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
|
|
1373
1582
|
nextParams = {
|
|
1374
1583
|
...nextParams,
|
|
1375
1584
|
...fn(nextParams)
|
|
@@ -1377,8 +1586,8 @@ function RouterProvider({
|
|
|
1377
1586
|
});
|
|
1378
1587
|
}
|
|
1379
1588
|
pathname = interpolatePath(pathname, nextParams ?? {});
|
|
1380
|
-
const preSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1381
|
-
const postSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1589
|
+
const preSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1590
|
+
const postSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
|
|
1382
1591
|
|
|
1383
1592
|
// Pre filters first
|
|
1384
1593
|
const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
|
|
@@ -1392,7 +1601,7 @@ function RouterProvider({
|
|
|
1392
1601
|
// Then post filters
|
|
1393
1602
|
const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
|
|
1394
1603
|
const search = replaceEqualDeep(from.search, postFilteredSearch);
|
|
1395
|
-
const searchStr = options.stringifySearch(search);
|
|
1604
|
+
const searchStr = this.options.stringifySearch(search);
|
|
1396
1605
|
const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
|
|
1397
1606
|
const hashStr = hash ? `#${hash}` : '';
|
|
1398
1607
|
let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
|
|
@@ -1403,7 +1612,7 @@ function RouterProvider({
|
|
|
1403
1612
|
searchStr,
|
|
1404
1613
|
state: nextState,
|
|
1405
1614
|
hash,
|
|
1406
|
-
href: history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1615
|
+
href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
|
|
1407
1616
|
unmaskOnReload: dest.unmaskOnReload
|
|
1408
1617
|
};
|
|
1409
1618
|
};
|
|
@@ -1412,8 +1621,8 @@ function RouterProvider({
|
|
|
1412
1621
|
let maskedNext = maskedDest ? build(maskedDest) : undefined;
|
|
1413
1622
|
if (!maskedNext) {
|
|
1414
1623
|
let params = {};
|
|
1415
|
-
let foundMask = options.routeMasks?.find(d => {
|
|
1416
|
-
const match = matchPathname(basepath, next.pathname, {
|
|
1624
|
+
let foundMask = this.options.routeMasks?.find(d => {
|
|
1625
|
+
const match = matchPathname(this.basepath, next.pathname, {
|
|
1417
1626
|
to: d.from,
|
|
1418
1627
|
caseSensitive: false,
|
|
1419
1628
|
fuzzy: false
|
|
@@ -1433,8 +1642,8 @@ function RouterProvider({
|
|
|
1433
1642
|
maskedNext = build(maskedDest);
|
|
1434
1643
|
}
|
|
1435
1644
|
}
|
|
1436
|
-
const nextMatches = matchRoutes(next.pathname, next.search);
|
|
1437
|
-
const maskedMatches = maskedNext ? matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1645
|
+
const nextMatches = this.matchRoutes(next.pathname, next.search);
|
|
1646
|
+
const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
|
|
1438
1647
|
const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
|
|
1439
1648
|
const final = build(dest, nextMatches);
|
|
1440
1649
|
if (maskedFinal) {
|
|
@@ -1449,13 +1658,13 @@ function RouterProvider({
|
|
|
1449
1658
|
});
|
|
1450
1659
|
}
|
|
1451
1660
|
return buildWithMatches(opts);
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1661
|
+
};
|
|
1662
|
+
commitLocation = async ({
|
|
1454
1663
|
startTransition,
|
|
1455
1664
|
...next
|
|
1456
1665
|
}) => {
|
|
1457
|
-
if (
|
|
1458
|
-
const isSameUrl =
|
|
1666
|
+
if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
|
|
1667
|
+
const isSameUrl = this.latestLocation.href === next.href;
|
|
1459
1668
|
|
|
1460
1669
|
// If the next urls are the same and we're not replacing,
|
|
1461
1670
|
// do nothing
|
|
@@ -1482,37 +1691,37 @@ function RouterProvider({
|
|
|
1482
1691
|
}
|
|
1483
1692
|
}
|
|
1484
1693
|
};
|
|
1485
|
-
if (nextHistory.unmaskOnReload ?? options.unmaskOnReload ?? false) {
|
|
1486
|
-
nextHistory.state.__tempKey =
|
|
1694
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
1695
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
1487
1696
|
}
|
|
1488
1697
|
}
|
|
1489
1698
|
const apply = () => {
|
|
1490
|
-
history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
|
|
1699
|
+
this.history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
|
|
1491
1700
|
};
|
|
1492
1701
|
if (startTransition ?? true) {
|
|
1493
|
-
startReactTransition(apply);
|
|
1702
|
+
this.startReactTransition(apply);
|
|
1494
1703
|
} else {
|
|
1495
1704
|
apply();
|
|
1496
1705
|
}
|
|
1497
1706
|
}
|
|
1498
|
-
|
|
1499
|
-
return
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1707
|
+
this.resetNextScroll = next.resetScroll ?? true;
|
|
1708
|
+
return this.latestLoadPromise;
|
|
1709
|
+
};
|
|
1710
|
+
buildAndCommitLocation = ({
|
|
1502
1711
|
replace,
|
|
1503
1712
|
resetScroll,
|
|
1504
1713
|
startTransition,
|
|
1505
1714
|
...rest
|
|
1506
1715
|
} = {}) => {
|
|
1507
|
-
const location = buildLocation(rest);
|
|
1508
|
-
return commitLocation({
|
|
1716
|
+
const location = this.buildLocation(rest);
|
|
1717
|
+
return this.commitLocation({
|
|
1509
1718
|
...location,
|
|
1510
1719
|
startTransition,
|
|
1511
1720
|
replace,
|
|
1512
1721
|
resetScroll
|
|
1513
1722
|
});
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1723
|
+
};
|
|
1724
|
+
navigate = ({
|
|
1516
1725
|
from,
|
|
1517
1726
|
to = '',
|
|
1518
1727
|
...rest
|
|
@@ -1530,13 +1739,13 @@ function RouterProvider({
|
|
|
1530
1739
|
isExternal = true;
|
|
1531
1740
|
} catch (e) {}
|
|
1532
1741
|
invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
|
|
1533
|
-
return buildAndCommitLocation({
|
|
1742
|
+
return this.buildAndCommitLocation({
|
|
1534
1743
|
...rest,
|
|
1535
1744
|
from: fromString,
|
|
1536
1745
|
to: toString
|
|
1537
1746
|
});
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1747
|
+
};
|
|
1748
|
+
loadMatches = async ({
|
|
1540
1749
|
checkLatest,
|
|
1541
1750
|
matches,
|
|
1542
1751
|
preload
|
|
@@ -1548,7 +1757,7 @@ function RouterProvider({
|
|
|
1548
1757
|
try {
|
|
1549
1758
|
for (let [index, match] of matches.entries()) {
|
|
1550
1759
|
const parentMatch = matches[index - 1];
|
|
1551
|
-
const route = looseRoutesById[match.routeId];
|
|
1760
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1552
1761
|
const handleError = (err, code) => {
|
|
1553
1762
|
err.routerCode = code;
|
|
1554
1763
|
firstBadMatchIndex = firstBadMatchIndex ?? index;
|
|
@@ -1577,19 +1786,21 @@ function RouterProvider({
|
|
|
1577
1786
|
if (match.searchError) {
|
|
1578
1787
|
handleError(match.searchError, 'VALIDATE_SEARCH');
|
|
1579
1788
|
}
|
|
1580
|
-
const parentContext = parentMatch?.context ?? options.context ?? {};
|
|
1789
|
+
const parentContext = parentMatch?.context ?? this.options.context ?? {};
|
|
1581
1790
|
const beforeLoadContext = (await route.options.beforeLoad?.({
|
|
1582
1791
|
search: match.search,
|
|
1583
1792
|
abortController: match.abortController,
|
|
1584
1793
|
params: match.params,
|
|
1585
1794
|
preload: !!preload,
|
|
1586
1795
|
context: parentContext,
|
|
1587
|
-
location: state.location,
|
|
1588
|
-
|
|
1796
|
+
location: this.state.location,
|
|
1797
|
+
// TOOD: just expose state and router, etc
|
|
1798
|
+
navigate: opts => this.navigate({
|
|
1589
1799
|
...opts,
|
|
1590
1800
|
from: match.pathname
|
|
1591
1801
|
}),
|
|
1592
|
-
buildLocation
|
|
1802
|
+
buildLocation: this.buildLocation,
|
|
1803
|
+
cause: match.cause
|
|
1593
1804
|
})) ?? {};
|
|
1594
1805
|
const context = {
|
|
1595
1806
|
...parentContext,
|
|
@@ -1606,7 +1817,7 @@ function RouterProvider({
|
|
|
1606
1817
|
}
|
|
1607
1818
|
} catch (err) {
|
|
1608
1819
|
if (isRedirect(err)) {
|
|
1609
|
-
if (!preload) navigate(err);
|
|
1820
|
+
if (!preload) this.navigate(err);
|
|
1610
1821
|
return matches;
|
|
1611
1822
|
}
|
|
1612
1823
|
throw err;
|
|
@@ -1616,11 +1827,11 @@ function RouterProvider({
|
|
|
1616
1827
|
validResolvedMatches.forEach((match, index) => {
|
|
1617
1828
|
matchPromises.push((async () => {
|
|
1618
1829
|
const parentMatchPromise = matchPromises[index - 1];
|
|
1619
|
-
const route = looseRoutesById[match.routeId];
|
|
1830
|
+
const route = this.looseRoutesById[match.routeId];
|
|
1620
1831
|
const handleIfRedirect = err => {
|
|
1621
1832
|
if (isRedirect(err)) {
|
|
1622
1833
|
if (!preload) {
|
|
1623
|
-
navigate(err);
|
|
1834
|
+
this.navigate(err);
|
|
1624
1835
|
}
|
|
1625
1836
|
return true;
|
|
1626
1837
|
}
|
|
@@ -1633,9 +1844,8 @@ function RouterProvider({
|
|
|
1633
1844
|
invalid: false
|
|
1634
1845
|
};
|
|
1635
1846
|
if (match.isFetching) {
|
|
1636
|
-
loadPromise = getRouteMatch(state, match.id)?.loadPromise;
|
|
1847
|
+
loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
|
|
1637
1848
|
} else {
|
|
1638
|
-
const cause = state.matches.find(d => d.id === match.id) ? 'stay' : 'enter';
|
|
1639
1849
|
const loaderContext = {
|
|
1640
1850
|
params: match.params,
|
|
1641
1851
|
search: match.search,
|
|
@@ -1643,20 +1853,20 @@ function RouterProvider({
|
|
|
1643
1853
|
parentMatchPromise,
|
|
1644
1854
|
abortController: match.abortController,
|
|
1645
1855
|
context: match.context,
|
|
1646
|
-
location: state.location,
|
|
1647
|
-
navigate: opts => navigate({
|
|
1856
|
+
location: this.state.location,
|
|
1857
|
+
navigate: opts => this.navigate({
|
|
1648
1858
|
...opts,
|
|
1649
1859
|
from: match.pathname
|
|
1650
1860
|
}),
|
|
1651
|
-
cause
|
|
1861
|
+
cause: match.cause
|
|
1652
1862
|
};
|
|
1653
1863
|
|
|
1654
1864
|
// Default to reloading the route all the time
|
|
1655
1865
|
let shouldReload = true;
|
|
1656
1866
|
let shouldReloadDeps = typeof route.options.shouldReload === 'function' ? route.options.shouldReload?.(loaderContext) : !!(route.options.shouldReload ?? true);
|
|
1657
|
-
if (cause === 'enter') {
|
|
1867
|
+
if (match.cause === 'enter') {
|
|
1658
1868
|
match.shouldReloadDeps = shouldReloadDeps;
|
|
1659
|
-
} else if (cause === 'stay') {
|
|
1869
|
+
} else if (match.cause === 'stay') {
|
|
1660
1870
|
if (typeof shouldReloadDeps === 'object') {
|
|
1661
1871
|
// compare the deps to see if they've changed
|
|
1662
1872
|
shouldReload = !deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
@@ -1692,7 +1902,7 @@ function RouterProvider({
|
|
|
1692
1902
|
loadPromise
|
|
1693
1903
|
};
|
|
1694
1904
|
if (!preload) {
|
|
1695
|
-
setState(s => ({
|
|
1905
|
+
this.setState(s => ({
|
|
1696
1906
|
...s,
|
|
1697
1907
|
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1698
1908
|
}));
|
|
@@ -1727,7 +1937,7 @@ function RouterProvider({
|
|
|
1727
1937
|
};
|
|
1728
1938
|
}
|
|
1729
1939
|
if (!preload) {
|
|
1730
|
-
setState(s => ({
|
|
1940
|
+
this.setState(s => ({
|
|
1731
1941
|
...s,
|
|
1732
1942
|
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1733
1943
|
}));
|
|
@@ -1736,17 +1946,17 @@ function RouterProvider({
|
|
|
1736
1946
|
});
|
|
1737
1947
|
await Promise.all(matchPromises);
|
|
1738
1948
|
return matches;
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1949
|
+
};
|
|
1950
|
+
load = async () => {
|
|
1741
1951
|
const promise = new Promise(async (resolve, reject) => {
|
|
1742
|
-
const next =
|
|
1743
|
-
const prevLocation = state.resolvedLocation;
|
|
1952
|
+
const next = this.latestLocation;
|
|
1953
|
+
const prevLocation = this.state.resolvedLocation;
|
|
1744
1954
|
const pathDidChange = prevLocation.href !== next.href;
|
|
1745
1955
|
let latestPromise;
|
|
1746
1956
|
|
|
1747
1957
|
// Cancel any pending matches
|
|
1748
|
-
cancelMatches(
|
|
1749
|
-
|
|
1958
|
+
this.cancelMatches();
|
|
1959
|
+
this.emit({
|
|
1750
1960
|
type: 'onBeforeLoad',
|
|
1751
1961
|
fromLocation: prevLocation,
|
|
1752
1962
|
toLocation: next,
|
|
@@ -1754,14 +1964,14 @@ function RouterProvider({
|
|
|
1754
1964
|
});
|
|
1755
1965
|
|
|
1756
1966
|
// Match the routes
|
|
1757
|
-
let matches = matchRoutes(next.pathname, next.search, {
|
|
1967
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
1758
1968
|
debug: true
|
|
1759
1969
|
});
|
|
1760
|
-
|
|
1761
|
-
const previousMatches = state.matches;
|
|
1970
|
+
this.pendingMatches = matches;
|
|
1971
|
+
const previousMatches = this.state.matches;
|
|
1762
1972
|
|
|
1763
1973
|
// Ingest the new matches
|
|
1764
|
-
setState(s => ({
|
|
1974
|
+
this.setState(s => ({
|
|
1765
1975
|
...s,
|
|
1766
1976
|
status: 'pending',
|
|
1767
1977
|
location: next,
|
|
@@ -1770,9 +1980,9 @@ function RouterProvider({
|
|
|
1770
1980
|
try {
|
|
1771
1981
|
try {
|
|
1772
1982
|
// Load the matches
|
|
1773
|
-
await loadMatches({
|
|
1983
|
+
await this.loadMatches({
|
|
1774
1984
|
matches,
|
|
1775
|
-
checkLatest: () => checkLatest(promise)
|
|
1985
|
+
checkLatest: () => this.checkLatest(promise)
|
|
1776
1986
|
});
|
|
1777
1987
|
} catch (err) {
|
|
1778
1988
|
// swallow this error, since we'll display the
|
|
@@ -1780,12 +1990,12 @@ function RouterProvider({
|
|
|
1780
1990
|
}
|
|
1781
1991
|
|
|
1782
1992
|
// Only apply the latest transition
|
|
1783
|
-
if (latestPromise = checkLatest(promise)) {
|
|
1993
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
1784
1994
|
return latestPromise;
|
|
1785
1995
|
}
|
|
1786
|
-
const exitingMatchIds = previousMatches.filter(id => !
|
|
1787
|
-
const enteringMatchIds =
|
|
1788
|
-
const stayingMatchIds = previousMatches.filter(id =>
|
|
1996
|
+
const exitingMatchIds = previousMatches.filter(id => !this.pendingMatches.includes(id));
|
|
1997
|
+
const enteringMatchIds = this.pendingMatches.filter(id => !previousMatches.includes(id));
|
|
1998
|
+
const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id))
|
|
1789
1999
|
|
|
1790
2000
|
// setState((s) => ({
|
|
1791
2001
|
// ...s,
|
|
@@ -1797,10 +2007,10 @@ function RouterProvider({
|
|
|
1797
2007
|
;
|
|
1798
2008
|
[[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matches, hook]) => {
|
|
1799
2009
|
matches.forEach(match => {
|
|
1800
|
-
looseRoutesById[match.routeId].options[hook]?.(match);
|
|
2010
|
+
this.looseRoutesById[match.routeId].options[hook]?.(match);
|
|
1801
2011
|
});
|
|
1802
2012
|
});
|
|
1803
|
-
|
|
2013
|
+
this.emit({
|
|
1804
2014
|
type: 'onLoad',
|
|
1805
2015
|
fromLocation: prevLocation,
|
|
1806
2016
|
toLocation: next,
|
|
@@ -1809,28 +2019,28 @@ function RouterProvider({
|
|
|
1809
2019
|
resolve();
|
|
1810
2020
|
} catch (err) {
|
|
1811
2021
|
// Only apply the latest transition
|
|
1812
|
-
if (latestPromise = checkLatest(promise)) {
|
|
2022
|
+
if (latestPromise = this.checkLatest(promise)) {
|
|
1813
2023
|
return latestPromise;
|
|
1814
2024
|
}
|
|
1815
2025
|
reject(err);
|
|
1816
2026
|
}
|
|
1817
2027
|
});
|
|
1818
|
-
|
|
1819
|
-
return
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
let next = buildLocation(navigateOpts);
|
|
1823
|
-
let matches = matchRoutes(next.pathname, next.search, {
|
|
2028
|
+
this.latestLoadPromise = promise;
|
|
2029
|
+
return this.latestLoadPromise;
|
|
2030
|
+
};
|
|
2031
|
+
preloadRoute = async (navigateOpts = this.state.location) => {
|
|
2032
|
+
let next = this.buildLocation(navigateOpts);
|
|
2033
|
+
let matches = this.matchRoutes(next.pathname, next.search, {
|
|
1824
2034
|
throwOnError: true
|
|
1825
2035
|
});
|
|
1826
|
-
await loadMatches({
|
|
2036
|
+
await this.loadMatches({
|
|
1827
2037
|
matches,
|
|
1828
2038
|
preload: true,
|
|
1829
2039
|
checkLatest: () => undefined
|
|
1830
2040
|
});
|
|
1831
2041
|
return [last(matches), matches];
|
|
1832
|
-
}
|
|
1833
|
-
|
|
2042
|
+
};
|
|
2043
|
+
buildLink = dest => {
|
|
1834
2044
|
// If this link simply reloads the current route,
|
|
1835
2045
|
// make sure it has a new key so it will trigger a data refresh
|
|
1836
2046
|
|
|
@@ -1856,18 +2066,18 @@ function RouterProvider({
|
|
|
1856
2066
|
};
|
|
1857
2067
|
} catch (e) {}
|
|
1858
2068
|
const nextOpts = dest;
|
|
1859
|
-
const next = buildLocation(nextOpts);
|
|
1860
|
-
const preload = userPreload ?? options.defaultPreload;
|
|
1861
|
-
const preloadDelay = userPreloadDelay ?? options.defaultPreloadDelay ?? 0;
|
|
2069
|
+
const next = this.buildLocation(nextOpts);
|
|
2070
|
+
const preload = userPreload ?? this.options.defaultPreload;
|
|
2071
|
+
const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
|
|
1862
2072
|
|
|
1863
2073
|
// Compare path/hash for matches
|
|
1864
|
-
const currentPathSplit =
|
|
2074
|
+
const currentPathSplit = this.latestLocation.pathname.split('/');
|
|
1865
2075
|
const nextPathSplit = next.pathname.split('/');
|
|
1866
2076
|
const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
|
|
1867
|
-
// Combine the matches based on user options
|
|
1868
|
-
const pathTest = activeOptions?.exact ?
|
|
1869
|
-
const hashTest = activeOptions?.includeHash ?
|
|
1870
|
-
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(
|
|
2077
|
+
// Combine the matches based on user this.options
|
|
2078
|
+
const pathTest = activeOptions?.exact ? this.latestLocation.pathname === next.pathname : pathIsFuzzyEqual;
|
|
2079
|
+
const hashTest = activeOptions?.includeHash ? this.latestLocation.hash === next.hash : true;
|
|
2080
|
+
const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(this.latestLocation.search, next.search, true) : true;
|
|
1871
2081
|
|
|
1872
2082
|
// The final "active" test
|
|
1873
2083
|
const isActive = pathTest && hashTest && searchTest;
|
|
@@ -1878,7 +2088,7 @@ function RouterProvider({
|
|
|
1878
2088
|
e.preventDefault();
|
|
1879
2089
|
|
|
1880
2090
|
// All is well? Navigate!
|
|
1881
|
-
commitLocation({
|
|
2091
|
+
this.commitLocation({
|
|
1882
2092
|
...next,
|
|
1883
2093
|
replace,
|
|
1884
2094
|
resetScroll,
|
|
@@ -1890,384 +2100,184 @@ function RouterProvider({
|
|
|
1890
2100
|
// The click handler
|
|
1891
2101
|
const handleFocus = e => {
|
|
1892
2102
|
if (preload) {
|
|
1893
|
-
preloadRoute(nextOpts).catch(err => {
|
|
2103
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
1894
2104
|
console.warn(err);
|
|
1895
2105
|
console.warn(preloadWarning);
|
|
1896
2106
|
});
|
|
1897
2107
|
}
|
|
1898
2108
|
};
|
|
1899
2109
|
const handleTouchStart = e => {
|
|
1900
|
-
preloadRoute(nextOpts).catch(err => {
|
|
2110
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
1901
2111
|
console.warn(err);
|
|
1902
2112
|
console.warn(preloadWarning);
|
|
1903
2113
|
});
|
|
1904
2114
|
};
|
|
1905
|
-
const handleEnter = e => {
|
|
1906
|
-
const target = e.target || {};
|
|
1907
|
-
if (preload) {
|
|
1908
|
-
if (target.preloadTimeout) {
|
|
1909
|
-
return;
|
|
1910
|
-
}
|
|
1911
|
-
target.preloadTimeout = setTimeout(() => {
|
|
1912
|
-
target.preloadTimeout = null;
|
|
1913
|
-
preloadRoute(nextOpts).catch(err => {
|
|
1914
|
-
console.warn(err);
|
|
1915
|
-
console.warn(preloadWarning);
|
|
1916
|
-
});
|
|
1917
|
-
}, preloadDelay);
|
|
1918
|
-
}
|
|
1919
|
-
};
|
|
1920
|
-
const handleLeave = e => {
|
|
1921
|
-
const target = e.target || {};
|
|
1922
|
-
if (target.preloadTimeout) {
|
|
1923
|
-
clearTimeout(target.preloadTimeout);
|
|
1924
|
-
target.preloadTimeout = null;
|
|
1925
|
-
}
|
|
1926
|
-
};
|
|
1927
|
-
return {
|
|
1928
|
-
type: 'internal',
|
|
1929
|
-
next,
|
|
1930
|
-
handleFocus,
|
|
1931
|
-
handleClick,
|
|
1932
|
-
handleEnter,
|
|
1933
|
-
handleLeave,
|
|
1934
|
-
handleTouchStart,
|
|
1935
|
-
isActive,
|
|
1936
|
-
disabled
|
|
1937
|
-
};
|
|
1938
|
-
});
|
|
1939
|
-
React.useLayoutEffect(() => {
|
|
1940
|
-
const unsub = history.subscribe(() => {
|
|
1941
|
-
latestLocationRef.current = parseLocation(latestLocationRef.current);
|
|
1942
|
-
if (state.location !== latestLocationRef.current) {
|
|
1943
|
-
startReactTransition(() => {
|
|
1944
|
-
try {
|
|
1945
|
-
load();
|
|
1946
|
-
} catch (err) {
|
|
1947
|
-
console.error(err);
|
|
1948
|
-
}
|
|
1949
|
-
});
|
|
1950
|
-
}
|
|
1951
|
-
});
|
|
1952
|
-
const nextLocation = buildLocation({
|
|
1953
|
-
search: true,
|
|
1954
|
-
params: true,
|
|
1955
|
-
hash: true,
|
|
1956
|
-
state: true
|
|
1957
|
-
});
|
|
1958
|
-
if (state.location.href !== nextLocation.href) {
|
|
1959
|
-
commitLocation({
|
|
1960
|
-
...nextLocation,
|
|
1961
|
-
replace: true
|
|
1962
|
-
});
|
|
1963
|
-
}
|
|
1964
|
-
return () => {
|
|
1965
|
-
unsub();
|
|
1966
|
-
};
|
|
1967
|
-
}, [history]);
|
|
1968
|
-
const matchRoute = useStableCallback((location, opts) => {
|
|
1969
|
-
location = {
|
|
1970
|
-
...location,
|
|
1971
|
-
to: location.to ? resolvePathWithBase(location.from || '', location.to) : undefined
|
|
1972
|
-
};
|
|
1973
|
-
const next = buildLocation(location);
|
|
1974
|
-
if (opts?.pending && state.status !== 'pending') {
|
|
1975
|
-
return false;
|
|
1976
|
-
}
|
|
1977
|
-
const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
|
|
1978
|
-
|
|
1979
|
-
// const baseLocation = state.resolvedLocation
|
|
1980
|
-
|
|
1981
|
-
if (!baseLocation) {
|
|
1982
|
-
return false;
|
|
1983
|
-
}
|
|
1984
|
-
const match = matchPathname(basepath, baseLocation.pathname, {
|
|
1985
|
-
...opts,
|
|
1986
|
-
to: next.pathname
|
|
1987
|
-
});
|
|
1988
|
-
if (!match) {
|
|
1989
|
-
return false;
|
|
1990
|
-
}
|
|
1991
|
-
if (match && (opts?.includeSearch ?? true)) {
|
|
1992
|
-
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
1993
|
-
}
|
|
1994
|
-
return match;
|
|
1995
|
-
});
|
|
1996
|
-
const injectedHtmlRef = React.useRef([]);
|
|
1997
|
-
const injectHtml = useStableCallback(async html => {
|
|
1998
|
-
injectedHtmlRef.current.push(html);
|
|
1999
|
-
});
|
|
2000
|
-
const dehydrateData = useStableCallback((key, getData) => {
|
|
2001
|
-
if (typeof document === 'undefined') {
|
|
2002
|
-
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2003
|
-
injectHtml(async () => {
|
|
2004
|
-
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2005
|
-
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2006
|
-
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2007
|
-
;(() => {
|
|
2008
|
-
var el = document.getElementById('${id}')
|
|
2009
|
-
el.parentElement.removeChild(el)
|
|
2010
|
-
})()
|
|
2011
|
-
</script>`;
|
|
2012
|
-
});
|
|
2013
|
-
return () => hydrateData(key);
|
|
2014
|
-
}
|
|
2015
|
-
return () => undefined;
|
|
2016
|
-
});
|
|
2017
|
-
const hydrateData = useStableCallback(key => {
|
|
2018
|
-
if (typeof document !== 'undefined') {
|
|
2019
|
-
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2020
|
-
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
2021
|
-
}
|
|
2022
|
-
return undefined;
|
|
2023
|
-
});
|
|
2024
|
-
React.useLayoutEffect(() => {
|
|
2025
|
-
startReactTransition(() => {
|
|
2026
|
-
try {
|
|
2027
|
-
load();
|
|
2028
|
-
} catch (err) {
|
|
2029
|
-
console.error(err);
|
|
2030
|
-
}
|
|
2031
|
-
});
|
|
2032
|
-
}, []);
|
|
2033
|
-
const routerContextValue = {
|
|
2034
|
-
routeTree: router.routeTree,
|
|
2035
|
-
navigate,
|
|
2036
|
-
buildLink,
|
|
2037
|
-
state,
|
|
2038
|
-
matchRoute,
|
|
2039
|
-
routesById,
|
|
2040
|
-
options,
|
|
2041
|
-
history,
|
|
2042
|
-
load,
|
|
2043
|
-
buildLocation,
|
|
2044
|
-
subscribe: router.subscribe,
|
|
2045
|
-
resetNextScrollRef,
|
|
2046
|
-
injectedHtmlRef,
|
|
2047
|
-
injectHtml,
|
|
2048
|
-
dehydrateData,
|
|
2049
|
-
hydrateData
|
|
2050
|
-
};
|
|
2051
|
-
return /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
2052
|
-
value: routerContextValue
|
|
2053
|
-
}, /*#__PURE__*/React.createElement(Matches, null));
|
|
2054
|
-
}
|
|
2055
|
-
function getRouteMatch(state, id) {
|
|
2056
|
-
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
2057
|
-
}
|
|
2058
|
-
function useRouterState(opts) {
|
|
2059
|
-
const {
|
|
2060
|
-
state
|
|
2061
|
-
} = useRouter();
|
|
2062
|
-
// return useStore(router.__store, opts?.select as any)
|
|
2063
|
-
return opts?.select ? opts.select(state) : state;
|
|
2064
|
-
}
|
|
2065
|
-
function useRouter() {
|
|
2066
|
-
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
2067
|
-
const value = React.useContext(resolvedContext);
|
|
2068
|
-
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
2069
|
-
return value;
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
|
-
function defer(_promise) {
|
|
2073
|
-
const promise = _promise;
|
|
2074
|
-
if (!promise.__deferredState) {
|
|
2075
|
-
promise.__deferredState = {
|
|
2076
|
-
uid: Math.random().toString(36).slice(2),
|
|
2077
|
-
status: 'pending'
|
|
2078
|
-
};
|
|
2079
|
-
const state = promise.__deferredState;
|
|
2080
|
-
promise.then(data => {
|
|
2081
|
-
state.status = 'success';
|
|
2082
|
-
state.data = data;
|
|
2083
|
-
}).catch(error => {
|
|
2084
|
-
state.status = 'error';
|
|
2085
|
-
state.error = error;
|
|
2086
|
-
});
|
|
2087
|
-
}
|
|
2088
|
-
return promise;
|
|
2089
|
-
}
|
|
2090
|
-
function isDehydratedDeferred(obj) {
|
|
2091
|
-
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
2092
|
-
}
|
|
2093
|
-
|
|
2094
|
-
function useAwaited({
|
|
2095
|
-
promise
|
|
2096
|
-
}) {
|
|
2097
|
-
const router = useRouter();
|
|
2098
|
-
let state = promise.__deferredState;
|
|
2099
|
-
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
2100
|
-
if (isDehydratedDeferred(promise)) {
|
|
2101
|
-
state = router.hydrateData(key);
|
|
2102
|
-
promise = Promise.resolve(state.data);
|
|
2103
|
-
promise.__deferredState = state;
|
|
2104
|
-
}
|
|
2105
|
-
if (state.status === 'pending') {
|
|
2106
|
-
throw promise;
|
|
2107
|
-
}
|
|
2108
|
-
if (state.status === 'error') {
|
|
2109
|
-
throw state.error;
|
|
2110
|
-
}
|
|
2111
|
-
router.dehydrateData(key, state);
|
|
2112
|
-
return [state.data];
|
|
2113
|
-
}
|
|
2114
|
-
function Await(props) {
|
|
2115
|
-
const awaited = useAwaited(props);
|
|
2116
|
-
return props.children(...awaited);
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
class FileRoute {
|
|
2120
|
-
constructor(path) {
|
|
2121
|
-
this.path = path;
|
|
2122
|
-
}
|
|
2123
|
-
createRoute = options => {
|
|
2124
|
-
const route = new Route(options);
|
|
2125
|
-
route.isRoot = false;
|
|
2126
|
-
return route;
|
|
2127
|
-
};
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
function lazyRouteComponent(importer, exportName) {
|
|
2131
|
-
let loadPromise;
|
|
2132
|
-
const load = () => {
|
|
2133
|
-
if (!loadPromise) {
|
|
2134
|
-
loadPromise = importer();
|
|
2135
|
-
}
|
|
2136
|
-
return loadPromise;
|
|
2137
|
-
};
|
|
2138
|
-
const lazyComp = /*#__PURE__*/React.lazy(async () => {
|
|
2139
|
-
const moduleExports = await load();
|
|
2140
|
-
const comp = moduleExports[exportName ?? 'default'];
|
|
2141
|
-
return {
|
|
2142
|
-
default: comp
|
|
2143
|
-
};
|
|
2144
|
-
});
|
|
2145
|
-
lazyComp.preload = load;
|
|
2146
|
-
return lazyComp;
|
|
2147
|
-
}
|
|
2148
|
-
|
|
2149
|
-
function _extends() {
|
|
2150
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
2151
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
2152
|
-
var source = arguments[i];
|
|
2153
|
-
for (var key in source) {
|
|
2154
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2155
|
-
target[key] = source[key];
|
|
2115
|
+
const handleEnter = e => {
|
|
2116
|
+
const target = e.target || {};
|
|
2117
|
+
if (preload) {
|
|
2118
|
+
if (target.preloadTimeout) {
|
|
2119
|
+
return;
|
|
2156
2120
|
}
|
|
2121
|
+
target.preloadTimeout = setTimeout(() => {
|
|
2122
|
+
target.preloadTimeout = null;
|
|
2123
|
+
this.preloadRoute(nextOpts).catch(err => {
|
|
2124
|
+
console.warn(err);
|
|
2125
|
+
console.warn(preloadWarning);
|
|
2126
|
+
});
|
|
2127
|
+
}, preloadDelay);
|
|
2157
2128
|
}
|
|
2158
|
-
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
buildLink
|
|
2167
|
-
} = useRouter();
|
|
2168
|
-
const match = useMatch({
|
|
2169
|
-
strict: false
|
|
2170
|
-
});
|
|
2171
|
-
const {
|
|
2172
|
-
// custom props
|
|
2173
|
-
type,
|
|
2174
|
-
children,
|
|
2175
|
-
target,
|
|
2176
|
-
activeProps = () => ({
|
|
2177
|
-
className: 'active'
|
|
2178
|
-
}),
|
|
2179
|
-
inactiveProps = () => ({}),
|
|
2180
|
-
activeOptions,
|
|
2181
|
-
disabled,
|
|
2182
|
-
hash,
|
|
2183
|
-
search,
|
|
2184
|
-
params,
|
|
2185
|
-
to,
|
|
2186
|
-
state,
|
|
2187
|
-
mask,
|
|
2188
|
-
preload,
|
|
2189
|
-
preloadDelay,
|
|
2190
|
-
replace,
|
|
2191
|
-
startTransition,
|
|
2192
|
-
resetScroll,
|
|
2193
|
-
// element props
|
|
2194
|
-
style,
|
|
2195
|
-
className,
|
|
2196
|
-
onClick,
|
|
2197
|
-
onFocus,
|
|
2198
|
-
onMouseEnter,
|
|
2199
|
-
onMouseLeave,
|
|
2200
|
-
onTouchStart,
|
|
2201
|
-
...rest
|
|
2202
|
-
} = options;
|
|
2203
|
-
const linkInfo = buildLink({
|
|
2204
|
-
from: options.to ? match.pathname : undefined,
|
|
2205
|
-
...options
|
|
2206
|
-
});
|
|
2207
|
-
if (linkInfo.type === 'external') {
|
|
2208
|
-
const {
|
|
2209
|
-
href
|
|
2210
|
-
} = linkInfo;
|
|
2129
|
+
};
|
|
2130
|
+
const handleLeave = e => {
|
|
2131
|
+
const target = e.target || {};
|
|
2132
|
+
if (target.preloadTimeout) {
|
|
2133
|
+
clearTimeout(target.preloadTimeout);
|
|
2134
|
+
target.preloadTimeout = null;
|
|
2135
|
+
}
|
|
2136
|
+
};
|
|
2211
2137
|
return {
|
|
2212
|
-
|
|
2138
|
+
type: 'internal',
|
|
2139
|
+
next,
|
|
2140
|
+
handleFocus,
|
|
2141
|
+
handleClick,
|
|
2142
|
+
handleEnter,
|
|
2143
|
+
handleLeave,
|
|
2144
|
+
handleTouchStart,
|
|
2145
|
+
isActive,
|
|
2146
|
+
disabled
|
|
2213
2147
|
};
|
|
2214
|
-
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2148
|
+
};
|
|
2149
|
+
matchRoute = (location, opts) => {
|
|
2150
|
+
location = {
|
|
2151
|
+
...location,
|
|
2152
|
+
to: location.to ? this.resolvePathWithBase(location.from || '', location.to) : undefined
|
|
2153
|
+
};
|
|
2154
|
+
const next = this.buildLocation(location);
|
|
2155
|
+
if (opts?.pending && this.state.status !== 'pending') {
|
|
2156
|
+
return false;
|
|
2157
|
+
}
|
|
2158
|
+
const baseLocation = opts?.pending ? this.latestLocation : this.state.resolvedLocation;
|
|
2159
|
+
|
|
2160
|
+
// const baseLocation = state.resolvedLocation
|
|
2161
|
+
|
|
2162
|
+
if (!baseLocation) {
|
|
2163
|
+
return false;
|
|
2164
|
+
}
|
|
2165
|
+
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
2166
|
+
...opts,
|
|
2167
|
+
to: next.pathname
|
|
2229
2168
|
});
|
|
2169
|
+
if (!match) {
|
|
2170
|
+
return false;
|
|
2171
|
+
}
|
|
2172
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
2173
|
+
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
2174
|
+
}
|
|
2175
|
+
return match;
|
|
2176
|
+
};
|
|
2177
|
+
injectHtml = async html => {
|
|
2178
|
+
this.injectedHtml.push(html);
|
|
2179
|
+
};
|
|
2180
|
+
dehydrateData = (key, getData) => {
|
|
2181
|
+
if (typeof document === 'undefined') {
|
|
2182
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2183
|
+
this.injectHtml(async () => {
|
|
2184
|
+
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2185
|
+
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2186
|
+
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2187
|
+
;(() => {
|
|
2188
|
+
var el = document.getElementById('${id}')
|
|
2189
|
+
el.parentElement.removeChild(el)
|
|
2190
|
+
})()
|
|
2191
|
+
</script>`;
|
|
2192
|
+
});
|
|
2193
|
+
return () => this.hydrateData(key);
|
|
2194
|
+
}
|
|
2195
|
+
return () => undefined;
|
|
2196
|
+
};
|
|
2197
|
+
hydrateData = key => {
|
|
2198
|
+
if (typeof document !== 'undefined') {
|
|
2199
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2200
|
+
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
2201
|
+
}
|
|
2202
|
+
return undefined;
|
|
2230
2203
|
};
|
|
2231
2204
|
|
|
2232
|
-
//
|
|
2233
|
-
|
|
2205
|
+
// dehydrate = (): DehydratedRouter => {
|
|
2206
|
+
// return {
|
|
2207
|
+
// state: {
|
|
2208
|
+
// dehydratedMatches: this.state.matches.map((d) =>
|
|
2209
|
+
// pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
|
|
2210
|
+
// ),
|
|
2211
|
+
// },
|
|
2212
|
+
// }
|
|
2213
|
+
// }
|
|
2234
2214
|
|
|
2235
|
-
//
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2215
|
+
// hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
|
|
2216
|
+
// let _ctx = __do_not_use_server_ctx
|
|
2217
|
+
// // Client hydrates from window
|
|
2218
|
+
// if (typeof document !== 'undefined') {
|
|
2219
|
+
// _ctx = window.__TSR_DEHYDRATED__
|
|
2220
|
+
// }
|
|
2221
|
+
|
|
2222
|
+
// invariant(
|
|
2223
|
+
// _ctx,
|
|
2224
|
+
// 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
|
|
2225
|
+
// )
|
|
2226
|
+
|
|
2227
|
+
// const ctx = _ctx
|
|
2228
|
+
// this.dehydratedData = ctx.payload as any
|
|
2229
|
+
// this.options.hydrate?.(ctx.payload as any)
|
|
2230
|
+
// const dehydratedState = ctx.router.state
|
|
2231
|
+
|
|
2232
|
+
// let matches = this.matchRoutes(
|
|
2233
|
+
// this.state.location.pathname,
|
|
2234
|
+
// this.state.location.search,
|
|
2235
|
+
// ).map((match) => {
|
|
2236
|
+
// const dehydratedMatch = dehydratedState.dehydratedMatches.find(
|
|
2237
|
+
// (d) => d.id === match.id,
|
|
2238
|
+
// )
|
|
2239
|
+
|
|
2240
|
+
// invariant(
|
|
2241
|
+
// dehydratedMatch,
|
|
2242
|
+
// `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
|
|
2243
|
+
// )
|
|
2244
|
+
|
|
2245
|
+
// if (dehydratedMatch) {
|
|
2246
|
+
// return {
|
|
2247
|
+
// ...match,
|
|
2248
|
+
// ...dehydratedMatch,
|
|
2249
|
+
// }
|
|
2250
|
+
// }
|
|
2251
|
+
// return match
|
|
2252
|
+
// })
|
|
2253
|
+
|
|
2254
|
+
// this.setState((s) => {
|
|
2255
|
+
// return {
|
|
2256
|
+
// ...s,
|
|
2257
|
+
// matches: dehydratedState.dehydratedMatches as any,
|
|
2258
|
+
// }
|
|
2259
|
+
// })
|
|
2260
|
+
// }
|
|
2261
|
+
|
|
2262
|
+
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
2263
|
+
// state.matches
|
|
2264
|
+
// .find((d) => d.id === matchId)
|
|
2265
|
+
// ?.__promisesByKey[key]?.resolve(value)
|
|
2266
|
+
// }
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
// A function that takes an import() argument which is a function and returns a new function that will
|
|
2270
|
+
// proxy arguments from the caller to the imported function, retaining all type
|
|
2271
|
+
// information along the way
|
|
2272
|
+
function lazyFn(fn, key) {
|
|
2273
|
+
return async (...args) => {
|
|
2274
|
+
const imported = await fn();
|
|
2275
|
+
return imported[key || 'default'](...args);
|
|
2259
2276
|
};
|
|
2260
2277
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
ref: ref
|
|
2265
|
-
}, linkProps, {
|
|
2266
|
-
children: typeof props.children === 'function' ? props.children({
|
|
2267
|
-
isActive: linkProps['data-status'] === 'active'
|
|
2268
|
-
}) : props.children
|
|
2269
|
-
}));
|
|
2270
|
-
});
|
|
2278
|
+
function isCtrlEvent(e) {
|
|
2279
|
+
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
|
2280
|
+
}
|
|
2271
2281
|
|
|
2272
2282
|
const useLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
2273
2283
|
const windowKey = 'window';
|
|
@@ -2277,11 +2287,7 @@ let cache;
|
|
|
2277
2287
|
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
|
|
2278
2288
|
const defaultGetKey = location => location.state.key;
|
|
2279
2289
|
function useScrollRestoration(options) {
|
|
2280
|
-
const
|
|
2281
|
-
state,
|
|
2282
|
-
subscribe,
|
|
2283
|
-
resetNextScrollRef
|
|
2284
|
-
} = useRouter();
|
|
2290
|
+
const router = useRouter();
|
|
2285
2291
|
useLayoutEffect(() => {
|
|
2286
2292
|
const getKey = options?.getKey || defaultGetKey;
|
|
2287
2293
|
if (sessionsStorage) {
|
|
@@ -2337,7 +2343,7 @@ function useScrollRestoration(options) {
|
|
|
2337
2343
|
if (typeof document !== 'undefined') {
|
|
2338
2344
|
document.addEventListener('scroll', onScroll, true);
|
|
2339
2345
|
}
|
|
2340
|
-
const unsubOnBeforeLoad = subscribe('onBeforeLoad', event => {
|
|
2346
|
+
const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', event => {
|
|
2341
2347
|
if (event.pathChanged) {
|
|
2342
2348
|
const restoreKey = getKey(event.fromLocation);
|
|
2343
2349
|
for (const elementSelector in cache.state.next) {
|
|
@@ -2367,12 +2373,12 @@ function useScrollRestoration(options) {
|
|
|
2367
2373
|
}
|
|
2368
2374
|
}
|
|
2369
2375
|
});
|
|
2370
|
-
const unsubOnResolved = subscribe('onResolved', event => {
|
|
2376
|
+
const unsubOnResolved = router.subscribe('onResolved', event => {
|
|
2371
2377
|
if (event.pathChanged) {
|
|
2372
|
-
if (!
|
|
2378
|
+
if (!router.resetNextScroll) {
|
|
2373
2379
|
return;
|
|
2374
2380
|
}
|
|
2375
|
-
|
|
2381
|
+
router.resetNextScroll = true;
|
|
2376
2382
|
const getKey = options?.getKey || defaultGetKey;
|
|
2377
2383
|
const restoreKey = getKey(event.toLocation);
|
|
2378
2384
|
let windowRestored = false;
|