@tanstack/react-router 0.0.1-alpha.9 → 0.0.1-beta.2

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.
@@ -1274,6 +1274,40 @@ function createRoute(routeConfig, options, parent, router) {
1274
1274
  return router.state.actions[id];
1275
1275
  })();
1276
1276
 
1277
+ const loader = router.state.loaders[id] || (() => {
1278
+ router.state.loaders[id] = {
1279
+ pending: [],
1280
+ fetch: async loaderContext => {
1281
+ if (!route) {
1282
+ return;
1283
+ }
1284
+
1285
+ const loaderState = {
1286
+ loadedAt: Date.now(),
1287
+ loaderContext
1288
+ };
1289
+ loader.current = loaderState;
1290
+ loader.latest = loaderState;
1291
+ loader.pending.push(loaderState); // router.state = {
1292
+ // ...router.state,
1293
+ // currentAction: loaderState,
1294
+ // latestAction: loaderState,
1295
+ // }
1296
+
1297
+ router.notify();
1298
+
1299
+ try {
1300
+ return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1301
+ } finally {
1302
+ loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1303
+
1304
+ router.notify();
1305
+ }
1306
+ }
1307
+ };
1308
+ return router.state.loaders[id];
1309
+ })();
1310
+
1277
1311
  let route = {
1278
1312
  routeId: id,
1279
1313
  routeRouteId: routeId,
@@ -1284,6 +1318,7 @@ function createRoute(routeConfig, options, parent, router) {
1284
1318
  childRoutes: undefined,
1285
1319
  parentRoute: parent,
1286
1320
  action,
1321
+ loader: loader,
1287
1322
  buildLink: options => {
1288
1323
  return router.buildLink(_extends({}, options, {
1289
1324
  from: fullPath
@@ -1471,9 +1506,33 @@ function createRouteMatch(router, route, opts) {
1471
1506
  routeMatch.isInvalid = true;
1472
1507
  },
1473
1508
  hasLoaders: () => {
1474
- return !!(route.options.loader || route.options.import || elementTypes.some(d => typeof route.options[d] === 'function'));
1509
+ return !!(route.options.loader || elementTypes.some(d => typeof route.options[d] === 'function'));
1475
1510
  },
1476
- load: async opts => {
1511
+ load: async loaderOpts => {
1512
+ const now = Date.now();
1513
+ const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1514
+
1515
+ if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1516
+ // If the match is currently active, don't preload it
1517
+ if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1518
+ return;
1519
+ }
1520
+
1521
+ router.matchCache[routeMatch.matchId] = {
1522
+ gc: now + loaderOpts.gcMaxAge,
1523
+ match: routeMatch
1524
+ };
1525
+ } // If the match is invalid, errored or idle, trigger it to load
1526
+
1527
+
1528
+ if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1529
+ const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1530
+ routeMatch.fetch({
1531
+ maxAge
1532
+ });
1533
+ }
1534
+ },
1535
+ fetch: async opts => {
1477
1536
  const id = '' + Date.now() + Math.random();
1478
1537
  routeMatch.__.latestId = id; // If the match was in an error state, set it
1479
1538
  // to a loading state again. Otherwise, keep it
@@ -1492,21 +1551,7 @@ function createRouteMatch(router, route, opts) {
1492
1551
  routeMatch.__.resolve = resolve;
1493
1552
 
1494
1553
  const loaderPromise = (async () => {
1495
- const importer = routeMatch.options.import; // First, run any importers
1496
-
1497
- if (importer) {
1498
- routeMatch.__.importPromise = importer({
1499
- params: routeMatch.params // search: routeMatch.search,
1500
-
1501
- }).then(imported => {
1502
- routeMatch.__ = _extends({}, routeMatch.__, imported);
1503
- });
1504
- } // Wait for the importer to finish before
1505
- // attempting to load elements and data
1506
-
1507
-
1508
- await routeMatch.__.importPromise; // Next, load the elements and data in parallel
1509
-
1554
+ // Load the elements and data in parallel
1510
1555
  routeMatch.__.elementsPromise = (async () => {
1511
1556
  // then run all element and data loaders in parallel
1512
1557
  // For each element type, potentially load it asynchronously
@@ -1517,12 +1562,7 @@ function createRouteMatch(router, route, opts) {
1517
1562
  return;
1518
1563
  }
1519
1564
 
1520
- if (typeof routeElement === 'function') {
1521
- const res = await routeElement(routeMatch);
1522
- routeMatch.__[type] = res;
1523
- } else {
1524
- routeMatch.__[type] = routeMatch.options[type];
1525
- }
1565
+ routeMatch.__[type] = await router.options.createElement(routeElement);
1526
1566
  }));
1527
1567
  })();
1528
1568
 
@@ -1678,6 +1718,7 @@ function createRouter(userOptions) {
1678
1718
  });
1679
1719
 
1680
1720
  let router = {
1721
+ history,
1681
1722
  options: originalOptions,
1682
1723
  listeners: [],
1683
1724
  removeActionQueue: [],
@@ -1696,6 +1737,7 @@ function createRouter(userOptions) {
1696
1737
  location: null,
1697
1738
  matches: [],
1698
1739
  actions: {},
1740
+ loaders: {},
1699
1741
  loaderData: {},
1700
1742
  lastUpdated: Date.now(),
1701
1743
  isFetching: false,
@@ -1717,24 +1759,25 @@ function createRouter(userOptions) {
1717
1759
  isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
1718
1760
  });
1719
1761
  cascadeLoaderData(router.state.matches);
1720
- router.listeners.forEach(listener => listener());
1762
+ router.listeners.forEach(listener => listener(router));
1721
1763
  },
1722
1764
  mount: () => {
1723
- const next = router.buildLocation({
1765
+ const next = router.__.buildLocation({
1724
1766
  to: '.',
1725
1767
  search: true,
1726
1768
  hash: true
1727
1769
  }); // If the current location isn't updated, trigger a navigation
1728
1770
  // to the current location. Otherwise, load the current location.
1729
1771
 
1772
+
1730
1773
  if (next.href !== router.location.href) {
1731
- router.commitLocation(next, true);
1774
+ router.__.commitLocation(next, true);
1732
1775
  } else {
1733
1776
  router.loadLocation();
1734
1777
  }
1735
1778
 
1736
1779
  const unsub = history.listen(event => {
1737
- router.loadLocation(router.parseLocation(event.location, router.location));
1780
+ router.loadLocation(router.__.parseLocation(event.location, router.location));
1738
1781
  }); // addEventListener does not exist in React Native, but window does
1739
1782
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1740
1783
 
@@ -1764,169 +1807,11 @@ function createRouter(userOptions) {
1764
1807
 
1765
1808
  if (routeConfig) {
1766
1809
  router.routesById = {};
1767
- router.routeTree = router.buildRouteTree(routeConfig);
1810
+ router.routeTree = router.__.buildRouteTree(routeConfig);
1768
1811
  }
1769
1812
 
1770
1813
  return router;
1771
1814
  },
1772
- buildRouteTree: rootRouteConfig => {
1773
- const recurseRoutes = (routeConfigs, parent) => {
1774
- return routeConfigs.map(routeConfig => {
1775
- const routeOptions = routeConfig.options;
1776
- const route = createRoute(routeConfig, routeOptions, parent, router); // {
1777
- // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
1778
- // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
1779
- // }
1780
-
1781
- const existingRoute = router.routesById[route.routeId];
1782
-
1783
- if (existingRoute) {
1784
- if (process.env.NODE_ENV !== 'production') {
1785
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1786
- }
1787
-
1788
- throw new Error();
1789
- }
1790
- router.routesById[route.routeId] = route;
1791
- const children = routeConfig.children;
1792
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
1793
- return route;
1794
- });
1795
- };
1796
-
1797
- const routes = recurseRoutes([rootRouteConfig]);
1798
- return routes[0];
1799
- },
1800
- parseLocation: (location, previousLocation) => {
1801
- var _location$hash$split$;
1802
-
1803
- const parsedSearch = router.options.parseSearch(location.search);
1804
- return {
1805
- pathname: location.pathname,
1806
- searchStr: location.search,
1807
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
1808
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
1809
- href: "" + location.pathname + location.search + location.hash,
1810
- state: location.state,
1811
- key: location.key
1812
- };
1813
- },
1814
- buildLocation: function buildLocation(dest) {
1815
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
1816
-
1817
- if (dest === void 0) {
1818
- dest = {};
1819
- }
1820
-
1821
- // const resolvedFrom: Location = {
1822
- // ...router.location,
1823
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
1824
-
1825
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
1826
-
1827
- const fromMatches = router.matchRoutes(router.location.pathname, {
1828
- strictParseParams: true
1829
- });
1830
- const toMatches = router.matchRoutes(pathname);
1831
-
1832
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
1833
-
1834
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1835
-
1836
- if (nextParams) {
1837
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
1838
- Object.assign({}, nextParams, fn(nextParams));
1839
- });
1840
- }
1841
-
1842
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
1843
-
1844
- const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
1845
-
1846
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1847
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
1848
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
1849
- : {}; // Then post filters
1850
-
1851
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1852
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
1853
- const searchStr = router.options.stringifySearch(search);
1854
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
1855
- hash = hash ? "#" + hash : '';
1856
- return {
1857
- pathname,
1858
- search,
1859
- searchStr,
1860
- state: router.location.state,
1861
- hash,
1862
- href: "" + pathname + searchStr + hash,
1863
- key: dest.key
1864
- };
1865
- },
1866
- commitLocation: (next, replace) => {
1867
- const id = '' + Date.now() + Math.random();
1868
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
1869
- let nextAction = 'replace';
1870
-
1871
- if (!replace) {
1872
- nextAction = 'push';
1873
- }
1874
-
1875
- const isSameUrl = router.parseLocation(history.location).href === next.href;
1876
-
1877
- if (isSameUrl && !next.key) {
1878
- nextAction = 'replace';
1879
- }
1880
-
1881
- if (nextAction === 'replace') {
1882
- history.replace({
1883
- pathname: next.pathname,
1884
- hash: next.hash,
1885
- search: next.searchStr
1886
- }, {
1887
- id
1888
- });
1889
- } else {
1890
- history.push({
1891
- pathname: next.pathname,
1892
- hash: next.hash,
1893
- search: next.searchStr
1894
- }, {
1895
- id
1896
- });
1897
- }
1898
-
1899
- router.navigationPromise = new Promise(resolve => {
1900
- const previousNavigationResolve = router.resolveNavigation;
1901
-
1902
- router.resolveNavigation = () => {
1903
- previousNavigationResolve();
1904
- resolve();
1905
- };
1906
- });
1907
- return router.navigationPromise;
1908
- },
1909
- buildNext: opts => {
1910
- const next = router.buildLocation(opts);
1911
- const matches = router.matchRoutes(next.pathname);
1912
-
1913
- const __preSearchFilters = matches.map(match => {
1914
- var _match$options$preSea;
1915
-
1916
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
1917
- }).flat().filter(Boolean);
1918
-
1919
- const __postSearchFilters = matches.map(match => {
1920
- var _match$options$postSe;
1921
-
1922
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
1923
- }).flat().filter(Boolean);
1924
-
1925
- return router.buildLocation(_extends({}, opts, {
1926
- __preSearchFilters,
1927
- __postSearchFilters
1928
- }));
1929
- },
1930
1815
  cancelMatches: () => {
1931
1816
  var _router$state$pending, _router$state$pending2;
1932
1817
  [...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
@@ -2029,6 +1914,7 @@ function createRouter(userOptions) {
2029
1914
  params: d.params,
2030
1915
  search: d.search
2031
1916
  });
1917
+ delete router.matchCache[d.matchId];
2032
1918
  });
2033
1919
 
2034
1920
  if (matches.some(d => d.status === 'loading')) {
@@ -2188,32 +2074,11 @@ function createRouter(userOptions) {
2188
2074
  return matches;
2189
2075
  },
2190
2076
  loadMatches: async (resolvedMatches, loaderOpts) => {
2191
- const now = Date.now();
2192
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0;
2193
2077
  const matchPromises = resolvedMatches.map(async match => {
2194
2078
  // Validate the match (loads search params etc)
2195
- match.__.validate(); // If this is a preload, add it to the preload cache
2079
+ match.__.validate();
2196
2080
 
2197
-
2198
- if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
2199
- // If the match is currently active, don't preload it
2200
- if (router.state.matches.find(d => d.matchId === match.matchId)) {
2201
- return;
2202
- }
2203
-
2204
- router.matchCache[match.matchId] = {
2205
- gc: now + loaderOpts.gcMaxAge,
2206
- match
2207
- };
2208
- } // If the match is invalid, errored or idle, trigger it to load
2209
-
2210
-
2211
- if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
2212
- const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
2213
- match.load({
2214
- maxAge
2215
- });
2216
- }
2081
+ match.load(loaderOpts);
2217
2082
 
2218
2083
  if (match.status === 'loading') {
2219
2084
  // If requested, start the pending timers
@@ -2237,7 +2102,7 @@ function createRouter(userOptions) {
2237
2102
  }
2238
2103
  });
2239
2104
  },
2240
- reload: () => router._navigate({
2105
+ reload: () => router.__.navigate({
2241
2106
  fromCurrent: true,
2242
2107
  replace: true,
2243
2108
  search: true
@@ -2270,10 +2135,6 @@ function createRouter(userOptions) {
2270
2135
  to: next.pathname
2271
2136
  }));
2272
2137
  },
2273
- _navigate: location => {
2274
- const next = router.buildNext(location);
2275
- return router.commitLocation(next, location.replace);
2276
- },
2277
2138
  navigate: async _ref8 => {
2278
2139
  let {
2279
2140
  from,
@@ -2297,7 +2158,7 @@ function createRouter(userOptions) {
2297
2158
  } catch (e) {}
2298
2159
 
2299
2160
  invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2300
- return router._navigate({
2161
+ return router.__.navigate({
2301
2162
  from: fromString,
2302
2163
  to: toString,
2303
2164
  search,
@@ -2369,7 +2230,7 @@ function createRouter(userOptions) {
2369
2230
  } // All is well? Navigate!)
2370
2231
 
2371
2232
 
2372
- router._navigate(nextOpts);
2233
+ router.__.navigate(nextOpts);
2373
2234
  }
2374
2235
  }; // The click handler
2375
2236
 
@@ -2420,9 +2281,174 @@ function createRouter(userOptions) {
2420
2281
  isActive,
2421
2282
  disabled
2422
2283
  };
2284
+ },
2285
+ buildNext: opts => {
2286
+ const next = router.__.buildLocation(opts);
2287
+
2288
+ const matches = router.matchRoutes(next.pathname);
2289
+
2290
+ const __preSearchFilters = matches.map(match => {
2291
+ var _match$options$preSea;
2292
+
2293
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2294
+ }).flat().filter(Boolean);
2295
+
2296
+ const __postSearchFilters = matches.map(match => {
2297
+ var _match$options$postSe;
2298
+
2299
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2300
+ }).flat().filter(Boolean);
2301
+
2302
+ return router.__.buildLocation(_extends({}, opts, {
2303
+ __preSearchFilters,
2304
+ __postSearchFilters
2305
+ }));
2306
+ },
2307
+ __: {
2308
+ buildRouteTree: rootRouteConfig => {
2309
+ const recurseRoutes = (routeConfigs, parent) => {
2310
+ return routeConfigs.map(routeConfig => {
2311
+ const routeOptions = routeConfig.options;
2312
+ const route = createRoute(routeConfig, routeOptions, parent, router); // {
2313
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
2314
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
2315
+ // }
2316
+
2317
+ const existingRoute = router.routesById[route.routeId];
2318
+
2319
+ if (existingRoute) {
2320
+ if (process.env.NODE_ENV !== 'production') {
2321
+ console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
2322
+ }
2323
+
2324
+ throw new Error();
2325
+ }
2326
+ router.routesById[route.routeId] = route;
2327
+ const children = routeConfig.children;
2328
+ route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2329
+ return route;
2330
+ });
2331
+ };
2332
+
2333
+ const routes = recurseRoutes([rootRouteConfig]);
2334
+ return routes[0];
2335
+ },
2336
+ parseLocation: (location, previousLocation) => {
2337
+ var _location$hash$split$;
2338
+
2339
+ const parsedSearch = router.options.parseSearch(location.search);
2340
+ return {
2341
+ pathname: location.pathname,
2342
+ searchStr: location.search,
2343
+ search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2344
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2345
+ href: "" + location.pathname + location.search + location.hash,
2346
+ state: location.state,
2347
+ key: location.key
2348
+ };
2349
+ },
2350
+ navigate: location => {
2351
+ const next = router.buildNext(location);
2352
+ return router.__.commitLocation(next, location.replace);
2353
+ },
2354
+ buildLocation: function buildLocation(dest) {
2355
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2356
+
2357
+ if (dest === void 0) {
2358
+ dest = {};
2359
+ }
2360
+
2361
+ // const resolvedFrom: Location = {
2362
+ // ...router.location,
2363
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2364
+
2365
+ let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2366
+
2367
+ const fromMatches = router.matchRoutes(router.location.pathname, {
2368
+ strictParseParams: true
2369
+ });
2370
+ const toMatches = router.matchRoutes(pathname);
2371
+
2372
+ const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2373
+
2374
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
2375
+
2376
+ if (nextParams) {
2377
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2378
+ Object.assign({}, nextParams, fn(nextParams));
2379
+ });
2380
+ }
2381
+
2382
+ pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2383
+
2384
+ const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
2385
+
2386
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2387
+ : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2388
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2389
+ : {}; // Then post filters
2390
+
2391
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2392
+ const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2393
+ const searchStr = router.options.stringifySearch(search);
2394
+ let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2395
+ hash = hash ? "#" + hash : '';
2396
+ return {
2397
+ pathname,
2398
+ search,
2399
+ searchStr,
2400
+ state: router.location.state,
2401
+ hash,
2402
+ href: "" + pathname + searchStr + hash,
2403
+ key: dest.key
2404
+ };
2405
+ },
2406
+ commitLocation: (next, replace) => {
2407
+ const id = '' + Date.now() + Math.random();
2408
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2409
+ let nextAction = 'replace';
2410
+
2411
+ if (!replace) {
2412
+ nextAction = 'push';
2413
+ }
2414
+
2415
+ const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2416
+
2417
+ if (isSameUrl && !next.key) {
2418
+ nextAction = 'replace';
2419
+ }
2420
+
2421
+ if (nextAction === 'replace') {
2422
+ history.replace({
2423
+ pathname: next.pathname,
2424
+ hash: next.hash,
2425
+ search: next.searchStr
2426
+ }, {
2427
+ id
2428
+ });
2429
+ } else {
2430
+ history.push({
2431
+ pathname: next.pathname,
2432
+ hash: next.hash,
2433
+ search: next.searchStr
2434
+ }, {
2435
+ id
2436
+ });
2437
+ }
2438
+
2439
+ router.navigationPromise = new Promise(resolve => {
2440
+ const previousNavigationResolve = router.resolveNavigation;
2441
+
2442
+ router.resolveNavigation = () => {
2443
+ previousNavigationResolve();
2444
+ resolve();
2445
+ };
2446
+ });
2447
+ return router.navigationPromise;
2448
+ }
2423
2449
  }
2424
2450
  };
2425
- router.location = router.parseLocation(history.location);
2451
+ router.location = router.__.parseLocation(history.location);
2426
2452
  router.state.location = router.location;
2427
2453
  router.update(userOptions); // Allow frameworks to hook into the router creation
2428
2454