@tanstack/react-router 0.0.1-beta.284 → 0.0.1-beta.286

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.
@@ -771,6 +771,8 @@
771
771
  // // Using DeepMerge to merge TypeA and TypeB
772
772
  // type MergedType = Expand<AssignAll<[TypeA, TypeB, TypeC]>>
773
773
 
774
+ // from https://github.com/type-challenges/type-challenges/issues/737
775
+
774
776
  //
775
777
 
776
778
  const isServer = typeof document === 'undefined';
@@ -909,468 +911,110 @@
909
911
  .replace(/"/g, '\\"'); // Escape double quotes
910
912
  }
911
913
 
912
- const matchContext = /*#__PURE__*/React__namespace.createContext(undefined);
913
- function Matches() {
914
- const router = useRouter();
915
- const matchId = useRouterState({
916
- select: s => {
917
- return getRenderedMatches(s)[0]?.id;
918
- }
919
- });
920
- return /*#__PURE__*/React__namespace.createElement(matchContext.Provider, {
921
- value: matchId
922
- }, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
923
- getResetKey: () => router.state.resolvedLocation.state?.key,
924
- errorComponent: ErrorComponent,
925
- onCatch: () => {
926
- warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
927
- }
928
- }, matchId ? /*#__PURE__*/React__namespace.createElement(Match, {
929
- matchId: matchId
930
- }) : null));
914
+ function joinPaths(paths) {
915
+ return cleanPath(paths.filter(Boolean).join('/'));
931
916
  }
932
- function SafeFragment(props) {
933
- return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.children);
917
+ function cleanPath(path) {
918
+ // remove double slashes
919
+ return path.replace(/\/{2,}/g, '/');
934
920
  }
935
- function Match({
936
- matchId
937
- }) {
938
- const router = useRouter();
939
- const routeId = useRouterState({
940
- select: s => getRenderedMatches(s).find(d => d.id === matchId)?.routeId
941
- });
942
- invariant(routeId, `Could not find routeId for matchId "${matchId}". Please file an issue!`);
943
- const route = router.routesById[routeId];
944
- const PendingComponent = route.options.pendingComponent ?? router.options.defaultPendingComponent;
945
- const pendingElement = PendingComponent ? /*#__PURE__*/React__namespace.createElement(PendingComponent, null) : null;
946
- const routeErrorComponent = route.options.errorComponent ?? router.options.defaultErrorComponent ?? ErrorComponent;
947
- const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? PendingComponent ?? route.options.component?.preload ?? route.options.pendingComponent?.preload ?? route.options.errorComponent?.preload ? React__namespace.Suspense : SafeFragment;
948
- const ResolvedCatchBoundary = routeErrorComponent ? CatchBoundary : SafeFragment;
949
- return /*#__PURE__*/React__namespace.createElement(matchContext.Provider, {
950
- value: matchId
951
- }, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
952
- fallback: pendingElement
953
- }, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
954
- getResetKey: () => router.state.resolvedLocation.state?.key,
955
- errorComponent: routeErrorComponent,
956
- onCatch: () => {
957
- warning(false, `Error in route match: ${matchId}`);
958
- }
959
- }, /*#__PURE__*/React__namespace.createElement(MatchInner, {
960
- matchId: matchId,
961
- pendingElement: pendingElement
962
- }))));
921
+ function trimPathLeft(path) {
922
+ return path === '/' ? path : path.replace(/^\/{1,}/, '');
963
923
  }
964
- function MatchInner({
965
- matchId,
966
- pendingElement
967
- }) {
968
- const router = useRouter();
969
- const routeId = useRouterState({
970
- select: s => getRenderedMatches(s).find(d => d.id === matchId)?.routeId
971
- });
972
- const route = router.routesById[routeId];
973
- const match = useRouterState({
974
- select: s => pick(getRenderedMatches(s).find(d => d.id === matchId), ['status', 'error', 'showPending', 'loadPromise'])
975
- });
976
- if (match.status === 'error') {
977
- throw match.error;
978
- }
979
- if (match.status === 'pending') {
980
- if (match.showPending) {
981
- return pendingElement;
982
- }
983
- throw match.loadPromise;
984
- }
985
- if (match.status === 'success') {
986
- let Comp = route.options.component ?? router.options.defaultComponent;
987
- if (Comp) {
988
- return /*#__PURE__*/React__namespace.createElement(Comp, null);
989
- }
990
- return /*#__PURE__*/React__namespace.createElement(Outlet, null);
991
- }
992
- invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
924
+ function trimPathRight(path) {
925
+ return path === '/' ? path : path.replace(/\/{1,}$/, '');
993
926
  }
994
- const Outlet = /*#__PURE__*/React__namespace.memo(function Outlet() {
995
- const matchId = React__namespace.useContext(matchContext);
996
- const childMatchId = useRouterState({
997
- select: s => {
998
- const matches = getRenderedMatches(s);
999
- const index = matches.findIndex(d => d.id === matchId);
1000
- return matches[index + 1]?.id;
927
+ function trimPath(path) {
928
+ return trimPathRight(trimPathLeft(path));
929
+ }
930
+ function resolvePath(basepath, base, to) {
931
+ base = base.replace(new RegExp(`^${basepath}`), '/');
932
+ to = to.replace(new RegExp(`^${basepath}`), '/');
933
+ let baseSegments = parsePathname(base);
934
+ const toSegments = parsePathname(to);
935
+ toSegments.forEach((toSegment, index) => {
936
+ if (toSegment.value === '/') {
937
+ if (!index) {
938
+ // Leading slash
939
+ baseSegments = [toSegment];
940
+ } else if (index === toSegments.length - 1) {
941
+ // Trailing Slash
942
+ baseSegments.push(toSegment);
943
+ } else ;
944
+ } else if (toSegment.value === '..') {
945
+ // Extra trailing slash? pop it off
946
+ if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {
947
+ baseSegments.pop();
948
+ }
949
+ baseSegments.pop();
950
+ } else if (toSegment.value === '.') {
951
+ return;
952
+ } else {
953
+ baseSegments.push(toSegment);
1001
954
  }
1002
955
  });
1003
- if (!childMatchId) {
1004
- return null;
956
+ const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
957
+ return cleanPath(joined);
958
+ }
959
+ function parsePathname(pathname) {
960
+ if (!pathname) {
961
+ return [];
1005
962
  }
1006
- return /*#__PURE__*/React__namespace.createElement(Match, {
1007
- matchId: childMatchId
1008
- });
1009
- });
1010
- function useMatchRoute() {
1011
- useRouterState({
1012
- select: s => [s.location, s.resolvedLocation]
1013
- });
1014
- const {
1015
- matchRoute
1016
- } = useRouter();
1017
- return React__namespace.useCallback(opts => {
1018
- const {
1019
- pending,
1020
- caseSensitive,
1021
- ...rest
1022
- } = opts;
1023
- return matchRoute(rest, {
1024
- pending,
1025
- caseSensitive
963
+ pathname = cleanPath(pathname);
964
+ const segments = [];
965
+ if (pathname.slice(0, 1) === '/') {
966
+ pathname = pathname.substring(1);
967
+ segments.push({
968
+ type: 'pathname',
969
+ value: '/'
1026
970
  });
1027
- }, []);
1028
- }
1029
- function MatchRoute(props) {
1030
- const matchRoute = useMatchRoute();
1031
- const params = matchRoute(props);
1032
- if (typeof props.children === 'function') {
1033
- return props.children(params);
1034
971
  }
1035
- return !!params ? props.children : null;
1036
- }
1037
- function getRenderedMatches(state) {
1038
- return state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
1039
- }
1040
- function useMatch(opts) {
1041
- const router = useRouter();
1042
- const nearestMatchId = React__namespace.useContext(matchContext);
1043
- const nearestMatchRouteId = getRenderedMatches(router.state).find(d => d.id === nearestMatchId)?.routeId;
1044
- const matchRouteId = (() => {
1045
- const matches = getRenderedMatches(router.state);
1046
- const match = opts?.from ? matches.find(d => d.routeId === opts?.from) : matches.find(d => d.id === nearestMatchId);
1047
- return match.routeId;
1048
- })();
1049
- if (opts?.strict ?? true) {
1050
- invariant(nearestMatchRouteId == matchRouteId, `useMatch("${matchRouteId}") is being called in a component that is meant to render the '${nearestMatchRouteId}' route. Did you mean to 'useMatch("${matchRouteId}", { strict: false })' or 'useRoute("${matchRouteId}")' instead?`);
972
+ if (!pathname) {
973
+ return segments;
1051
974
  }
1052
- const matchSelection = useRouterState({
1053
- select: state => {
1054
- const match = getRenderedMatches(state).find(d => d.id === nearestMatchId);
1055
- invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
1056
- return opts?.select ? opts.select(match) : match;
1057
- }
1058
- });
1059
- return matchSelection;
1060
- }
1061
- function useMatches(opts) {
1062
- return useRouterState({
1063
- select: state => {
1064
- let matches = getRenderedMatches(state);
1065
- return opts?.select ? opts.select(matches) : matches;
975
+
976
+ // Remove empty segments and '.' segments
977
+ const split = pathname.split('/').filter(Boolean);
978
+ segments.push(...split.map(part => {
979
+ if (part === '$' || part === '*') {
980
+ return {
981
+ type: 'wildcard',
982
+ value: part
983
+ };
1066
984
  }
1067
- });
1068
- }
1069
- function useParentMatches(opts) {
1070
- const contextMatchId = React__namespace.useContext(matchContext);
1071
- return useMatches({
1072
- select: matches => {
1073
- matches = matches.slice(matches.findIndex(d => d.id === contextMatchId));
1074
- return opts?.select ? opts.select(matches) : matches;
985
+ if (part.charAt(0) === '$') {
986
+ return {
987
+ type: 'param',
988
+ value: part
989
+ };
1075
990
  }
1076
- });
991
+ return {
992
+ type: 'pathname',
993
+ value: part
994
+ };
995
+ }));
996
+ if (pathname.slice(-1) === '/') {
997
+ pathname = pathname.substring(1);
998
+ segments.push({
999
+ type: 'pathname',
1000
+ value: '/'
1001
+ });
1002
+ }
1003
+ return segments;
1077
1004
  }
1078
- function useLoaderDeps(opts) {
1079
- return useMatch({
1080
- ...opts,
1081
- select: s => {
1082
- return typeof opts.select === 'function' ? opts.select(s?.loaderDeps) : s?.loaderDeps;
1005
+ function interpolatePath(path, params, leaveWildcards = false) {
1006
+ const interpolatedPathSegments = parsePathname(path);
1007
+ return joinPaths(interpolatedPathSegments.map(segment => {
1008
+ if (segment.type === 'wildcard') {
1009
+ const value = params[segment.value];
1010
+ if (leaveWildcards) return `${segment.value}${value ?? ''}`;
1011
+ return value;
1083
1012
  }
1084
- });
1085
- }
1086
- function useLoaderData(opts) {
1087
- return useMatch({
1088
- ...opts,
1089
- select: s => {
1090
- return typeof opts.select === 'function' ? opts.select(s?.loaderData) : s?.loaderData;
1013
+ if (segment.type === 'param') {
1014
+ return params[segment.value.substring(1)] ?? 'undefined';
1091
1015
  }
1092
- });
1093
- }
1094
-
1095
- exports.routerContext = /*#__PURE__*/React__namespace.createContext(null);
1096
- if (typeof document !== 'undefined') {
1097
- if (window.__TSR_ROUTER_CONTEXT__) {
1098
- exports.routerContext = window.__TSR_ROUTER_CONTEXT__;
1099
- } else {
1100
- window.__TSR_ROUTER_CONTEXT__ = exports.routerContext;
1101
- }
1102
- }
1103
- function RouterProvider({
1104
- router,
1105
- ...rest
1106
- }) {
1107
- // Allow the router to update options on the router instance
1108
- router.update({
1109
- ...router.options,
1110
- ...rest,
1111
- context: {
1112
- ...router.options.context,
1113
- ...rest?.context
1114
- }
1115
- });
1116
- const matches = router.options.InnerWrap ? /*#__PURE__*/React__namespace.createElement(router.options.InnerWrap, null, /*#__PURE__*/React__namespace.createElement(Matches, null)) : /*#__PURE__*/React__namespace.createElement(Matches, null);
1117
- const provider = /*#__PURE__*/React__namespace.createElement(exports.routerContext.Provider, {
1118
- value: router
1119
- }, matches, /*#__PURE__*/React__namespace.createElement(Transitioner, null));
1120
- if (router.options.Wrap) {
1121
- return /*#__PURE__*/React__namespace.createElement(router.options.Wrap, null, provider);
1122
- }
1123
- return provider;
1124
- }
1125
- function Transitioner() {
1126
- const router = useRouter();
1127
- const routerState = useRouterState({
1128
- select: s => pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning'])
1129
- });
1130
- const [isTransitioning, startReactTransition] = React__namespace.useTransition();
1131
- router.startReactTransition = startReactTransition;
1132
- React__namespace.useEffect(() => {
1133
- if (isTransitioning) {
1134
- router.__store.setState(s => ({
1135
- ...s,
1136
- isTransitioning
1137
- }));
1138
- }
1139
- }, [isTransitioning]);
1140
- const tryLoad = () => {
1141
- const apply = cb => {
1142
- if (!routerState.isTransitioning) {
1143
- startReactTransition(() => cb());
1144
- } else {
1145
- cb();
1146
- }
1147
- };
1148
- apply(() => {
1149
- try {
1150
- router.load();
1151
- } catch (err) {
1152
- console.error(err);
1153
- }
1154
- });
1155
- };
1156
- useLayoutEffect$1(() => {
1157
- const unsub = router.history.subscribe(() => {
1158
- router.latestLocation = router.parseLocation(router.latestLocation);
1159
- if (routerState.location !== router.latestLocation) {
1160
- tryLoad();
1161
- }
1162
- });
1163
- const nextLocation = router.buildLocation({
1164
- search: true,
1165
- params: true,
1166
- hash: true,
1167
- state: true
1168
- });
1169
- if (routerState.location.href !== nextLocation.href) {
1170
- router.commitLocation({
1171
- ...nextLocation,
1172
- replace: true
1173
- });
1174
- }
1175
- return () => {
1176
- unsub();
1177
- };
1178
- }, [router.history]);
1179
- useLayoutEffect$1(() => {
1180
- if (routerState.isTransitioning && !isTransitioning && !routerState.isLoading && routerState.resolvedLocation !== routerState.location) {
1181
- router.emit({
1182
- type: 'onResolved',
1183
- fromLocation: routerState.resolvedLocation,
1184
- toLocation: routerState.location,
1185
- pathChanged: routerState.location.href !== routerState.resolvedLocation?.href
1186
- });
1187
- if (document.querySelector) {
1188
- if (routerState.location.hash !== '') {
1189
- const el = document.getElementById(routerState.location.hash);
1190
- if (el) {
1191
- el.scrollIntoView();
1192
- }
1193
- }
1194
- }
1195
- router.__store.setState(s => ({
1196
- ...s,
1197
- isTransitioning: false,
1198
- resolvedLocation: s.location
1199
- }));
1200
- }
1201
- }, [routerState.isTransitioning, isTransitioning, routerState.isLoading, routerState.resolvedLocation, routerState.location]);
1202
- useLayoutEffect$1(() => {
1203
- if (!window.__TSR_DEHYDRATED__) {
1204
- tryLoad();
1205
- }
1206
- }, []);
1207
- return null;
1208
- }
1209
- function getRouteMatch(state, id) {
1210
- return [...state.cachedMatches, ...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
1211
- }
1212
- function useRouterState(opts) {
1213
- const router = useRouter();
1214
- return useStore(router.__store, opts?.select);
1215
- }
1216
- function useRouter() {
1217
- const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || exports.routerContext : exports.routerContext;
1218
- const value = React__namespace.useContext(resolvedContext);
1219
- warning(value, 'useRouter must be used inside a <RouterProvider> component!');
1220
- return value;
1221
- }
1222
-
1223
- function defer(_promise) {
1224
- const promise = _promise;
1225
- if (!promise.__deferredState) {
1226
- promise.__deferredState = {
1227
- uid: Math.random().toString(36).slice(2),
1228
- status: 'pending'
1229
- };
1230
- const state = promise.__deferredState;
1231
- promise.then(data => {
1232
- state.status = 'success';
1233
- state.data = data;
1234
- }).catch(error => {
1235
- state.status = 'error';
1236
- state.error = error;
1237
- });
1238
- }
1239
- return promise;
1240
- }
1241
- function isDehydratedDeferred(obj) {
1242
- return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
1243
- }
1244
-
1245
- function useAwaited({
1246
- promise
1247
- }) {
1248
- const router = useRouter();
1249
- let state = promise.__deferredState;
1250
- const key = `__TSR__DEFERRED__${state.uid}`;
1251
- if (isDehydratedDeferred(promise)) {
1252
- state = router.hydrateData(key);
1253
- promise = Promise.resolve(state.data);
1254
- promise.__deferredState = state;
1255
- }
1256
- if (state.status === 'pending') {
1257
- throw new Promise(r => setTimeout(r, 1)).then(() => promise);
1258
- }
1259
- if (state.status === 'error') {
1260
- throw state.error;
1261
- }
1262
- router.dehydrateData(key, state);
1263
- return [state.data];
1264
- }
1265
- function Await(props) {
1266
- const awaited = useAwaited(props);
1267
- return props.children(...awaited);
1268
- }
1269
-
1270
- function joinPaths(paths) {
1271
- return cleanPath(paths.filter(Boolean).join('/'));
1272
- }
1273
- function cleanPath(path) {
1274
- // remove double slashes
1275
- return path.replace(/\/{2,}/g, '/');
1276
- }
1277
- function trimPathLeft(path) {
1278
- return path === '/' ? path : path.replace(/^\/{1,}/, '');
1279
- }
1280
- function trimPathRight(path) {
1281
- return path === '/' ? path : path.replace(/\/{1,}$/, '');
1282
- }
1283
- function trimPath(path) {
1284
- return trimPathRight(trimPathLeft(path));
1285
- }
1286
- function resolvePath(basepath, base, to) {
1287
- base = base.replace(new RegExp(`^${basepath}`), '/');
1288
- to = to.replace(new RegExp(`^${basepath}`), '/');
1289
- let baseSegments = parsePathname(base);
1290
- const toSegments = parsePathname(to);
1291
- toSegments.forEach((toSegment, index) => {
1292
- if (toSegment.value === '/') {
1293
- if (!index) {
1294
- // Leading slash
1295
- baseSegments = [toSegment];
1296
- } else if (index === toSegments.length - 1) {
1297
- // Trailing Slash
1298
- baseSegments.push(toSegment);
1299
- } else ;
1300
- } else if (toSegment.value === '..') {
1301
- // Extra trailing slash? pop it off
1302
- if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {
1303
- baseSegments.pop();
1304
- }
1305
- baseSegments.pop();
1306
- } else if (toSegment.value === '.') {
1307
- return;
1308
- } else {
1309
- baseSegments.push(toSegment);
1310
- }
1311
- });
1312
- const joined = joinPaths([basepath, ...baseSegments.map(d => d.value)]);
1313
- return cleanPath(joined);
1314
- }
1315
- function parsePathname(pathname) {
1316
- if (!pathname) {
1317
- return [];
1318
- }
1319
- pathname = cleanPath(pathname);
1320
- const segments = [];
1321
- if (pathname.slice(0, 1) === '/') {
1322
- pathname = pathname.substring(1);
1323
- segments.push({
1324
- type: 'pathname',
1325
- value: '/'
1326
- });
1327
- }
1328
- if (!pathname) {
1329
- return segments;
1330
- }
1331
-
1332
- // Remove empty segments and '.' segments
1333
- const split = pathname.split('/').filter(Boolean);
1334
- segments.push(...split.map(part => {
1335
- if (part === '$' || part === '*') {
1336
- return {
1337
- type: 'wildcard',
1338
- value: part
1339
- };
1340
- }
1341
- if (part.charAt(0) === '$') {
1342
- return {
1343
- type: 'param',
1344
- value: part
1345
- };
1346
- }
1347
- return {
1348
- type: 'pathname',
1349
- value: part
1350
- };
1351
- }));
1352
- if (pathname.slice(-1) === '/') {
1353
- pathname = pathname.substring(1);
1354
- segments.push({
1355
- type: 'pathname',
1356
- value: '/'
1357
- });
1358
- }
1359
- return segments;
1360
- }
1361
- function interpolatePath(path, params, leaveWildcards = false) {
1362
- const interpolatedPathSegments = parsePathname(path);
1363
- return joinPaths(interpolatedPathSegments.map(segment => {
1364
- if (segment.type === 'wildcard') {
1365
- const value = params[segment.value];
1366
- if (leaveWildcards) return `${segment.value}${value ?? ''}`;
1367
- return value;
1368
- }
1369
- if (segment.type === 'param') {
1370
- return params[segment.value.substring(1)] ?? 'undefined';
1371
- }
1372
- return segment.value;
1373
- }));
1016
+ return segment.value;
1017
+ }));
1374
1018
  }
1375
1019
  function matchPathname(basepath, currentPathname, matchLocation) {
1376
1020
  const pathParams = matchByPath(basepath, currentPathname, matchLocation);
@@ -1544,98 +1188,463 @@
1544
1188
  } else {
1545
1189
  invariant(this.parentRoute, `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`);
1546
1190
  }
1547
- let path = isRoot ? rootRouteId : options.path;
1548
-
1549
- // If the path is anything other than an index path, trim it up
1550
- if (path && path !== '/') {
1551
- path = trimPath(path);
1191
+ let path = isRoot ? rootRouteId : options.path;
1192
+
1193
+ // If the path is anything other than an index path, trim it up
1194
+ if (path && path !== '/') {
1195
+ path = trimPath(path);
1196
+ }
1197
+ const customId = options?.id || path;
1198
+
1199
+ // Strip the parentId prefix from the first level of children
1200
+ let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
1201
+ if (path === rootRouteId) {
1202
+ path = '/';
1203
+ }
1204
+ if (id !== rootRouteId) {
1205
+ id = joinPaths(['/', id]);
1206
+ }
1207
+ const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
1208
+ this.path = path;
1209
+ this.id = id;
1210
+ // this.customId = customId as TCustomId
1211
+ this.fullPath = fullPath;
1212
+ this.to = fullPath;
1213
+ };
1214
+ addChildren = children => {
1215
+ this.children = children;
1216
+ return this;
1217
+ };
1218
+ update = options => {
1219
+ Object.assign(this.options, options);
1220
+ return this;
1221
+ };
1222
+ useMatch = opts => {
1223
+ return useMatch({
1224
+ ...opts,
1225
+ from: this.id
1226
+ });
1227
+ };
1228
+ useRouteContext = opts => {
1229
+ return useMatch({
1230
+ ...opts,
1231
+ from: this.id,
1232
+ select: d => opts?.select ? opts.select(d.context) : d.context
1233
+ });
1234
+ };
1235
+ useSearch = opts => {
1236
+ return useSearch({
1237
+ ...opts,
1238
+ from: this.id
1239
+ });
1240
+ };
1241
+ useParams = opts => {
1242
+ return useParams({
1243
+ ...opts,
1244
+ from: this.id
1245
+ });
1246
+ };
1247
+ useLoaderDeps = opts => {
1248
+ return useLoaderDeps({
1249
+ ...opts,
1250
+ from: this.id
1251
+ });
1252
+ };
1253
+ useLoaderData = opts => {
1254
+ return useLoaderData({
1255
+ ...opts,
1256
+ from: this.id
1257
+ });
1258
+ };
1259
+ }
1260
+ function rootRouteWithContext() {
1261
+ return options => {
1262
+ return new RootRoute(options);
1263
+ };
1264
+ }
1265
+ class RootRoute extends Route {
1266
+ constructor(options) {
1267
+ super(options);
1268
+ }
1269
+ }
1270
+ function createRouteMask(opts) {
1271
+ return opts;
1272
+ }
1273
+
1274
+ //
1275
+
1276
+ class NotFoundRoute extends Route {
1277
+ constructor(options) {
1278
+ super({
1279
+ ...options,
1280
+ id: '404'
1281
+ });
1282
+ }
1283
+ }
1284
+
1285
+ const matchContext = /*#__PURE__*/React__namespace.createContext(undefined);
1286
+ function Matches() {
1287
+ const router = useRouter();
1288
+ const matchId = useRouterState({
1289
+ select: s => {
1290
+ return getRenderedMatches(s)[0]?.id;
1291
+ }
1292
+ });
1293
+ return /*#__PURE__*/React__namespace.createElement(matchContext.Provider, {
1294
+ value: matchId
1295
+ }, /*#__PURE__*/React__namespace.createElement(CatchBoundary, {
1296
+ getResetKey: () => router.state.resolvedLocation.state?.key,
1297
+ errorComponent: ErrorComponent,
1298
+ onCatch: () => {
1299
+ warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
1300
+ }
1301
+ }, matchId ? /*#__PURE__*/React__namespace.createElement(Match, {
1302
+ matchId: matchId
1303
+ }) : null));
1304
+ }
1305
+ function SafeFragment(props) {
1306
+ return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, props.children);
1307
+ }
1308
+ function Match({
1309
+ matchId
1310
+ }) {
1311
+ const router = useRouter();
1312
+ const routeId = useRouterState({
1313
+ select: s => getRenderedMatches(s).find(d => d.id === matchId)?.routeId
1314
+ });
1315
+ invariant(routeId, `Could not find routeId for matchId "${matchId}". Please file an issue!`);
1316
+ const route = router.routesById[routeId];
1317
+ const PendingComponent = route.options.pendingComponent ?? router.options.defaultPendingComponent;
1318
+ const pendingElement = PendingComponent ? /*#__PURE__*/React__namespace.createElement(PendingComponent, null) : null;
1319
+ const routeErrorComponent = route.options.errorComponent ?? router.options.defaultErrorComponent ?? ErrorComponent;
1320
+ const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? PendingComponent ?? route.options.component?.preload ?? route.options.pendingComponent?.preload ?? route.options.errorComponent?.preload ? React__namespace.Suspense : SafeFragment;
1321
+ const ResolvedCatchBoundary = routeErrorComponent ? CatchBoundary : SafeFragment;
1322
+ return /*#__PURE__*/React__namespace.createElement(matchContext.Provider, {
1323
+ value: matchId
1324
+ }, /*#__PURE__*/React__namespace.createElement(ResolvedSuspenseBoundary, {
1325
+ fallback: pendingElement
1326
+ }, /*#__PURE__*/React__namespace.createElement(ResolvedCatchBoundary, {
1327
+ getResetKey: () => router.state.resolvedLocation.state?.key,
1328
+ errorComponent: routeErrorComponent,
1329
+ onCatch: () => {
1330
+ warning(false, `Error in route match: ${matchId}`);
1331
+ }
1332
+ }, /*#__PURE__*/React__namespace.createElement(MatchInner, {
1333
+ matchId: matchId,
1334
+ pendingElement: pendingElement
1335
+ }))));
1336
+ }
1337
+ function MatchInner({
1338
+ matchId,
1339
+ pendingElement
1340
+ }) {
1341
+ const router = useRouter();
1342
+ const routeId = useRouterState({
1343
+ select: s => getRenderedMatches(s).find(d => d.id === matchId)?.routeId
1344
+ });
1345
+ const route = router.routesById[routeId];
1346
+ const match = useRouterState({
1347
+ select: s => pick(getRenderedMatches(s).find(d => d.id === matchId), ['status', 'error', 'showPending', 'loadPromise'])
1348
+ });
1349
+ if (match.status === 'error') {
1350
+ throw match.error;
1351
+ }
1352
+ if (match.status === 'pending') {
1353
+ if (match.showPending) {
1354
+ return pendingElement;
1355
+ }
1356
+ throw match.loadPromise;
1357
+ }
1358
+ if (match.status === 'success') {
1359
+ let Comp = route.options.component ?? router.options.defaultComponent;
1360
+ if (Comp) {
1361
+ return /*#__PURE__*/React__namespace.createElement(Comp, null);
1362
+ }
1363
+ return /*#__PURE__*/React__namespace.createElement(Outlet, null);
1364
+ }
1365
+ invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
1366
+ }
1367
+ const Outlet = /*#__PURE__*/React__namespace.memo(function Outlet() {
1368
+ const matchId = React__namespace.useContext(matchContext);
1369
+ const childMatchId = useRouterState({
1370
+ select: s => {
1371
+ const matches = getRenderedMatches(s);
1372
+ const index = matches.findIndex(d => d.id === matchId);
1373
+ return matches[index + 1]?.id;
1374
+ }
1375
+ });
1376
+ if (!childMatchId) {
1377
+ return null;
1378
+ }
1379
+ return /*#__PURE__*/React__namespace.createElement(Match, {
1380
+ matchId: childMatchId
1381
+ });
1382
+ });
1383
+ function useMatchRoute() {
1384
+ useRouterState({
1385
+ select: s => [s.location, s.resolvedLocation]
1386
+ });
1387
+ const {
1388
+ matchRoute
1389
+ } = useRouter();
1390
+ return React__namespace.useCallback(opts => {
1391
+ const {
1392
+ pending,
1393
+ caseSensitive,
1394
+ ...rest
1395
+ } = opts;
1396
+ return matchRoute(rest, {
1397
+ pending,
1398
+ caseSensitive
1399
+ });
1400
+ }, []);
1401
+ }
1402
+ function MatchRoute(props) {
1403
+ const matchRoute = useMatchRoute();
1404
+ const params = matchRoute(props);
1405
+ if (typeof props.children === 'function') {
1406
+ return props.children(params);
1407
+ }
1408
+ return !!params ? props.children : null;
1409
+ }
1410
+ function getRenderedMatches(state) {
1411
+ return state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
1412
+ }
1413
+ function removeUnderscores(s) {
1414
+ if (s === rootRouteId) return s;
1415
+ return s?.replace(/(^_|_$)/, '').replace(/(\/_|_\/)/, '/');
1416
+ }
1417
+ function useMatch(opts) {
1418
+ const router = useRouter();
1419
+ const nearestMatchId = React__namespace.useContext(matchContext);
1420
+ const nearestMatchRouteId = getRenderedMatches(router.state).find(d => d.id === nearestMatchId)?.routeId;
1421
+ const matchRouteId = (() => {
1422
+ const matches = getRenderedMatches(router.state);
1423
+ if (!opts.from) {
1424
+ return matches.find(d => d.id === nearestMatchId);
1425
+ }
1426
+ const from = removeUnderscores(opts.from);
1427
+ return matches.find(d => d.routeId === from) ?? matches.find(d => d.routeId === from?.replace(/\/$/, ''));
1428
+ })()?.routeId;
1429
+ if (opts?.strict ?? true) {
1430
+ invariant(nearestMatchRouteId == matchRouteId, `useMatch("${matchRouteId}") is being called in a component that is meant to render the '${nearestMatchRouteId}' route. Did you mean to 'useMatch("${matchRouteId}", { strict: false })' or 'useRoute("${matchRouteId}")' instead?`);
1431
+ }
1432
+ const matchSelection = useRouterState({
1433
+ select: state => {
1434
+ const match = getRenderedMatches(state).find(d => d.id === nearestMatchId);
1435
+ invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
1436
+ return opts?.select ? opts.select(match) : match;
1437
+ }
1438
+ });
1439
+ return matchSelection;
1440
+ }
1441
+ function useMatches(opts) {
1442
+ return useRouterState({
1443
+ select: state => {
1444
+ let matches = getRenderedMatches(state);
1445
+ return opts?.select ? opts.select(matches) : matches;
1446
+ }
1447
+ });
1448
+ }
1449
+ function useParentMatches(opts) {
1450
+ const contextMatchId = React__namespace.useContext(matchContext);
1451
+ return useMatches({
1452
+ select: matches => {
1453
+ matches = matches.slice(matches.findIndex(d => d.id === contextMatchId));
1454
+ return opts?.select ? opts.select(matches) : matches;
1455
+ }
1456
+ });
1457
+ }
1458
+ function useLoaderDeps(opts) {
1459
+ return useMatch({
1460
+ ...opts,
1461
+ select: s => {
1462
+ return typeof opts.select === 'function' ? opts.select(s?.loaderDeps) : s?.loaderDeps;
1552
1463
  }
1553
- const customId = options?.id || path;
1464
+ });
1465
+ }
1466
+ function useLoaderData(opts) {
1467
+ return useMatch({
1468
+ ...opts,
1469
+ select: s => {
1470
+ return typeof opts.select === 'function' ? opts.select(s?.loaderData) : s?.loaderData;
1471
+ }
1472
+ });
1473
+ }
1554
1474
 
1555
- // Strip the parentId prefix from the first level of children
1556
- let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
1557
- if (path === rootRouteId) {
1558
- path = '/';
1475
+ exports.routerContext = /*#__PURE__*/React__namespace.createContext(null);
1476
+ if (typeof document !== 'undefined') {
1477
+ if (window.__TSR_ROUTER_CONTEXT__) {
1478
+ exports.routerContext = window.__TSR_ROUTER_CONTEXT__;
1479
+ } else {
1480
+ window.__TSR_ROUTER_CONTEXT__ = exports.routerContext;
1481
+ }
1482
+ }
1483
+ function RouterProvider({
1484
+ router,
1485
+ ...rest
1486
+ }) {
1487
+ // Allow the router to update options on the router instance
1488
+ router.update({
1489
+ ...router.options,
1490
+ ...rest,
1491
+ context: {
1492
+ ...router.options.context,
1493
+ ...rest?.context
1559
1494
  }
1560
- if (id !== rootRouteId) {
1561
- id = joinPaths(['/', id]);
1495
+ });
1496
+ const matches = router.options.InnerWrap ? /*#__PURE__*/React__namespace.createElement(router.options.InnerWrap, null, /*#__PURE__*/React__namespace.createElement(Matches, null)) : /*#__PURE__*/React__namespace.createElement(Matches, null);
1497
+ const provider = /*#__PURE__*/React__namespace.createElement(exports.routerContext.Provider, {
1498
+ value: router
1499
+ }, matches, /*#__PURE__*/React__namespace.createElement(Transitioner, null));
1500
+ if (router.options.Wrap) {
1501
+ return /*#__PURE__*/React__namespace.createElement(router.options.Wrap, null, provider);
1502
+ }
1503
+ return provider;
1504
+ }
1505
+ function Transitioner() {
1506
+ const router = useRouter();
1507
+ const routerState = useRouterState({
1508
+ select: s => pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning'])
1509
+ });
1510
+ const [isTransitioning, startReactTransition] = React__namespace.useTransition();
1511
+ router.startReactTransition = startReactTransition;
1512
+ React__namespace.useEffect(() => {
1513
+ if (isTransitioning) {
1514
+ router.__store.setState(s => ({
1515
+ ...s,
1516
+ isTransitioning
1517
+ }));
1562
1518
  }
1563
- const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
1564
- this.path = path;
1565
- this.id = id;
1566
- // this.customId = customId as TCustomId
1567
- this.fullPath = fullPath;
1568
- this.to = fullPath;
1569
- };
1570
- addChildren = children => {
1571
- this.children = children;
1572
- return this;
1573
- };
1574
- update = options => {
1575
- Object.assign(this.options, options);
1576
- return this;
1577
- };
1578
- useMatch = opts => {
1579
- return useMatch({
1580
- ...opts,
1581
- from: this.id
1582
- });
1583
- };
1584
- useRouteContext = opts => {
1585
- return useMatch({
1586
- ...opts,
1587
- from: this.id,
1588
- select: d => opts?.select ? opts.select(d.context) : d.context
1589
- });
1590
- };
1591
- useSearch = opts => {
1592
- return useSearch({
1593
- ...opts,
1594
- from: this.id
1595
- });
1596
- };
1597
- useParams = opts => {
1598
- return useParams({
1599
- ...opts,
1600
- from: this.id
1519
+ }, [isTransitioning]);
1520
+ const tryLoad = () => {
1521
+ const apply = cb => {
1522
+ if (!routerState.isTransitioning) {
1523
+ startReactTransition(() => cb());
1524
+ } else {
1525
+ cb();
1526
+ }
1527
+ };
1528
+ apply(() => {
1529
+ try {
1530
+ router.load();
1531
+ } catch (err) {
1532
+ console.error(err);
1533
+ }
1601
1534
  });
1602
1535
  };
1603
- useLoaderDeps = opts => {
1604
- return useLoaderDeps({
1605
- ...opts,
1606
- from: this.id
1536
+ useLayoutEffect$1(() => {
1537
+ const unsub = router.history.subscribe(() => {
1538
+ router.latestLocation = router.parseLocation(router.latestLocation);
1539
+ if (routerState.location !== router.latestLocation) {
1540
+ tryLoad();
1541
+ }
1607
1542
  });
1608
- };
1609
- useLoaderData = opts => {
1610
- return useLoaderData({
1611
- ...opts,
1612
- from: this.id
1543
+ const nextLocation = router.buildLocation({
1544
+ search: true,
1545
+ params: true,
1546
+ hash: true,
1547
+ state: true
1613
1548
  });
1614
- };
1549
+ if (routerState.location.href !== nextLocation.href) {
1550
+ router.commitLocation({
1551
+ ...nextLocation,
1552
+ replace: true
1553
+ });
1554
+ }
1555
+ return () => {
1556
+ unsub();
1557
+ };
1558
+ }, [router.history]);
1559
+ useLayoutEffect$1(() => {
1560
+ if (routerState.isTransitioning && !isTransitioning && !routerState.isLoading && routerState.resolvedLocation !== routerState.location) {
1561
+ router.emit({
1562
+ type: 'onResolved',
1563
+ fromLocation: routerState.resolvedLocation,
1564
+ toLocation: routerState.location,
1565
+ pathChanged: routerState.location.href !== routerState.resolvedLocation?.href
1566
+ });
1567
+ if (document.querySelector) {
1568
+ if (routerState.location.hash !== '') {
1569
+ const el = document.getElementById(routerState.location.hash);
1570
+ if (el) {
1571
+ el.scrollIntoView();
1572
+ }
1573
+ }
1574
+ }
1575
+ router.__store.setState(s => ({
1576
+ ...s,
1577
+ isTransitioning: false,
1578
+ resolvedLocation: s.location
1579
+ }));
1580
+ }
1581
+ }, [routerState.isTransitioning, isTransitioning, routerState.isLoading, routerState.resolvedLocation, routerState.location]);
1582
+ useLayoutEffect$1(() => {
1583
+ if (!window.__TSR_DEHYDRATED__) {
1584
+ tryLoad();
1585
+ }
1586
+ }, []);
1587
+ return null;
1615
1588
  }
1616
- function rootRouteWithContext() {
1617
- return options => {
1618
- return new RootRoute(options);
1619
- };
1589
+ function getRouteMatch(state, id) {
1590
+ return [...state.cachedMatches, ...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
1620
1591
  }
1621
- class RootRoute extends Route {
1622
- constructor(options) {
1623
- super(options);
1624
- }
1592
+ function useRouterState(opts) {
1593
+ const router = useRouter();
1594
+ return useStore(router.__store, opts?.select);
1625
1595
  }
1626
- function createRouteMask(opts) {
1627
- return opts;
1596
+ function useRouter() {
1597
+ const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || exports.routerContext : exports.routerContext;
1598
+ const value = React__namespace.useContext(resolvedContext);
1599
+ warning(value, 'useRouter must be used inside a <RouterProvider> component!');
1600
+ return value;
1628
1601
  }
1629
1602
 
1630
- //
1631
-
1632
- class NotFoundRoute extends Route {
1633
- constructor(options) {
1634
- super({
1635
- ...options,
1636
- id: '404'
1603
+ function defer(_promise) {
1604
+ const promise = _promise;
1605
+ if (!promise.__deferredState) {
1606
+ promise.__deferredState = {
1607
+ uid: Math.random().toString(36).slice(2),
1608
+ status: 'pending'
1609
+ };
1610
+ const state = promise.__deferredState;
1611
+ promise.then(data => {
1612
+ state.status = 'success';
1613
+ state.data = data;
1614
+ }).catch(error => {
1615
+ state.status = 'error';
1616
+ state.error = error;
1637
1617
  });
1638
1618
  }
1619
+ return promise;
1620
+ }
1621
+ function isDehydratedDeferred(obj) {
1622
+ return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
1623
+ }
1624
+
1625
+ function useAwaited({
1626
+ promise
1627
+ }) {
1628
+ const router = useRouter();
1629
+ let state = promise.__deferredState;
1630
+ const key = `__TSR__DEFERRED__${state.uid}`;
1631
+ if (isDehydratedDeferred(promise)) {
1632
+ state = router.hydrateData(key);
1633
+ promise = Promise.resolve(state.data);
1634
+ promise.__deferredState = state;
1635
+ }
1636
+ if (state.status === 'pending') {
1637
+ throw new Promise(r => setTimeout(r, 1)).then(() => promise);
1638
+ }
1639
+ if (state.status === 'error') {
1640
+ throw state.error;
1641
+ }
1642
+ router.dehydrateData(key, state);
1643
+ return [state.data];
1644
+ }
1645
+ function Await(props) {
1646
+ const awaited = useAwaited(props);
1647
+ return props.children(...awaited);
1639
1648
  }
1640
1649
 
1641
1650
  class FileRoute {