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