@tanstack/react-router 0.0.1-beta.223 → 0.0.1-beta.225

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.
Files changed (65) hide show
  1. package/build/cjs/CatchBoundary.js +3 -6
  2. package/build/cjs/CatchBoundary.js.map +1 -1
  3. package/build/cjs/Matches.js +8 -15
  4. package/build/cjs/Matches.js.map +1 -1
  5. package/build/cjs/RouterProvider.js +61 -968
  6. package/build/cjs/RouterProvider.js.map +1 -1
  7. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +1 -3
  8. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
  9. package/build/cjs/awaited.js +0 -2
  10. package/build/cjs/awaited.js.map +1 -1
  11. package/build/cjs/defer.js +0 -2
  12. package/build/cjs/defer.js.map +1 -1
  13. package/build/cjs/fileRoute.js +0 -2
  14. package/build/cjs/fileRoute.js.map +1 -1
  15. package/build/cjs/index.js +3 -16
  16. package/build/cjs/index.js.map +1 -1
  17. package/build/cjs/lazyRouteComponent.js +3 -6
  18. package/build/cjs/lazyRouteComponent.js.map +1 -1
  19. package/build/cjs/link.js +4 -7
  20. package/build/cjs/link.js.map +1 -1
  21. package/build/cjs/path.js +0 -2
  22. package/build/cjs/path.js.map +1 -1
  23. package/build/cjs/qss.js +0 -2
  24. package/build/cjs/qss.js.map +1 -1
  25. package/build/cjs/redirects.js +0 -2
  26. package/build/cjs/redirects.js.map +1 -1
  27. package/build/cjs/route.js +2 -7
  28. package/build/cjs/route.js.map +1 -1
  29. package/build/cjs/router.js +949 -42
  30. package/build/cjs/router.js.map +1 -1
  31. package/build/cjs/scroll-restoration.js +8 -15
  32. package/build/cjs/scroll-restoration.js.map +1 -1
  33. package/build/cjs/searchParams.js +0 -2
  34. package/build/cjs/searchParams.js.map +1 -1
  35. package/build/cjs/useBlocker.js +3 -6
  36. package/build/cjs/useBlocker.js.map +1 -1
  37. package/build/cjs/useNavigate.js +3 -6
  38. package/build/cjs/useNavigate.js.map +1 -1
  39. package/build/cjs/useParams.js +0 -2
  40. package/build/cjs/useParams.js.map +1 -1
  41. package/build/cjs/useSearch.js +0 -2
  42. package/build/cjs/useSearch.js.map +1 -1
  43. package/build/cjs/utils.js +9 -6
  44. package/build/cjs/utils.js.map +1 -1
  45. package/build/esm/index.js +889 -878
  46. package/build/esm/index.js.map +1 -1
  47. package/build/stats-html.html +3494 -2700
  48. package/build/stats-react.json +374 -368
  49. package/build/types/CatchBoundary.d.ts +2 -2
  50. package/build/types/Matches.d.ts +3 -3
  51. package/build/types/RouterProvider.d.ts +4 -23
  52. package/build/types/awaited.d.ts +1 -0
  53. package/build/types/fileRoute.d.ts +4 -3
  54. package/build/types/route.d.ts +1 -0
  55. package/build/types/router.d.ts +50 -5
  56. package/build/umd/index.development.js +865 -857
  57. package/build/umd/index.development.js.map +1 -1
  58. package/build/umd/index.production.js +2 -2
  59. package/build/umd/index.production.js.map +1 -1
  60. package/package.json +2 -2
  61. package/src/RouterProvider.tsx +57 -1314
  62. package/src/fileRoute.ts +1 -1
  63. package/src/route.ts +23 -0
  64. package/src/router.ts +1320 -45
  65. package/src/scroll-restoration.tsx +5 -5
@@ -14,8 +14,7 @@
14
14
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactRouter = {}, global.React));
15
15
  })(this, (function (exports, React) { 'use strict';
16
16
 
17
- function _interopNamespace(e) {
18
- if (e && e.__esModule) return e;
17
+ function _interopNamespaceDefault(e) {
19
18
  var n = Object.create(null);
20
19
  if (e) {
21
20
  Object.keys(e).forEach(function (k) {
@@ -28,11 +27,11 @@
28
27
  }
29
28
  });
30
29
  }
31
- n["default"] = e;
30
+ n.default = e;
32
31
  return Object.freeze(n);
33
32
  }
34
33
 
35
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
36
35
 
37
36
  /**
38
37
  * @tanstack/history/src/index.ts
@@ -446,6 +445,7 @@
446
445
  // : never
447
446
  // }
448
447
  // >
448
+
449
449
  // // Sample types to merge
450
450
  // type TypeA = {
451
451
  // shared: string
@@ -456,6 +456,7 @@
456
456
  // }
457
457
  // array: string[]
458
458
  // }
459
+
459
460
  // type TypeB = {
460
461
  // shared: number
461
462
  // onlyInB: number
@@ -465,6 +466,7 @@
465
466
  // }
466
467
  // array: number[]
467
468
  // }
469
+
468
470
  // type TypeC = {
469
471
  // shared: boolean
470
472
  // onlyInC: boolean
@@ -474,9 +476,12 @@
474
476
  // }
475
477
  // array: boolean[]
476
478
  // }
479
+
477
480
  // type Test = Expand<Assign<TypeA, TypeB>>
481
+
478
482
  // // Using DeepMerge to merge TypeA and TypeB
479
483
  // type MergedType = Expand<AssignAll<[TypeA, TypeB, TypeC]>>
484
+
480
485
  //
481
486
 
482
487
  const isServer = typeof document === 'undefined';
@@ -832,6 +837,7 @@
832
837
  this.options = options || {};
833
838
  this.isRoot = !options?.getParentRoute;
834
839
  Route.__onInit(this);
840
+ this.$$typeof = Symbol.for('react.memo');
835
841
  }
836
842
  init = opts => {
837
843
  this.originalIndex = opts.originalIndex;
@@ -1106,274 +1112,35 @@
1106
1112
  return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
1107
1113
  }
1108
1114
 
1109
- // Detect if we're in the DOM
1110
-
1111
- function redirect(opts) {
1112
- opts.isRedirect = true;
1113
- return opts;
1114
- }
1115
- function isRedirect(obj) {
1116
- return !!obj?.isRedirect;
1117
- }
1118
-
1119
- // @ts-nocheck
1120
-
1121
- // 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.
1122
-
1123
- function encode(obj, pfx) {
1124
- var k,
1125
- i,
1126
- tmp,
1127
- str = '';
1128
- for (k in obj) {
1129
- if ((tmp = obj[k]) !== void 0) {
1130
- if (Array.isArray(tmp)) {
1131
- for (i = 0; i < tmp.length; i++) {
1132
- str && (str += '&');
1133
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1134
- }
1135
- } else {
1136
- str && (str += '&');
1137
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
1138
- }
1139
- }
1140
- }
1141
- return (pfx || '') + str;
1142
- }
1143
- function toValue(mix) {
1144
- if (!mix) return '';
1145
- var str = decodeURIComponent(mix);
1146
- if (str === 'false') return false;
1147
- if (str === 'true') return true;
1148
- return +str * 0 === 0 && +str + '' === str ? +str : str;
1149
- }
1150
- function decode(str) {
1151
- var tmp,
1152
- k,
1153
- out = {},
1154
- arr = str.split('&');
1155
- while (tmp = arr.shift()) {
1156
- tmp = tmp.split('=');
1157
- k = tmp.shift();
1158
- if (out[k] !== void 0) {
1159
- out[k] = [].concat(out[k], toValue(tmp.shift()));
1160
- } else {
1161
- out[k] = toValue(tmp.shift());
1162
- }
1163
- }
1164
- return out;
1165
- }
1166
-
1167
- const defaultParseSearch = parseSearchWith(JSON.parse);
1168
- const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
1169
- function parseSearchWith(parser) {
1170
- return searchStr => {
1171
- if (searchStr.substring(0, 1) === '?') {
1172
- searchStr = searchStr.substring(1);
1173
- }
1174
- let query = decode(searchStr);
1175
-
1176
- // Try to parse any query params that might be json
1177
- for (let key in query) {
1178
- const value = query[key];
1179
- if (typeof value === 'string') {
1180
- try {
1181
- query[key] = parser(value);
1182
- } catch (err) {
1183
- //
1184
- }
1185
- }
1186
- }
1187
- return query;
1188
- };
1189
- }
1190
- function stringifySearchWith(stringify, parser) {
1191
- function stringifyValue(val) {
1192
- if (typeof val === 'object' && val !== null) {
1193
- try {
1194
- return stringify(val);
1195
- } catch (err) {
1196
- // silent
1197
- }
1198
- } else if (typeof val === 'string' && typeof parser === 'function') {
1199
- try {
1200
- // Check if it's a valid parseable string.
1201
- // If it is, then stringify it again.
1202
- parser(val);
1203
- return stringify(val);
1204
- } catch (err) {
1205
- // silent
1206
- }
1207
- }
1208
- return val;
1209
- }
1210
- return search => {
1211
- search = {
1212
- ...search
1213
- };
1214
- if (search) {
1215
- Object.keys(search).forEach(key => {
1216
- const val = search[key];
1217
- if (typeof val === 'undefined' || val === undefined) {
1218
- delete search[key];
1219
- } else {
1220
- search[key] = stringifyValue(val);
1221
- }
1222
- });
1223
- }
1224
- const searchStr = encode(search).toString();
1225
- return searchStr ? `?${searchStr}` : '';
1226
- };
1227
- }
1228
-
1229
- //
1230
-
1231
- //
1232
-
1233
- const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1234
- class Router {
1235
- // dehydratedData?: TDehydrated
1236
- // resetNextScroll = false
1237
- // tempLocationKey = `${Math.round(Math.random() * 10000000)}`
1238
- constructor(options) {
1239
- this.options = {
1240
- defaultPreloadDelay: 50,
1241
- context: undefined,
1242
- ...options,
1243
- stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
1244
- parseSearch: options?.parseSearch ?? defaultParseSearch
1245
- };
1246
- this.routeTree = this.options.routeTree;
1247
- }
1248
- subscribers = new Set();
1249
- subscribe = (eventType, fn) => {
1250
- const listener = {
1251
- eventType,
1252
- fn
1253
- };
1254
- this.subscribers.add(listener);
1255
- return () => {
1256
- this.subscribers.delete(listener);
1257
- };
1258
- };
1259
- emit = routerEvent => {
1260
- this.subscribers.forEach(listener => {
1261
- if (listener.eventType === routerEvent.type) {
1262
- listener.fn(routerEvent);
1263
- }
1264
- });
1265
- };
1266
-
1267
- // dehydrate = (): DehydratedRouter => {
1268
- // return {
1269
- // state: {
1270
- // dehydratedMatches: state.matches.map((d) =>
1271
- // pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
1272
- // ),
1273
- // },
1274
- // }
1275
- // }
1276
-
1277
- // hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
1278
- // let _ctx = __do_not_use_server_ctx
1279
- // // Client hydrates from window
1280
- // if (typeof document !== 'undefined') {
1281
- // _ctx = window.__TSR_DEHYDRATED__
1282
- // }
1283
-
1284
- // invariant(
1285
- // _ctx,
1286
- // 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
1287
- // )
1288
-
1289
- // const ctx = _ctx
1290
- // this.dehydratedData = ctx.payload as any
1291
- // this.options.hydrate?.(ctx.payload as any)
1292
- // const dehydratedState = ctx.router.state
1293
-
1294
- // let matches = this.matchRoutes(
1295
- // state.location.pathname,
1296
- // state.location.search,
1297
- // ).map((match) => {
1298
- // const dehydratedMatch = dehydratedState.dehydratedMatches.find(
1299
- // (d) => d.id === match.id,
1300
- // )
1301
-
1302
- // invariant(
1303
- // dehydratedMatch,
1304
- // `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
1305
- // )
1306
-
1307
- // if (dehydratedMatch) {
1308
- // return {
1309
- // ...match,
1310
- // ...dehydratedMatch,
1311
- // }
1312
- // }
1313
- // return match
1314
- // })
1315
-
1316
- // this.setState((s) => {
1317
- // return {
1318
- // ...s,
1319
- // matches: dehydratedState.dehydratedMatches as any,
1320
- // }
1321
- // })
1322
- // }
1323
-
1324
- // resolveMatchPromise = (matchId: string, key: string, value: any) => {
1325
- // state.matches
1326
- // .find((d) => d.id === matchId)
1327
- // ?.__promisesByKey[key]?.resolve(value)
1328
- // }
1329
-
1330
- // setRouteMatch = (
1331
- // id: string,
1332
- // pending: boolean,
1333
- // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
1334
- // ) => {
1335
- // const key = pending ? 'pendingMatches' : 'matches'
1336
-
1337
- // this.setState((prev) => {
1338
- // return {
1339
- // ...prev,
1340
- // [key]: prev[key].map((d) => {
1341
- // if (d.id === id) {
1342
- // return functionalUpdate(updater, d)
1343
- // }
1344
-
1345
- // return d
1346
- // }),
1347
- // }
1348
- // })
1349
- // }
1350
-
1351
- // setPendingRouteMatch = (
1352
- // id: string,
1353
- // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
1354
- // ) => {
1355
- // this.setRouteMatch(id, true, updater)
1356
- // }
1357
- }
1358
-
1359
- // A function that takes an import() argument which is a function and returns a new function that will
1360
- // proxy arguments from the caller to the imported function, retaining all type
1361
- // information along the way
1362
- function lazyFn(fn, key) {
1363
- return async (...args) => {
1364
- const imported = await fn();
1365
- return imported[key || 'default'](...args);
1366
- };
1367
- }
1115
+ // export type RouterContext<
1116
+ // TRouteTree extends AnyRoute,
1117
+ // // TDehydrated extends Record<string, any>,
1118
+ // > = {
1119
+ // buildLink: BuildLinkFn<TRouteTree>
1120
+ // state: RouterState<TRouteTree>
1121
+ // navigate: NavigateFn<TRouteTree>
1122
+ // matchRoute: MatchRouteFn<TRouteTree>
1123
+ // routeTree: TRouteTree
1124
+ // routesById: RoutesById<TRouteTree>
1125
+ // options: RouterOptions<TRouteTree>
1126
+ // history: RouterHistory
1127
+ // load: LoadFn
1128
+ // buildLocation: BuildLocationFn<TRouteTree>
1129
+ // subscribe: Router<TRouteTree>['subscribe']
1130
+ // resetNextScrollRef: React.MutableRefObject<boolean>
1131
+ // injectedHtmlRef: React.MutableRefObject<InjectedHtmlEntry[]>
1132
+ // injectHtml: (entry: InjectedHtmlEntry) => void
1133
+ // dehydrateData: <T>(
1134
+ // key: any,
1135
+ // getData: T | (() => Promise<T> | T),
1136
+ // ) => () => void
1137
+ // hydrateData: <T>(key: any) => T | undefined
1138
+ // }
1368
1139
 
1369
1140
  const routerContext = /*#__PURE__*/React__namespace.createContext(null);
1370
1141
  if (typeof document !== 'undefined') {
1371
1142
  window.__TSR_ROUTER_CONTEXT__ = routerContext;
1372
1143
  }
1373
- const preloadWarning = 'Error preloading route! ☝️';
1374
- function isCtrlEvent(e) {
1375
- return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
1376
- }
1377
1144
  class SearchParamError extends Error {}
1378
1145
  class PathParamError extends Error {}
1379
1146
  function getInitialRouterState(location) {
@@ -1390,45 +1157,598 @@
1390
1157
  router,
1391
1158
  ...rest
1392
1159
  }) {
1393
- const options = {
1160
+ // Allow the router to update options on the router instance
1161
+ router.updateOptions({
1394
1162
  ...router.options,
1395
1163
  ...rest,
1396
1164
  context: {
1397
1165
  ...router.options.context,
1398
1166
  ...rest?.context
1399
1167
  }
1400
- };
1401
- const history = React__namespace.useState(() => options.history ?? createBrowserHistory())[0];
1402
- const tempLocationKeyRef = React__namespace.useRef(`${Math.round(Math.random() * 10000000)}`);
1403
- const resetNextScrollRef = React__namespace.useRef(true);
1404
- const navigateTimeoutRef = React__namespace.useRef(null);
1405
- const latestLoadPromiseRef = React__namespace.useRef(Promise.resolve());
1406
- const checkLatest = promise => {
1407
- return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
1408
- };
1409
- const parseLocation = useStableCallback(previousLocation => {
1410
- const parse = ({
1411
- pathname,
1412
- search,
1413
- hash,
1414
- state
1415
- }) => {
1416
- const parsedSearch = options.parseSearch(search);
1417
- return {
1418
- pathname: pathname,
1419
- searchStr: search,
1420
- search: replaceEqualDeep(previousLocation?.search, parsedSearch),
1421
- hash: hash.split('#').reverse()[0] ?? '',
1168
+ });
1169
+ const [preState, setState] = React__namespace.useState(() => router.state);
1170
+ const [isTransitioning, startReactTransition] = React__namespace.useTransition();
1171
+ const state = React__namespace.useMemo(() => ({
1172
+ ...preState,
1173
+ status: isTransitioning ? 'pending' : 'idle',
1174
+ location: isTransitioning ? router.latestLocation : preState.location,
1175
+ pendingMatches: router.pendingMatches
1176
+ }), [preState, isTransitioning]);
1177
+ router.setState = setState;
1178
+ router.state = state;
1179
+ router.startReactTransition = startReactTransition;
1180
+ React__namespace.useLayoutEffect(() => {
1181
+ const unsub = router.history.subscribe(() => {
1182
+ router.latestLocation = router.parseLocation(router.latestLocation);
1183
+ if (state.location !== router.latestLocation) {
1184
+ startReactTransition(() => {
1185
+ try {
1186
+ router.load();
1187
+ } catch (err) {
1188
+ console.error(err);
1189
+ }
1190
+ });
1191
+ }
1192
+ });
1193
+ const nextLocation = router.buildLocation({
1194
+ search: true,
1195
+ params: true,
1196
+ hash: true,
1197
+ state: true
1198
+ });
1199
+ if (state.location.href !== nextLocation.href) {
1200
+ router.commitLocation({
1201
+ ...nextLocation,
1202
+ replace: true
1203
+ });
1204
+ }
1205
+ return () => {
1206
+ unsub();
1207
+ };
1208
+ }, [history]);
1209
+ React__namespace.useLayoutEffect(() => {
1210
+ if (!isTransitioning && state.resolvedLocation !== state.location) {
1211
+ router.emit({
1212
+ type: 'onResolved',
1213
+ fromLocation: state.resolvedLocation,
1214
+ toLocation: state.location,
1215
+ pathChanged: state.location.href !== state.resolvedLocation?.href
1216
+ });
1217
+ router.pendingMatches = [];
1218
+ setState(s => ({
1219
+ ...s,
1220
+ resolvedLocation: s.location
1221
+ }));
1222
+ }
1223
+ });
1224
+ React__namespace.useLayoutEffect(() => {
1225
+ startReactTransition(() => {
1226
+ try {
1227
+ router.load();
1228
+ } catch (err) {
1229
+ console.error(err);
1230
+ }
1231
+ });
1232
+ }, []);
1233
+ return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
1234
+ value: router
1235
+ }, /*#__PURE__*/React__namespace.createElement(Matches, null));
1236
+ }
1237
+ function getRouteMatch(state, id) {
1238
+ return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
1239
+ }
1240
+ function useRouterState(opts) {
1241
+ const {
1242
+ state
1243
+ } = useRouter();
1244
+ // return useStore(router.__store, opts?.select as any)
1245
+ return opts?.select ? opts.select(state) : state;
1246
+ }
1247
+ function useRouter() {
1248
+ const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
1249
+ const value = React__namespace.useContext(resolvedContext);
1250
+ warning(value, 'useRouter must be used inside a <RouterProvider> component!');
1251
+ return value;
1252
+ }
1253
+
1254
+ function defer(_promise) {
1255
+ const promise = _promise;
1256
+ if (!promise.__deferredState) {
1257
+ promise.__deferredState = {
1258
+ uid: Math.random().toString(36).slice(2),
1259
+ status: 'pending'
1260
+ };
1261
+ const state = promise.__deferredState;
1262
+ promise.then(data => {
1263
+ state.status = 'success';
1264
+ state.data = data;
1265
+ }).catch(error => {
1266
+ state.status = 'error';
1267
+ state.error = error;
1268
+ });
1269
+ }
1270
+ return promise;
1271
+ }
1272
+ function isDehydratedDeferred(obj) {
1273
+ return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
1274
+ }
1275
+
1276
+ function useAwaited({
1277
+ promise
1278
+ }) {
1279
+ const router = useRouter();
1280
+ let state = promise.__deferredState;
1281
+ const key = `__TSR__DEFERRED__${state.uid}`;
1282
+ if (isDehydratedDeferred(promise)) {
1283
+ state = router.hydrateData(key);
1284
+ promise = Promise.resolve(state.data);
1285
+ promise.__deferredState = state;
1286
+ }
1287
+ if (state.status === 'pending') {
1288
+ throw promise;
1289
+ }
1290
+ if (state.status === 'error') {
1291
+ throw state.error;
1292
+ }
1293
+ router.dehydrateData(key, state);
1294
+ return [state.data];
1295
+ }
1296
+ function Await(props) {
1297
+ const awaited = useAwaited(props);
1298
+ return props.children(...awaited);
1299
+ }
1300
+
1301
+ class FileRoute {
1302
+ constructor(path) {
1303
+ this.path = path;
1304
+ }
1305
+ createRoute = options => {
1306
+ const route = new Route(options);
1307
+ route.isRoot = false;
1308
+ return route;
1309
+ };
1310
+ }
1311
+
1312
+ function lazyRouteComponent(importer, exportName) {
1313
+ let loadPromise;
1314
+ const load = () => {
1315
+ if (!loadPromise) {
1316
+ loadPromise = importer();
1317
+ }
1318
+ return loadPromise;
1319
+ };
1320
+ const lazyComp = /*#__PURE__*/React__namespace.lazy(async () => {
1321
+ const moduleExports = await load();
1322
+ const comp = moduleExports[exportName ?? 'default'];
1323
+ return {
1324
+ default: comp
1325
+ };
1326
+ });
1327
+ lazyComp.preload = load;
1328
+ return lazyComp;
1329
+ }
1330
+
1331
+ function _extends() {
1332
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
1333
+ for (var i = 1; i < arguments.length; i++) {
1334
+ var source = arguments[i];
1335
+ for (var key in source) {
1336
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1337
+ target[key] = source[key];
1338
+ }
1339
+ }
1340
+ }
1341
+ return target;
1342
+ };
1343
+ return _extends.apply(this, arguments);
1344
+ }
1345
+
1346
+ function useLinkProps(options) {
1347
+ const {
1348
+ buildLink
1349
+ } = useRouter();
1350
+ const match = useMatch({
1351
+ strict: false
1352
+ });
1353
+ const {
1354
+ // custom props
1355
+ type,
1356
+ children,
1357
+ target,
1358
+ activeProps = () => ({
1359
+ className: 'active'
1360
+ }),
1361
+ inactiveProps = () => ({}),
1362
+ activeOptions,
1363
+ disabled,
1364
+ hash,
1365
+ search,
1366
+ params,
1367
+ to,
1368
+ state,
1369
+ mask,
1370
+ preload,
1371
+ preloadDelay,
1372
+ replace,
1373
+ startTransition,
1374
+ resetScroll,
1375
+ // element props
1376
+ style,
1377
+ className,
1378
+ onClick,
1379
+ onFocus,
1380
+ onMouseEnter,
1381
+ onMouseLeave,
1382
+ onTouchStart,
1383
+ ...rest
1384
+ } = options;
1385
+ const linkInfo = buildLink({
1386
+ from: options.to ? match.pathname : undefined,
1387
+ ...options
1388
+ });
1389
+ if (linkInfo.type === 'external') {
1390
+ const {
1391
+ href
1392
+ } = linkInfo;
1393
+ return {
1394
+ href
1395
+ };
1396
+ }
1397
+ const {
1398
+ handleClick,
1399
+ handleFocus,
1400
+ handleEnter,
1401
+ handleLeave,
1402
+ handleTouchStart,
1403
+ isActive,
1404
+ next
1405
+ } = linkInfo;
1406
+ const composeHandlers = handlers => e => {
1407
+ if (e.persist) e.persist();
1408
+ handlers.filter(Boolean).forEach(handler => {
1409
+ if (e.defaultPrevented) return;
1410
+ handler(e);
1411
+ });
1412
+ };
1413
+
1414
+ // Get the active props
1415
+ const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
1416
+
1417
+ // Get the inactive props
1418
+ const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
1419
+ return {
1420
+ ...resolvedActiveProps,
1421
+ ...resolvedInactiveProps,
1422
+ ...rest,
1423
+ href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
1424
+ onClick: composeHandlers([onClick, handleClick]),
1425
+ onFocus: composeHandlers([onFocus, handleFocus]),
1426
+ onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
1427
+ onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
1428
+ onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
1429
+ target,
1430
+ style: {
1431
+ ...style,
1432
+ ...resolvedActiveProps.style,
1433
+ ...resolvedInactiveProps.style
1434
+ },
1435
+ className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
1436
+ ...(disabled ? {
1437
+ role: 'link',
1438
+ 'aria-disabled': true
1439
+ } : undefined),
1440
+ ['data-status']: isActive ? 'active' : undefined
1441
+ };
1442
+ }
1443
+ const Link = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
1444
+ const linkProps = useLinkProps(props);
1445
+ return /*#__PURE__*/React__namespace.createElement("a", _extends({
1446
+ ref: ref
1447
+ }, linkProps, {
1448
+ children: typeof props.children === 'function' ? props.children({
1449
+ isActive: linkProps['data-status'] === 'active'
1450
+ }) : props.children
1451
+ }));
1452
+ });
1453
+
1454
+ // @ts-nocheck
1455
+
1456
+ // 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.
1457
+
1458
+ function encode(obj, pfx) {
1459
+ var k,
1460
+ i,
1461
+ tmp,
1462
+ str = '';
1463
+ for (k in obj) {
1464
+ if ((tmp = obj[k]) !== void 0) {
1465
+ if (Array.isArray(tmp)) {
1466
+ for (i = 0; i < tmp.length; i++) {
1467
+ str && (str += '&');
1468
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1469
+ }
1470
+ } else {
1471
+ str && (str += '&');
1472
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
1473
+ }
1474
+ }
1475
+ }
1476
+ return (pfx || '') + str;
1477
+ }
1478
+ function toValue(mix) {
1479
+ if (!mix) return '';
1480
+ var str = decodeURIComponent(mix);
1481
+ if (str === 'false') return false;
1482
+ if (str === 'true') return true;
1483
+ return +str * 0 === 0 && +str + '' === str ? +str : str;
1484
+ }
1485
+ function decode(str) {
1486
+ var tmp,
1487
+ k,
1488
+ out = {},
1489
+ arr = str.split('&');
1490
+ while (tmp = arr.shift()) {
1491
+ tmp = tmp.split('=');
1492
+ k = tmp.shift();
1493
+ if (out[k] !== void 0) {
1494
+ out[k] = [].concat(out[k], toValue(tmp.shift()));
1495
+ } else {
1496
+ out[k] = toValue(tmp.shift());
1497
+ }
1498
+ }
1499
+ return out;
1500
+ }
1501
+
1502
+ // Detect if we're in the DOM
1503
+
1504
+ function redirect(opts) {
1505
+ opts.isRedirect = true;
1506
+ return opts;
1507
+ }
1508
+ function isRedirect(obj) {
1509
+ return !!obj?.isRedirect;
1510
+ }
1511
+
1512
+ const defaultParseSearch = parseSearchWith(JSON.parse);
1513
+ const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
1514
+ function parseSearchWith(parser) {
1515
+ return searchStr => {
1516
+ if (searchStr.substring(0, 1) === '?') {
1517
+ searchStr = searchStr.substring(1);
1518
+ }
1519
+ let query = decode(searchStr);
1520
+
1521
+ // Try to parse any query params that might be json
1522
+ for (let key in query) {
1523
+ const value = query[key];
1524
+ if (typeof value === 'string') {
1525
+ try {
1526
+ query[key] = parser(value);
1527
+ } catch (err) {
1528
+ //
1529
+ }
1530
+ }
1531
+ }
1532
+ return query;
1533
+ };
1534
+ }
1535
+ function stringifySearchWith(stringify, parser) {
1536
+ function stringifyValue(val) {
1537
+ if (typeof val === 'object' && val !== null) {
1538
+ try {
1539
+ return stringify(val);
1540
+ } catch (err) {
1541
+ // silent
1542
+ }
1543
+ } else if (typeof val === 'string' && typeof parser === 'function') {
1544
+ try {
1545
+ // Check if it's a valid parseable string.
1546
+ // If it is, then stringify it again.
1547
+ parser(val);
1548
+ return stringify(val);
1549
+ } catch (err) {
1550
+ // silent
1551
+ }
1552
+ }
1553
+ return val;
1554
+ }
1555
+ return search => {
1556
+ search = {
1557
+ ...search
1558
+ };
1559
+ if (search) {
1560
+ Object.keys(search).forEach(key => {
1561
+ const val = search[key];
1562
+ if (typeof val === 'undefined' || val === undefined) {
1563
+ delete search[key];
1564
+ } else {
1565
+ search[key] = stringifyValue(val);
1566
+ }
1567
+ });
1568
+ }
1569
+ const searchStr = encode(search).toString();
1570
+ return searchStr ? `?${searchStr}` : '';
1571
+ };
1572
+ }
1573
+
1574
+ //
1575
+
1576
+ const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1577
+ const preloadWarning = 'Error preloading route! ☝️';
1578
+ class Router {
1579
+ // Option-independent properties
1580
+ tempLocationKey = `${Math.round(Math.random() * 10000000)}`;
1581
+ resetNextScroll = true;
1582
+ navigateTimeout = null;
1583
+ latestLoadPromise = Promise.resolve();
1584
+ subscribers = new Set();
1585
+ pendingMatches = [];
1586
+ injectedHtml = [];
1587
+
1588
+ // Must build in constructor
1589
+
1590
+ constructor(options) {
1591
+ this.updateOptions({
1592
+ defaultPreloadDelay: 50,
1593
+ context: undefined,
1594
+ ...options,
1595
+ stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
1596
+ parseSearch: options?.parseSearch ?? defaultParseSearch
1597
+ });
1598
+ }
1599
+ startReactTransition = () => {
1600
+ warning(false, 'startReactTransition implementation is missing. If you see this, please file an issue.');
1601
+ };
1602
+ setState = () => {
1603
+ warning(false, 'setState implementation is missing. If you see this, please file an issue.');
1604
+ };
1605
+ updateOptions = newOptions => {
1606
+ this.options;
1607
+ this.options = {
1608
+ ...this.options,
1609
+ ...newOptions
1610
+ };
1611
+ this.basepath = `/${trimPath(newOptions.basepath ?? '') ?? ''}`;
1612
+ if (!this.history || this.options.history && this.options.history !== this.history) {
1613
+ this.history = this.options.history ?? createBrowserHistory();
1614
+ this.latestLocation = this.parseLocation();
1615
+ }
1616
+ if (this.options.routeTree !== this.routeTree) {
1617
+ this.routeTree = this.options.routeTree;
1618
+ this.buildRouteTree();
1619
+ }
1620
+ if (!this.state) {
1621
+ this.state = getInitialRouterState(this.latestLocation);
1622
+ }
1623
+ };
1624
+ buildRouteTree = () => {
1625
+ this.routesById = {};
1626
+ this.routesByPath = {};
1627
+ const recurseRoutes = childRoutes => {
1628
+ childRoutes.forEach((childRoute, i) => {
1629
+ // if (typeof childRoute === 'function') {
1630
+ // childRoute = (childRoute as any)()
1631
+ // }
1632
+ childRoute.init({
1633
+ originalIndex: i
1634
+ });
1635
+ const existingRoute = this.routesById[childRoute.id];
1636
+ invariant(!existingRoute, `Duplicate routes found with id: ${String(childRoute.id)}`);
1637
+ this.routesById[childRoute.id] = childRoute;
1638
+ if (!childRoute.isRoot && childRoute.path) {
1639
+ const trimmedFullPath = trimPathRight(childRoute.fullPath);
1640
+ if (!this.routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith('/')) {
1641
+ this.routesByPath[trimmedFullPath] = childRoute;
1642
+ }
1643
+ }
1644
+ const children = childRoute.children;
1645
+ if (children?.length) {
1646
+ recurseRoutes(children);
1647
+ }
1648
+ });
1649
+ };
1650
+ recurseRoutes([this.routeTree]);
1651
+ this.flatRoutes = Object.values(this.routesByPath).map((d, i) => {
1652
+ const trimmed = trimPath(d.fullPath);
1653
+ const parsed = parsePathname(trimmed);
1654
+ while (parsed.length > 1 && parsed[0]?.value === '/') {
1655
+ parsed.shift();
1656
+ }
1657
+ const score = parsed.map(d => {
1658
+ if (d.type === 'param') {
1659
+ return 0.5;
1660
+ }
1661
+ if (d.type === 'wildcard') {
1662
+ return 0.25;
1663
+ }
1664
+ return 1;
1665
+ });
1666
+ return {
1667
+ child: d,
1668
+ trimmed,
1669
+ parsed,
1670
+ index: i,
1671
+ score
1672
+ };
1673
+ }).sort((a, b) => {
1674
+ let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
1675
+ if (isIndex !== 0) return isIndex;
1676
+ const length = Math.min(a.score.length, b.score.length);
1677
+
1678
+ // Sort by length of score
1679
+ if (a.score.length !== b.score.length) {
1680
+ return b.score.length - a.score.length;
1681
+ }
1682
+
1683
+ // Sort by min available score
1684
+ for (let i = 0; i < length; i++) {
1685
+ if (a.score[i] !== b.score[i]) {
1686
+ return b.score[i] - a.score[i];
1687
+ }
1688
+ }
1689
+
1690
+ // Sort by min available parsed value
1691
+ for (let i = 0; i < length; i++) {
1692
+ if (a.parsed[i].value !== b.parsed[i].value) {
1693
+ return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
1694
+ }
1695
+ }
1696
+
1697
+ // Sort by length of trimmed full path
1698
+ if (a.trimmed !== b.trimmed) {
1699
+ return a.trimmed > b.trimmed ? 1 : -1;
1700
+ }
1701
+
1702
+ // Sort by original index
1703
+ return a.index - b.index;
1704
+ }).map((d, i) => {
1705
+ d.child.rank = i;
1706
+ return d.child;
1707
+ });
1708
+ };
1709
+ subscribe = (eventType, fn) => {
1710
+ const listener = {
1711
+ eventType,
1712
+ fn
1713
+ };
1714
+ this.subscribers.add(listener);
1715
+ return () => {
1716
+ this.subscribers.delete(listener);
1717
+ };
1718
+ };
1719
+ emit = routerEvent => {
1720
+ this.subscribers.forEach(listener => {
1721
+ if (listener.eventType === routerEvent.type) {
1722
+ listener.fn(routerEvent);
1723
+ }
1724
+ });
1725
+ };
1726
+ checkLatest = promise => {
1727
+ return this.latestLoadPromise !== promise ? this.latestLoadPromise : undefined;
1728
+ };
1729
+ parseLocation = previousLocation => {
1730
+ const parse = ({
1731
+ pathname,
1732
+ search,
1733
+ hash,
1734
+ state
1735
+ }) => {
1736
+ const parsedSearch = this.options.parseSearch(search);
1737
+ return {
1738
+ pathname: pathname,
1739
+ searchStr: search,
1740
+ search: replaceEqualDeep(previousLocation?.search, parsedSearch),
1741
+ hash: hash.split('#').reverse()[0] ?? '',
1422
1742
  href: `${pathname}${search}${hash}`,
1423
1743
  state: replaceEqualDeep(previousLocation?.state, state)
1424
1744
  };
1425
1745
  };
1426
- const location = parse(history.location);
1746
+ const location = parse(this.history.location);
1427
1747
  let {
1428
1748
  __tempLocation,
1429
1749
  __tempKey
1430
1750
  } = location.state;
1431
- if (__tempLocation && (!__tempKey || __tempKey === tempLocationKeyRef.current)) {
1751
+ if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
1432
1752
  // Sync up the location keys
1433
1753
  const parsedTempLocation = parse(__tempLocation);
1434
1754
  parsedTempLocation.state.key = location.state.key;
@@ -1439,126 +1759,19 @@
1439
1759
  };
1440
1760
  }
1441
1761
  return location;
1442
- });
1443
- const latestLocationRef = React__namespace.useRef(parseLocation());
1444
- const [preState, setState] = React__namespace.useState(() => getInitialRouterState(latestLocationRef.current));
1445
- const [isTransitioning, startReactTransition] = React__namespace.useTransition();
1446
- const pendingMatchesRef = React__namespace.useRef([]);
1447
- const state = React__namespace.useMemo(() => ({
1448
- ...preState,
1449
- status: isTransitioning ? 'pending' : 'idle',
1450
- location: isTransitioning ? latestLocationRef.current : preState.location,
1451
- pendingMatches: pendingMatchesRef.current
1452
- }), [preState, isTransitioning]);
1453
- React__namespace.useLayoutEffect(() => {
1454
- if (!isTransitioning && state.resolvedLocation !== state.location) {
1455
- router.emit({
1456
- type: 'onResolved',
1457
- fromLocation: state.resolvedLocation,
1458
- toLocation: state.location,
1459
- pathChanged: state.location.href !== state.resolvedLocation?.href
1460
- });
1461
- pendingMatchesRef.current = [];
1462
- setState(s => ({
1463
- ...s,
1464
- resolvedLocation: s.location
1465
- }));
1466
- }
1467
- });
1468
- const basepath = `/${trimPath(options.basepath ?? '') ?? ''}`;
1469
- const resolvePathWithBase = useStableCallback((from, path) => {
1470
- return resolvePath(basepath, from, cleanPath(path));
1471
- });
1472
- const [routesById, routesByPath] = React__namespace.useMemo(() => {
1473
- const routesById = {};
1474
- const routesByPath = {};
1475
- const recurseRoutes = routes => {
1476
- routes.forEach((route, i) => {
1477
- route.init({
1478
- originalIndex: i
1479
- });
1480
- const existingRoute = routesById[route.id];
1481
- invariant(!existingRoute, `Duplicate routes found with id: ${String(route.id)}`);
1482
- routesById[route.id] = route;
1483
- if (!route.isRoot && route.path) {
1484
- const trimmedFullPath = trimPathRight(route.fullPath);
1485
- if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {
1486
- routesByPath[trimmedFullPath] = route;
1487
- }
1488
- }
1489
- const children = route.children;
1490
- if (children?.length) {
1491
- recurseRoutes(children);
1492
- }
1493
- });
1494
- };
1495
- recurseRoutes([router.routeTree]);
1496
- return [routesById, routesByPath];
1497
- }, []);
1498
- const looseRoutesById = routesById;
1499
- const flatRoutes = React__namespace.useMemo(() => Object.values(routesByPath).map((d, i) => {
1500
- const trimmed = trimPath(d.fullPath);
1501
- const parsed = parsePathname(trimmed);
1502
- while (parsed.length > 1 && parsed[0]?.value === '/') {
1503
- parsed.shift();
1504
- }
1505
- const score = parsed.map(d => {
1506
- if (d.type === 'param') {
1507
- return 0.5;
1508
- }
1509
- if (d.type === 'wildcard') {
1510
- return 0.25;
1511
- }
1512
- return 1;
1513
- });
1514
- return {
1515
- child: d,
1516
- trimmed,
1517
- parsed,
1518
- index: i,
1519
- score
1520
- };
1521
- }).sort((a, b) => {
1522
- let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
1523
- if (isIndex !== 0) return isIndex;
1524
- const length = Math.min(a.score.length, b.score.length);
1525
-
1526
- // Sort by length of score
1527
- if (a.score.length !== b.score.length) {
1528
- return b.score.length - a.score.length;
1529
- }
1530
-
1531
- // Sort by min available score
1532
- for (let i = 0; i < length; i++) {
1533
- if (a.score[i] !== b.score[i]) {
1534
- return b.score[i] - a.score[i];
1535
- }
1536
- }
1537
-
1538
- // Sort by min available parsed value
1539
- for (let i = 0; i < length; i++) {
1540
- if (a.parsed[i].value !== b.parsed[i].value) {
1541
- return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
1542
- }
1543
- }
1544
-
1545
- // Sort by length of trimmed full path
1546
- if (a.trimmed !== b.trimmed) {
1547
- return a.trimmed > b.trimmed ? 1 : -1;
1548
- }
1549
-
1550
- // Sort by original index
1551
- return a.index - b.index;
1552
- }).map((d, i) => {
1553
- d.child.rank = i;
1554
- return d.child;
1555
- }), [routesByPath]);
1556
- const matchRoutes = useStableCallback((pathname, locationSearch, opts) => {
1762
+ };
1763
+ resolvePathWithBase = (from, path) => {
1764
+ return resolvePath(this.basepath, from, cleanPath(path));
1765
+ };
1766
+ get looseRoutesById() {
1767
+ return this.routesById;
1768
+ }
1769
+ matchRoutes = (pathname, locationSearch, opts) => {
1557
1770
  let routeParams = {};
1558
- let foundRoute = flatRoutes.find(route => {
1559
- const matchedParams = matchPathname(basepath, trimPathRight(pathname), {
1771
+ let foundRoute = this.flatRoutes.find(route => {
1772
+ const matchedParams = matchPathname(this.basepath, trimPathRight(pathname), {
1560
1773
  to: route.fullPath,
1561
- caseSensitive: route.options.caseSensitive ?? options.caseSensitive,
1774
+ caseSensitive: route.options.caseSensitive ?? this.options.caseSensitive,
1562
1775
  fuzzy: false
1563
1776
  });
1564
1777
  if (matchedParams) {
@@ -1567,7 +1780,7 @@
1567
1780
  }
1568
1781
  return false;
1569
1782
  });
1570
- let routeCursor = foundRoute || routesById['__root__'];
1783
+ let routeCursor = foundRoute || this.routesById['__root__'];
1571
1784
  let matchedRoutes = [routeCursor];
1572
1785
  // let includingLayouts = true
1573
1786
  while (routeCursor?.parentRoute) {
@@ -1604,8 +1817,8 @@
1604
1817
  // Waste not, want not. If we already have a match for this route,
1605
1818
  // reuse it. This is important for layout routes, which might stick
1606
1819
  // around between navigation actions that only change leaf routes.
1607
- const existingMatch = getRouteMatch(state, matchId);
1608
- const cause = state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
1820
+ const existingMatch = getRouteMatch(this.state, matchId);
1821
+ const cause = this.state.matches.find(d => d.id === matchId) ? 'stay' : 'enter';
1609
1822
  if (existingMatch) {
1610
1823
  return {
1611
1824
  ...existingMatch,
@@ -1619,7 +1832,7 @@
1619
1832
  id: matchId,
1620
1833
  routeId: route.id,
1621
1834
  params: routeParams,
1622
- pathname: joinPaths([basepath, interpolatedPath]),
1835
+ pathname: joinPaths([this.basepath, interpolatedPath]),
1623
1836
  updatedAt: Date.now(),
1624
1837
  routeSearch: {},
1625
1838
  search: {},
@@ -1644,7 +1857,7 @@
1644
1857
  // so that we can use the parent match's search params and context
1645
1858
  matches.forEach((match, i) => {
1646
1859
  const parentMatch = matches[i - 1];
1647
- const route = looseRoutesById[match.routeId];
1860
+ const route = this.looseRoutesById[match.routeId];
1648
1861
  const searchInfo = (() => {
1649
1862
  // Validate the search params and stabilize them
1650
1863
  const parentSearchInfo = {
@@ -1678,28 +1891,28 @@
1678
1891
  Object.assign(match, searchInfo);
1679
1892
  });
1680
1893
  return matches;
1681
- });
1682
- const cancelMatch = useStableCallback(id => {
1683
- getRouteMatch(state, id)?.abortController?.abort();
1684
- });
1685
- const cancelMatches = useStableCallback(state => {
1686
- state.matches.forEach(match => {
1687
- cancelMatch(match.id);
1894
+ };
1895
+ cancelMatch = id => {
1896
+ getRouteMatch(this.state, id)?.abortController?.abort();
1897
+ };
1898
+ cancelMatches = () => {
1899
+ this.state.matches.forEach(match => {
1900
+ this.cancelMatch(match.id);
1688
1901
  });
1689
- });
1690
- const buildLocation = useStableCallback(opts => {
1902
+ };
1903
+ buildLocation = opts => {
1691
1904
  const build = (dest = {}, matches) => {
1692
- const from = latestLocationRef.current;
1905
+ const from = this.latestLocation;
1693
1906
  const fromPathname = dest.from ?? from.pathname;
1694
- let pathname = resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
1695
- const fromMatches = matchRoutes(fromPathname, from.search);
1907
+ let pathname = this.resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
1908
+ const fromMatches = this.matchRoutes(fromPathname, from.search);
1696
1909
  const stayingMatches = matches?.filter(d => fromMatches?.find(e => e.routeId === d.routeId));
1697
1910
  const prevParams = {
1698
1911
  ...last(fromMatches)?.params
1699
1912
  };
1700
1913
  let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1701
1914
  if (nextParams) {
1702
- matches?.map(d => looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
1915
+ matches?.map(d => this.looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
1703
1916
  nextParams = {
1704
1917
  ...nextParams,
1705
1918
  ...fn(nextParams)
@@ -1707,8 +1920,8 @@
1707
1920
  });
1708
1921
  }
1709
1922
  pathname = interpolatePath(pathname, nextParams ?? {});
1710
- const preSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
1711
- const postSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
1923
+ const preSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
1924
+ const postSearchFilters = stayingMatches?.map(match => this.looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
1712
1925
 
1713
1926
  // Pre filters first
1714
1927
  const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
@@ -1722,7 +1935,7 @@
1722
1935
  // Then post filters
1723
1936
  const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1724
1937
  const search = replaceEqualDeep(from.search, postFilteredSearch);
1725
- const searchStr = options.stringifySearch(search);
1938
+ const searchStr = this.options.stringifySearch(search);
1726
1939
  const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
1727
1940
  const hashStr = hash ? `#${hash}` : '';
1728
1941
  let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
@@ -1733,7 +1946,7 @@
1733
1946
  searchStr,
1734
1947
  state: nextState,
1735
1948
  hash,
1736
- href: history.createHref(`${pathname}${searchStr}${hashStr}`),
1949
+ href: this.history.createHref(`${pathname}${searchStr}${hashStr}`),
1737
1950
  unmaskOnReload: dest.unmaskOnReload
1738
1951
  };
1739
1952
  };
@@ -1742,8 +1955,8 @@
1742
1955
  let maskedNext = maskedDest ? build(maskedDest) : undefined;
1743
1956
  if (!maskedNext) {
1744
1957
  let params = {};
1745
- let foundMask = options.routeMasks?.find(d => {
1746
- const match = matchPathname(basepath, next.pathname, {
1958
+ let foundMask = this.options.routeMasks?.find(d => {
1959
+ const match = matchPathname(this.basepath, next.pathname, {
1747
1960
  to: d.from,
1748
1961
  caseSensitive: false,
1749
1962
  fuzzy: false
@@ -1763,8 +1976,8 @@
1763
1976
  maskedNext = build(maskedDest);
1764
1977
  }
1765
1978
  }
1766
- const nextMatches = matchRoutes(next.pathname, next.search);
1767
- const maskedMatches = maskedNext ? matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
1979
+ const nextMatches = this.matchRoutes(next.pathname, next.search);
1980
+ const maskedMatches = maskedNext ? this.matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
1768
1981
  const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
1769
1982
  const final = build(dest, nextMatches);
1770
1983
  if (maskedFinal) {
@@ -1779,13 +1992,13 @@
1779
1992
  });
1780
1993
  }
1781
1994
  return buildWithMatches(opts);
1782
- });
1783
- const commitLocation = useStableCallback(async ({
1995
+ };
1996
+ commitLocation = async ({
1784
1997
  startTransition,
1785
1998
  ...next
1786
1999
  }) => {
1787
- if (navigateTimeoutRef.current) clearTimeout(navigateTimeoutRef.current);
1788
- const isSameUrl = latestLocationRef.current.href === next.href;
2000
+ if (this.navigateTimeout) clearTimeout(this.navigateTimeout);
2001
+ const isSameUrl = this.latestLocation.href === next.href;
1789
2002
 
1790
2003
  // If the next urls are the same and we're not replacing,
1791
2004
  // do nothing
@@ -1812,37 +2025,37 @@
1812
2025
  }
1813
2026
  }
1814
2027
  };
1815
- if (nextHistory.unmaskOnReload ?? options.unmaskOnReload ?? false) {
1816
- nextHistory.state.__tempKey = tempLocationKeyRef.current;
2028
+ if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
2029
+ nextHistory.state.__tempKey = this.tempLocationKey;
1817
2030
  }
1818
2031
  }
1819
2032
  const apply = () => {
1820
- history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
2033
+ this.history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
1821
2034
  };
1822
2035
  if (startTransition ?? true) {
1823
- startReactTransition(apply);
2036
+ this.startReactTransition(apply);
1824
2037
  } else {
1825
2038
  apply();
1826
2039
  }
1827
2040
  }
1828
- resetNextScrollRef.current = next.resetScroll ?? true;
1829
- return latestLoadPromiseRef.current;
1830
- });
1831
- const buildAndCommitLocation = useStableCallback(({
2041
+ this.resetNextScroll = next.resetScroll ?? true;
2042
+ return this.latestLoadPromise;
2043
+ };
2044
+ buildAndCommitLocation = ({
1832
2045
  replace,
1833
2046
  resetScroll,
1834
2047
  startTransition,
1835
2048
  ...rest
1836
2049
  } = {}) => {
1837
- const location = buildLocation(rest);
1838
- return commitLocation({
2050
+ const location = this.buildLocation(rest);
2051
+ return this.commitLocation({
1839
2052
  ...location,
1840
2053
  startTransition,
1841
2054
  replace,
1842
2055
  resetScroll
1843
2056
  });
1844
- });
1845
- const navigate = useStableCallback(({
2057
+ };
2058
+ navigate = ({
1846
2059
  from,
1847
2060
  to = '',
1848
2061
  ...rest
@@ -1860,13 +2073,13 @@
1860
2073
  isExternal = true;
1861
2074
  } catch (e) {}
1862
2075
  invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
1863
- return buildAndCommitLocation({
2076
+ return this.buildAndCommitLocation({
1864
2077
  ...rest,
1865
2078
  from: fromString,
1866
2079
  to: toString
1867
2080
  });
1868
- });
1869
- const loadMatches = useStableCallback(async ({
2081
+ };
2082
+ loadMatches = async ({
1870
2083
  checkLatest,
1871
2084
  matches,
1872
2085
  preload
@@ -1878,7 +2091,7 @@
1878
2091
  try {
1879
2092
  for (let [index, match] of matches.entries()) {
1880
2093
  const parentMatch = matches[index - 1];
1881
- const route = looseRoutesById[match.routeId];
2094
+ const route = this.looseRoutesById[match.routeId];
1882
2095
  const handleError = (err, code) => {
1883
2096
  err.routerCode = code;
1884
2097
  firstBadMatchIndex = firstBadMatchIndex ?? index;
@@ -1907,19 +2120,20 @@
1907
2120
  if (match.searchError) {
1908
2121
  handleError(match.searchError, 'VALIDATE_SEARCH');
1909
2122
  }
1910
- const parentContext = parentMatch?.context ?? options.context ?? {};
2123
+ const parentContext = parentMatch?.context ?? this.options.context ?? {};
1911
2124
  const beforeLoadContext = (await route.options.beforeLoad?.({
1912
2125
  search: match.search,
1913
2126
  abortController: match.abortController,
1914
2127
  params: match.params,
1915
2128
  preload: !!preload,
1916
2129
  context: parentContext,
1917
- location: state.location,
1918
- navigate: opts => navigate({
2130
+ location: this.state.location,
2131
+ // TOOD: just expose state and router, etc
2132
+ navigate: opts => this.navigate({
1919
2133
  ...opts,
1920
2134
  from: match.pathname
1921
2135
  }),
1922
- buildLocation,
2136
+ buildLocation: this.buildLocation,
1923
2137
  cause: match.cause
1924
2138
  })) ?? {};
1925
2139
  const context = {
@@ -1937,7 +2151,7 @@
1937
2151
  }
1938
2152
  } catch (err) {
1939
2153
  if (isRedirect(err)) {
1940
- if (!preload) navigate(err);
2154
+ if (!preload) this.navigate(err);
1941
2155
  return matches;
1942
2156
  }
1943
2157
  throw err;
@@ -1947,11 +2161,11 @@
1947
2161
  validResolvedMatches.forEach((match, index) => {
1948
2162
  matchPromises.push((async () => {
1949
2163
  const parentMatchPromise = matchPromises[index - 1];
1950
- const route = looseRoutesById[match.routeId];
2164
+ const route = this.looseRoutesById[match.routeId];
1951
2165
  const handleIfRedirect = err => {
1952
2166
  if (isRedirect(err)) {
1953
2167
  if (!preload) {
1954
- navigate(err);
2168
+ this.navigate(err);
1955
2169
  }
1956
2170
  return true;
1957
2171
  }
@@ -1964,7 +2178,7 @@
1964
2178
  invalid: false
1965
2179
  };
1966
2180
  if (match.isFetching) {
1967
- loadPromise = getRouteMatch(state, match.id)?.loadPromise;
2181
+ loadPromise = getRouteMatch(this.state, match.id)?.loadPromise;
1968
2182
  } else {
1969
2183
  const loaderContext = {
1970
2184
  params: match.params,
@@ -1973,8 +2187,8 @@
1973
2187
  parentMatchPromise,
1974
2188
  abortController: match.abortController,
1975
2189
  context: match.context,
1976
- location: state.location,
1977
- navigate: opts => navigate({
2190
+ location: this.state.location,
2191
+ navigate: opts => this.navigate({
1978
2192
  ...opts,
1979
2193
  from: match.pathname
1980
2194
  }),
@@ -2022,7 +2236,7 @@
2022
2236
  loadPromise
2023
2237
  };
2024
2238
  if (!preload) {
2025
- setState(s => ({
2239
+ this.setState(s => ({
2026
2240
  ...s,
2027
2241
  matches: s.matches.map(d => d.id === match.id ? match : d)
2028
2242
  }));
@@ -2057,7 +2271,7 @@
2057
2271
  };
2058
2272
  }
2059
2273
  if (!preload) {
2060
- setState(s => ({
2274
+ this.setState(s => ({
2061
2275
  ...s,
2062
2276
  matches: s.matches.map(d => d.id === match.id ? match : d)
2063
2277
  }));
@@ -2066,17 +2280,17 @@
2066
2280
  });
2067
2281
  await Promise.all(matchPromises);
2068
2282
  return matches;
2069
- });
2070
- const load = useStableCallback(async () => {
2283
+ };
2284
+ load = async () => {
2071
2285
  const promise = new Promise(async (resolve, reject) => {
2072
- const next = latestLocationRef.current;
2073
- const prevLocation = state.resolvedLocation;
2286
+ const next = this.latestLocation;
2287
+ const prevLocation = this.state.resolvedLocation;
2074
2288
  const pathDidChange = prevLocation.href !== next.href;
2075
2289
  let latestPromise;
2076
2290
 
2077
2291
  // Cancel any pending matches
2078
- cancelMatches(state);
2079
- router.emit({
2292
+ this.cancelMatches();
2293
+ this.emit({
2080
2294
  type: 'onBeforeLoad',
2081
2295
  fromLocation: prevLocation,
2082
2296
  toLocation: next,
@@ -2084,14 +2298,14 @@
2084
2298
  });
2085
2299
 
2086
2300
  // Match the routes
2087
- let matches = matchRoutes(next.pathname, next.search, {
2301
+ let matches = this.matchRoutes(next.pathname, next.search, {
2088
2302
  debug: true
2089
2303
  });
2090
- pendingMatchesRef.current = matches;
2091
- const previousMatches = state.matches;
2304
+ this.pendingMatches = matches;
2305
+ const previousMatches = this.state.matches;
2092
2306
 
2093
2307
  // Ingest the new matches
2094
- setState(s => ({
2308
+ this.setState(s => ({
2095
2309
  ...s,
2096
2310
  status: 'pending',
2097
2311
  location: next,
@@ -2100,9 +2314,9 @@
2100
2314
  try {
2101
2315
  try {
2102
2316
  // Load the matches
2103
- await loadMatches({
2317
+ await this.loadMatches({
2104
2318
  matches,
2105
- checkLatest: () => checkLatest(promise)
2319
+ checkLatest: () => this.checkLatest(promise)
2106
2320
  });
2107
2321
  } catch (err) {
2108
2322
  // swallow this error, since we'll display the
@@ -2110,12 +2324,12 @@
2110
2324
  }
2111
2325
 
2112
2326
  // Only apply the latest transition
2113
- if (latestPromise = checkLatest(promise)) {
2327
+ if (latestPromise = this.checkLatest(promise)) {
2114
2328
  return latestPromise;
2115
2329
  }
2116
- const exitingMatchIds = previousMatches.filter(id => !pendingMatchesRef.current.includes(id));
2117
- const enteringMatchIds = pendingMatchesRef.current.filter(id => !previousMatches.includes(id));
2118
- const stayingMatchIds = previousMatches.filter(id => pendingMatchesRef.current.includes(id))
2330
+ const exitingMatchIds = previousMatches.filter(id => !this.pendingMatches.includes(id));
2331
+ const enteringMatchIds = this.pendingMatches.filter(id => !previousMatches.includes(id));
2332
+ const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id))
2119
2333
 
2120
2334
  // setState((s) => ({
2121
2335
  // ...s,
@@ -2127,10 +2341,10 @@
2127
2341
  ;
2128
2342
  [[exitingMatchIds, 'onLeave'], [enteringMatchIds, 'onEnter'], [stayingMatchIds, 'onTransition']].forEach(([matches, hook]) => {
2129
2343
  matches.forEach(match => {
2130
- looseRoutesById[match.routeId].options[hook]?.(match);
2344
+ this.looseRoutesById[match.routeId].options[hook]?.(match);
2131
2345
  });
2132
2346
  });
2133
- router.emit({
2347
+ this.emit({
2134
2348
  type: 'onLoad',
2135
2349
  fromLocation: prevLocation,
2136
2350
  toLocation: next,
@@ -2139,28 +2353,28 @@
2139
2353
  resolve();
2140
2354
  } catch (err) {
2141
2355
  // Only apply the latest transition
2142
- if (latestPromise = checkLatest(promise)) {
2356
+ if (latestPromise = this.checkLatest(promise)) {
2143
2357
  return latestPromise;
2144
2358
  }
2145
2359
  reject(err);
2146
2360
  }
2147
2361
  });
2148
- latestLoadPromiseRef.current = promise;
2149
- return latestLoadPromiseRef.current;
2150
- });
2151
- const preloadRoute = useStableCallback(async (navigateOpts = state.location) => {
2152
- let next = buildLocation(navigateOpts);
2153
- let matches = matchRoutes(next.pathname, next.search, {
2362
+ this.latestLoadPromise = promise;
2363
+ return this.latestLoadPromise;
2364
+ };
2365
+ preloadRoute = async (navigateOpts = this.state.location) => {
2366
+ let next = this.buildLocation(navigateOpts);
2367
+ let matches = this.matchRoutes(next.pathname, next.search, {
2154
2368
  throwOnError: true
2155
2369
  });
2156
- await loadMatches({
2370
+ await this.loadMatches({
2157
2371
  matches,
2158
2372
  preload: true,
2159
2373
  checkLatest: () => undefined
2160
2374
  });
2161
2375
  return [last(matches), matches];
2162
- });
2163
- const buildLink = useStableCallback(dest => {
2376
+ };
2377
+ buildLink = dest => {
2164
2378
  // If this link simply reloads the current route,
2165
2379
  // make sure it has a new key so it will trigger a data refresh
2166
2380
 
@@ -2186,18 +2400,18 @@
2186
2400
  };
2187
2401
  } catch (e) {}
2188
2402
  const nextOpts = dest;
2189
- const next = buildLocation(nextOpts);
2190
- const preload = userPreload ?? options.defaultPreload;
2191
- const preloadDelay = userPreloadDelay ?? options.defaultPreloadDelay ?? 0;
2403
+ const next = this.buildLocation(nextOpts);
2404
+ const preload = userPreload ?? this.options.defaultPreload;
2405
+ const preloadDelay = userPreloadDelay ?? this.options.defaultPreloadDelay ?? 0;
2192
2406
 
2193
2407
  // Compare path/hash for matches
2194
- const currentPathSplit = latestLocationRef.current.pathname.split('/');
2408
+ const currentPathSplit = this.latestLocation.pathname.split('/');
2195
2409
  const nextPathSplit = next.pathname.split('/');
2196
2410
  const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2197
- // Combine the matches based on user options
2198
- const pathTest = activeOptions?.exact ? latestLocationRef.current.pathname === next.pathname : pathIsFuzzyEqual;
2199
- const hashTest = activeOptions?.includeHash ? latestLocationRef.current.hash === next.hash : true;
2200
- const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(latestLocationRef.current.search, next.search, true) : true;
2411
+ // Combine the matches based on user this.options
2412
+ const pathTest = activeOptions?.exact ? this.latestLocation.pathname === next.pathname : pathIsFuzzyEqual;
2413
+ const hashTest = activeOptions?.includeHash ? this.latestLocation.hash === next.hash : true;
2414
+ const searchTest = activeOptions?.includeSearch ?? true ? deepEqual(this.latestLocation.search, next.search, true) : true;
2201
2415
 
2202
2416
  // The final "active" test
2203
2417
  const isActive = pathTest && hashTest && searchTest;
@@ -2208,7 +2422,7 @@
2208
2422
  e.preventDefault();
2209
2423
 
2210
2424
  // All is well? Navigate!
2211
- commitLocation({
2425
+ this.commitLocation({
2212
2426
  ...next,
2213
2427
  replace,
2214
2428
  resetScroll,
@@ -2220,14 +2434,14 @@
2220
2434
  // The click handler
2221
2435
  const handleFocus = e => {
2222
2436
  if (preload) {
2223
- preloadRoute(nextOpts).catch(err => {
2437
+ this.preloadRoute(nextOpts).catch(err => {
2224
2438
  console.warn(err);
2225
2439
  console.warn(preloadWarning);
2226
2440
  });
2227
2441
  }
2228
2442
  };
2229
2443
  const handleTouchStart = e => {
2230
- preloadRoute(nextOpts).catch(err => {
2444
+ this.preloadRoute(nextOpts).catch(err => {
2231
2445
  console.warn(err);
2232
2446
  console.warn(preloadWarning);
2233
2447
  });
@@ -2240,7 +2454,7 @@
2240
2454
  }
2241
2455
  target.preloadTimeout = setTimeout(() => {
2242
2456
  target.preloadTimeout = null;
2243
- preloadRoute(nextOpts).catch(err => {
2457
+ this.preloadRoute(nextOpts).catch(err => {
2244
2458
  console.warn(err);
2245
2459
  console.warn(preloadWarning);
2246
2460
  });
@@ -2249,355 +2463,155 @@
2249
2463
  };
2250
2464
  const handleLeave = e => {
2251
2465
  const target = e.target || {};
2252
- if (target.preloadTimeout) {
2253
- clearTimeout(target.preloadTimeout);
2254
- target.preloadTimeout = null;
2255
- }
2256
- };
2257
- return {
2258
- type: 'internal',
2259
- next,
2260
- handleFocus,
2261
- handleClick,
2262
- handleEnter,
2263
- handleLeave,
2264
- handleTouchStart,
2265
- isActive,
2266
- disabled
2267
- };
2268
- });
2269
- React__namespace.useLayoutEffect(() => {
2270
- const unsub = history.subscribe(() => {
2271
- latestLocationRef.current = parseLocation(latestLocationRef.current);
2272
- if (state.location !== latestLocationRef.current) {
2273
- startReactTransition(() => {
2274
- try {
2275
- load();
2276
- } catch (err) {
2277
- console.error(err);
2278
- }
2279
- });
2280
- }
2281
- });
2282
- const nextLocation = buildLocation({
2283
- search: true,
2284
- params: true,
2285
- hash: true,
2286
- state: true
2287
- });
2288
- if (state.location.href !== nextLocation.href) {
2289
- commitLocation({
2290
- ...nextLocation,
2291
- replace: true
2292
- });
2293
- }
2294
- return () => {
2295
- unsub();
2296
- };
2297
- }, [history]);
2298
- const matchRoute = useStableCallback((location, opts) => {
2299
- location = {
2300
- ...location,
2301
- to: location.to ? resolvePathWithBase(location.from || '', location.to) : undefined
2302
- };
2303
- const next = buildLocation(location);
2304
- if (opts?.pending && state.status !== 'pending') {
2305
- return false;
2306
- }
2307
- const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
2308
-
2309
- // const baseLocation = state.resolvedLocation
2310
-
2311
- if (!baseLocation) {
2312
- return false;
2313
- }
2314
- const match = matchPathname(basepath, baseLocation.pathname, {
2315
- ...opts,
2316
- to: next.pathname
2317
- });
2318
- if (!match) {
2319
- return false;
2320
- }
2321
- if (match && (opts?.includeSearch ?? true)) {
2322
- return deepEqual(baseLocation.search, next.search, true) ? match : false;
2323
- }
2324
- return match;
2325
- });
2326
- const injectedHtmlRef = React__namespace.useRef([]);
2327
- const injectHtml = useStableCallback(async html => {
2328
- injectedHtmlRef.current.push(html);
2329
- });
2330
- const dehydrateData = useStableCallback((key, getData) => {
2331
- if (typeof document === 'undefined') {
2332
- const strKey = typeof key === 'string' ? key : JSON.stringify(key);
2333
- injectHtml(async () => {
2334
- const id = `__TSR_DEHYDRATED__${strKey}`;
2335
- const data = typeof getData === 'function' ? await getData() : getData;
2336
- return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
2337
- ;(() => {
2338
- var el = document.getElementById('${id}')
2339
- el.parentElement.removeChild(el)
2340
- })()
2341
- </script>`;
2342
- });
2343
- return () => hydrateData(key);
2344
- }
2345
- return () => undefined;
2346
- });
2347
- const hydrateData = useStableCallback(key => {
2348
- if (typeof document !== 'undefined') {
2349
- const strKey = typeof key === 'string' ? key : JSON.stringify(key);
2350
- return window[`__TSR_DEHYDRATED__${strKey}`];
2351
- }
2352
- return undefined;
2353
- });
2354
- React__namespace.useLayoutEffect(() => {
2355
- startReactTransition(() => {
2356
- try {
2357
- load();
2358
- } catch (err) {
2359
- console.error(err);
2360
- }
2361
- });
2362
- }, []);
2363
- const routerContextValue = {
2364
- routeTree: router.routeTree,
2365
- navigate,
2366
- buildLink,
2367
- state,
2368
- matchRoute,
2369
- routesById,
2370
- options,
2371
- history,
2372
- load,
2373
- buildLocation,
2374
- subscribe: router.subscribe,
2375
- resetNextScrollRef,
2376
- injectedHtmlRef,
2377
- injectHtml,
2378
- dehydrateData,
2379
- hydrateData
2380
- };
2381
- return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
2382
- value: routerContextValue
2383
- }, /*#__PURE__*/React__namespace.createElement(Matches, null));
2384
- }
2385
- function getRouteMatch(state, id) {
2386
- return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
2387
- }
2388
- function useRouterState(opts) {
2389
- const {
2390
- state
2391
- } = useRouter();
2392
- // return useStore(router.__store, opts?.select as any)
2393
- return opts?.select ? opts.select(state) : state;
2394
- }
2395
- function useRouter() {
2396
- const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
2397
- const value = React__namespace.useContext(resolvedContext);
2398
- warning(value, 'useRouter must be used inside a <RouterProvider> component!');
2399
- return value;
2400
- }
2401
-
2402
- function defer(_promise) {
2403
- const promise = _promise;
2404
- if (!promise.__deferredState) {
2405
- promise.__deferredState = {
2406
- uid: Math.random().toString(36).slice(2),
2407
- status: 'pending'
2408
- };
2409
- const state = promise.__deferredState;
2410
- promise.then(data => {
2411
- state.status = 'success';
2412
- state.data = data;
2413
- }).catch(error => {
2414
- state.status = 'error';
2415
- state.error = error;
2416
- });
2417
- }
2418
- return promise;
2419
- }
2420
- function isDehydratedDeferred(obj) {
2421
- return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
2422
- }
2423
-
2424
- function useAwaited({
2425
- promise
2426
- }) {
2427
- const router = useRouter();
2428
- let state = promise.__deferredState;
2429
- const key = `__TSR__DEFERRED__${state.uid}`;
2430
- if (isDehydratedDeferred(promise)) {
2431
- state = router.hydrateData(key);
2432
- promise = Promise.resolve(state.data);
2433
- promise.__deferredState = state;
2434
- }
2435
- if (state.status === 'pending') {
2436
- throw promise;
2437
- }
2438
- if (state.status === 'error') {
2439
- throw state.error;
2440
- }
2441
- router.dehydrateData(key, state);
2442
- return [state.data];
2443
- }
2444
- function Await(props) {
2445
- const awaited = useAwaited(props);
2446
- return props.children(...awaited);
2447
- }
2448
-
2449
- class FileRoute {
2450
- constructor(path) {
2451
- this.path = path;
2452
- }
2453
- createRoute = options => {
2454
- const route = new Route(options);
2455
- route.isRoot = false;
2456
- return route;
2466
+ if (target.preloadTimeout) {
2467
+ clearTimeout(target.preloadTimeout);
2468
+ target.preloadTimeout = null;
2469
+ }
2470
+ };
2471
+ return {
2472
+ type: 'internal',
2473
+ next,
2474
+ handleFocus,
2475
+ handleClick,
2476
+ handleEnter,
2477
+ handleLeave,
2478
+ handleTouchStart,
2479
+ isActive,
2480
+ disabled
2481
+ };
2457
2482
  };
2458
- }
2483
+ matchRoute = (location, opts) => {
2484
+ location = {
2485
+ ...location,
2486
+ to: location.to ? this.resolvePathWithBase(location.from || '', location.to) : undefined
2487
+ };
2488
+ const next = this.buildLocation(location);
2489
+ if (opts?.pending && this.state.status !== 'pending') {
2490
+ return false;
2491
+ }
2492
+ const baseLocation = opts?.pending ? this.latestLocation : this.state.resolvedLocation;
2459
2493
 
2460
- function lazyRouteComponent(importer, exportName) {
2461
- let loadPromise;
2462
- const load = () => {
2463
- if (!loadPromise) {
2464
- loadPromise = importer();
2494
+ // const baseLocation = state.resolvedLocation
2495
+
2496
+ if (!baseLocation) {
2497
+ return false;
2465
2498
  }
2466
- return loadPromise;
2499
+ const match = matchPathname(this.basepath, baseLocation.pathname, {
2500
+ ...opts,
2501
+ to: next.pathname
2502
+ });
2503
+ if (!match) {
2504
+ return false;
2505
+ }
2506
+ if (match && (opts?.includeSearch ?? true)) {
2507
+ return deepEqual(baseLocation.search, next.search, true) ? match : false;
2508
+ }
2509
+ return match;
2467
2510
  };
2468
- const lazyComp = /*#__PURE__*/React__namespace.lazy(async () => {
2469
- const moduleExports = await load();
2470
- const comp = moduleExports[exportName ?? 'default'];
2471
- return {
2472
- default: comp
2473
- };
2474
- });
2475
- lazyComp.preload = load;
2476
- return lazyComp;
2477
- }
2478
-
2479
- function _extends() {
2480
- _extends = Object.assign ? Object.assign.bind() : function (target) {
2481
- for (var i = 1; i < arguments.length; i++) {
2482
- var source = arguments[i];
2483
- for (var key in source) {
2484
- if (Object.prototype.hasOwnProperty.call(source, key)) {
2485
- target[key] = source[key];
2486
- }
2487
- }
2511
+ injectHtml = async html => {
2512
+ this.injectedHtml.push(html);
2513
+ };
2514
+ dehydrateData = (key, getData) => {
2515
+ if (typeof document === 'undefined') {
2516
+ const strKey = typeof key === 'string' ? key : JSON.stringify(key);
2517
+ this.injectHtml(async () => {
2518
+ const id = `__TSR_DEHYDRATED__${strKey}`;
2519
+ const data = typeof getData === 'function' ? await getData() : getData;
2520
+ return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
2521
+ ;(() => {
2522
+ var el = document.getElementById('${id}')
2523
+ el.parentElement.removeChild(el)
2524
+ })()
2525
+ </script>`;
2526
+ });
2527
+ return () => this.hydrateData(key);
2488
2528
  }
2489
- return target;
2529
+ return () => undefined;
2490
2530
  };
2491
- return _extends.apply(this, arguments);
2492
- }
2493
-
2494
- function useLinkProps(options) {
2495
- const {
2496
- buildLink
2497
- } = useRouter();
2498
- const match = useMatch({
2499
- strict: false
2500
- });
2501
- const {
2502
- // custom props
2503
- type,
2504
- children,
2505
- target,
2506
- activeProps = () => ({
2507
- className: 'active'
2508
- }),
2509
- inactiveProps = () => ({}),
2510
- activeOptions,
2511
- disabled,
2512
- hash,
2513
- search,
2514
- params,
2515
- to,
2516
- state,
2517
- mask,
2518
- preload,
2519
- preloadDelay,
2520
- replace,
2521
- startTransition,
2522
- resetScroll,
2523
- // element props
2524
- style,
2525
- className,
2526
- onClick,
2527
- onFocus,
2528
- onMouseEnter,
2529
- onMouseLeave,
2530
- onTouchStart,
2531
- ...rest
2532
- } = options;
2533
- const linkInfo = buildLink({
2534
- from: options.to ? match.pathname : undefined,
2535
- ...options
2536
- });
2537
- if (linkInfo.type === 'external') {
2538
- const {
2539
- href
2540
- } = linkInfo;
2541
- return {
2542
- href
2543
- };
2544
- }
2545
- const {
2546
- handleClick,
2547
- handleFocus,
2548
- handleEnter,
2549
- handleLeave,
2550
- handleTouchStart,
2551
- isActive,
2552
- next
2553
- } = linkInfo;
2554
- const composeHandlers = handlers => e => {
2555
- if (e.persist) e.persist();
2556
- handlers.filter(Boolean).forEach(handler => {
2557
- if (e.defaultPrevented) return;
2558
- handler(e);
2559
- });
2531
+ hydrateData = key => {
2532
+ if (typeof document !== 'undefined') {
2533
+ const strKey = typeof key === 'string' ? key : JSON.stringify(key);
2534
+ return window[`__TSR_DEHYDRATED__${strKey}`];
2535
+ }
2536
+ return undefined;
2560
2537
  };
2561
2538
 
2562
- // Get the active props
2563
- const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
2539
+ // dehydrate = (): DehydratedRouter => {
2540
+ // return {
2541
+ // state: {
2542
+ // dehydratedMatches: this.state.matches.map((d) =>
2543
+ // pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
2544
+ // ),
2545
+ // },
2546
+ // }
2547
+ // }
2564
2548
 
2565
- // Get the inactive props
2566
- const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
2567
- return {
2568
- ...resolvedActiveProps,
2569
- ...resolvedInactiveProps,
2570
- ...rest,
2571
- href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
2572
- onClick: composeHandlers([onClick, handleClick]),
2573
- onFocus: composeHandlers([onFocus, handleFocus]),
2574
- onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
2575
- onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
2576
- onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
2577
- target,
2578
- style: {
2579
- ...style,
2580
- ...resolvedActiveProps.style,
2581
- ...resolvedInactiveProps.style
2582
- },
2583
- className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
2584
- ...(disabled ? {
2585
- role: 'link',
2586
- 'aria-disabled': true
2587
- } : undefined),
2588
- ['data-status']: isActive ? 'active' : undefined
2549
+ // hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
2550
+ // let _ctx = __do_not_use_server_ctx
2551
+ // // Client hydrates from window
2552
+ // if (typeof document !== 'undefined') {
2553
+ // _ctx = window.__TSR_DEHYDRATED__
2554
+ // }
2555
+
2556
+ // invariant(
2557
+ // _ctx,
2558
+ // 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
2559
+ // )
2560
+
2561
+ // const ctx = _ctx
2562
+ // this.dehydratedData = ctx.payload as any
2563
+ // this.options.hydrate?.(ctx.payload as any)
2564
+ // const dehydratedState = ctx.router.state
2565
+
2566
+ // let matches = this.matchRoutes(
2567
+ // this.state.location.pathname,
2568
+ // this.state.location.search,
2569
+ // ).map((match) => {
2570
+ // const dehydratedMatch = dehydratedState.dehydratedMatches.find(
2571
+ // (d) => d.id === match.id,
2572
+ // )
2573
+
2574
+ // invariant(
2575
+ // dehydratedMatch,
2576
+ // `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
2577
+ // )
2578
+
2579
+ // if (dehydratedMatch) {
2580
+ // return {
2581
+ // ...match,
2582
+ // ...dehydratedMatch,
2583
+ // }
2584
+ // }
2585
+ // return match
2586
+ // })
2587
+
2588
+ // this.setState((s) => {
2589
+ // return {
2590
+ // ...s,
2591
+ // matches: dehydratedState.dehydratedMatches as any,
2592
+ // }
2593
+ // })
2594
+ // }
2595
+
2596
+ // resolveMatchPromise = (matchId: string, key: string, value: any) => {
2597
+ // state.matches
2598
+ // .find((d) => d.id === matchId)
2599
+ // ?.__promisesByKey[key]?.resolve(value)
2600
+ // }
2601
+ }
2602
+
2603
+ // A function that takes an import() argument which is a function and returns a new function that will
2604
+ // proxy arguments from the caller to the imported function, retaining all type
2605
+ // information along the way
2606
+ function lazyFn(fn, key) {
2607
+ return async (...args) => {
2608
+ const imported = await fn();
2609
+ return imported[key || 'default'](...args);
2589
2610
  };
2590
2611
  }
2591
- const Link = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
2592
- const linkProps = useLinkProps(props);
2593
- return /*#__PURE__*/React__namespace.createElement("a", _extends({
2594
- ref: ref
2595
- }, linkProps, {
2596
- children: typeof props.children === 'function' ? props.children({
2597
- isActive: linkProps['data-status'] === 'active'
2598
- }) : props.children
2599
- }));
2600
- });
2612
+ function isCtrlEvent(e) {
2613
+ return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2614
+ }
2601
2615
 
2602
2616
  const useLayoutEffect = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
2603
2617
  const windowKey = 'window';
@@ -2607,11 +2621,7 @@
2607
2621
  const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage;
2608
2622
  const defaultGetKey = location => location.state.key;
2609
2623
  function useScrollRestoration(options) {
2610
- const {
2611
- state,
2612
- subscribe,
2613
- resetNextScrollRef
2614
- } = useRouter();
2624
+ const router = useRouter();
2615
2625
  useLayoutEffect(() => {
2616
2626
  const getKey = options?.getKey || defaultGetKey;
2617
2627
  if (sessionsStorage) {
@@ -2667,7 +2677,7 @@
2667
2677
  if (typeof document !== 'undefined') {
2668
2678
  document.addEventListener('scroll', onScroll, true);
2669
2679
  }
2670
- const unsubOnBeforeLoad = subscribe('onBeforeLoad', event => {
2680
+ const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', event => {
2671
2681
  if (event.pathChanged) {
2672
2682
  const restoreKey = getKey(event.fromLocation);
2673
2683
  for (const elementSelector in cache.state.next) {
@@ -2697,12 +2707,12 @@
2697
2707
  }
2698
2708
  }
2699
2709
  });
2700
- const unsubOnResolved = subscribe('onResolved', event => {
2710
+ const unsubOnResolved = router.subscribe('onResolved', event => {
2701
2711
  if (event.pathChanged) {
2702
- if (!resetNextScrollRef.current) {
2712
+ if (!router.resetNextScroll) {
2703
2713
  return;
2704
2714
  }
2705
- resetNextScrollRef.current = true;
2715
+ router.resetNextScroll = true;
2706
2716
  const getKey = options?.getKey || defaultGetKey;
2707
2717
  const restoreKey = getKey(event.toLocation);
2708
2718
  let windowRestored = false;
@@ -2884,7 +2894,5 @@
2884
2894
  exports.useStableCallback = useStableCallback;
2885
2895
  exports.warning = warning;
2886
2896
 
2887
- Object.defineProperty(exports, '__esModule', { value: true });
2888
-
2889
2897
  }));
2890
2898
  //# sourceMappingURL=index.development.js.map