@remix-run/router 1.3.0-pre.0 → 1.3.0-pre.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.
package/dist/router.d.ts CHANGED
@@ -64,13 +64,13 @@ export interface Router {
64
64
  * Navigate forward/backward in the history stack
65
65
  * @param to Delta to move in the history stack
66
66
  */
67
- navigate(to: number): void;
67
+ navigate(to: number): Promise<void>;
68
68
  /**
69
69
  * Navigate to the given path
70
70
  * @param to Path to navigate to
71
71
  * @param opts Navigation options (method, submission, etc.)
72
72
  */
73
- navigate(to: To, opts?: RouterNavigateOptions): void;
73
+ navigate(to: To, opts?: RouterNavigateOptions): Promise<void>;
74
74
  /**
75
75
  * @internal
76
76
  * PRIVATE - DO NOT USE
@@ -130,6 +130,23 @@ export interface Router {
130
130
  * Cleanup listeners and abort any in-progress loads
131
131
  */
132
132
  dispose(): void;
133
+ /**
134
+ * @internal
135
+ * PRIVATE - DO NOT USE
136
+ *
137
+ * Get a navigation blocker
138
+ * @param key The identifier for the blocker
139
+ * @param fn The blocker function implementation
140
+ */
141
+ getBlocker(key: string, fn: BlockerFunction): Blocker;
142
+ /**
143
+ * @internal
144
+ * PRIVATE - DO NOT USE
145
+ *
146
+ * Delete a navigation blocker
147
+ * @param key The identifier for the blocker
148
+ */
149
+ deleteBlocker(key: string): void;
133
150
  /**
134
151
  * @internal
135
152
  * PRIVATE - DO NOT USE
@@ -202,6 +219,10 @@ export interface RouterState {
202
219
  * Map of current fetchers
203
220
  */
204
221
  fetchers: Map<string, Fetcher>;
222
+ /**
223
+ * Map of current blockers
224
+ */
225
+ blockers: Map<string, Blocker>;
205
226
  }
206
227
  /**
207
228
  * Data that can be passed into hydrate a Router from SSR
@@ -285,6 +306,7 @@ declare type LinkNavigateOptions = {
285
306
  declare type SubmissionNavigateOptions = {
286
307
  replace?: boolean;
287
308
  state?: any;
309
+ preventScrollReset?: boolean;
288
310
  formMethod?: FormMethod;
289
311
  formEncType?: FormEncType;
290
312
  formData: FormData;
@@ -361,8 +383,33 @@ declare type FetcherStates<TData = any> = {
361
383
  };
362
384
  };
363
385
  export declare type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
386
+ interface BlockerBlocked {
387
+ state: "blocked";
388
+ reset(): void;
389
+ proceed(): void;
390
+ location: Location;
391
+ }
392
+ interface BlockerUnblocked {
393
+ state: "unblocked";
394
+ reset: undefined;
395
+ proceed: undefined;
396
+ location: undefined;
397
+ }
398
+ interface BlockerProceeding {
399
+ state: "proceeding";
400
+ reset: undefined;
401
+ proceed: undefined;
402
+ location: Location;
403
+ }
404
+ export declare type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;
405
+ export declare type BlockerFunction = (args: {
406
+ currentLocation: Location;
407
+ nextLocation: Location;
408
+ historyAction: HistoryAction;
409
+ }) => boolean;
364
410
  export declare const IDLE_NAVIGATION: NavigationStates["Idle"];
365
411
  export declare const IDLE_FETCHER: FetcherStates["Idle"];
412
+ export declare const IDLE_BLOCKER: BlockerUnblocked;
366
413
  /**
367
414
  * Create a router and listen to history POP navigations
368
415
  */
package/dist/router.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.3.0-pre.0
2
+ * @remix-run/router v1.3.0-pre.2
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -140,7 +140,8 @@ function createMemoryHistory(options) {
140
140
  if (v5Compat && listener) {
141
141
  listener({
142
142
  action,
143
- location: nextLocation
143
+ location: nextLocation,
144
+ delta: 1
144
145
  });
145
146
  }
146
147
  },
@@ -153,19 +154,23 @@ function createMemoryHistory(options) {
153
154
  if (v5Compat && listener) {
154
155
  listener({
155
156
  action,
156
- location: nextLocation
157
+ location: nextLocation,
158
+ delta: 0
157
159
  });
158
160
  }
159
161
  },
160
162
 
161
163
  go(delta) {
162
164
  action = Action.Pop;
163
- index = clampIndex(index + delta);
165
+ let nextIndex = clampIndex(index + delta);
166
+ let nextLocation = entries[nextIndex];
167
+ index = nextIndex;
164
168
 
165
169
  if (listener) {
166
170
  listener({
167
171
  action,
168
- location: getCurrentLocation()
172
+ location: nextLocation,
173
+ delta
169
174
  });
170
175
  }
171
176
  },
@@ -290,10 +295,11 @@ function createKey() {
290
295
  */
291
296
 
292
297
 
293
- function getHistoryState(location) {
298
+ function getHistoryState(location, index) {
294
299
  return {
295
300
  usr: location.state,
296
- key: location.key
301
+ key: location.key,
302
+ idx: index
297
303
  };
298
304
  }
299
305
  /**
@@ -377,15 +383,45 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
377
383
  let globalHistory = window.history;
378
384
  let action = Action.Pop;
379
385
  let listener = null;
386
+ let index = getIndex(); // Index should only be null when we initialize. If not, it's because the
387
+ // user called history.pushState or history.replaceState directly, in which
388
+ // case we should log a warning as it will result in bugs.
389
+
390
+ if (index == null) {
391
+ index = 0;
392
+ globalHistory.replaceState(_extends({}, globalHistory.state, {
393
+ idx: index
394
+ }), "");
395
+ }
396
+
397
+ function getIndex() {
398
+ let state = globalHistory.state || {
399
+ idx: null
400
+ };
401
+ return state.idx;
402
+ }
380
403
 
381
404
  function handlePop() {
382
- action = Action.Pop;
405
+ let nextAction = Action.Pop;
406
+ let nextIndex = getIndex();
383
407
 
384
- if (listener) {
385
- listener({
386
- action,
387
- location: history.location
388
- });
408
+ if (nextIndex != null) {
409
+ let delta = nextIndex - index;
410
+ action = nextAction;
411
+ index = nextIndex;
412
+
413
+ if (listener) {
414
+ listener({
415
+ action,
416
+ location: history.location,
417
+ delta
418
+ });
419
+ }
420
+ } else {
421
+ warning$1(false, // TODO: Write up a doc that explains our blocking strategy in detail
422
+ // and link to it here so people can understand better what is going on
423
+ // and how to avoid it.
424
+ "You are trying to block a POP navigation to a location that was not " + "created by @remix-run/router. The block will fail silently in " + "production, but in general you should do all navigation with the " + "router (instead of using window.history.pushState directly) " + "to avoid this situation.");
389
425
  }
390
426
  }
391
427
 
@@ -393,7 +429,8 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
393
429
  action = Action.Push;
394
430
  let location = createLocation(history.location, to, state);
395
431
  if (validateLocation) validateLocation(location, to);
396
- let historyState = getHistoryState(location);
432
+ index = getIndex() + 1;
433
+ let historyState = getHistoryState(location, index);
397
434
  let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/
398
435
 
399
436
  try {
@@ -407,7 +444,8 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
407
444
  if (v5Compat && listener) {
408
445
  listener({
409
446
  action,
410
- location: history.location
447
+ location: history.location,
448
+ delta: 1
411
449
  });
412
450
  }
413
451
  }
@@ -416,14 +454,16 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
416
454
  action = Action.Replace;
417
455
  let location = createLocation(history.location, to, state);
418
456
  if (validateLocation) validateLocation(location, to);
419
- let historyState = getHistoryState(location);
457
+ index = getIndex();
458
+ let historyState = getHistoryState(location, index);
420
459
  let url = history.createHref(location);
421
460
  globalHistory.replaceState(historyState, "", url);
422
461
 
423
462
  if (v5Compat && listener) {
424
463
  listener({
425
464
  action,
426
- location: history.location
465
+ location: history.location,
466
+ delta: 0
427
467
  });
428
468
  }
429
469
  }
@@ -949,7 +989,7 @@ function warning(cond, message) {
949
989
  if (typeof console !== "undefined") console.warn(message);
950
990
 
951
991
  try {
952
- // Welcome to debugging React Router!
992
+ // Welcome to debugging @remix-run/router!
953
993
  //
954
994
  // This error is thrown as a convenience so you can more easily
955
995
  // find the source for a warning that appears in the console by
@@ -1385,6 +1425,12 @@ const IDLE_FETCHER = {
1385
1425
  formEncType: undefined,
1386
1426
  formData: undefined
1387
1427
  };
1428
+ const IDLE_BLOCKER = {
1429
+ state: "unblocked",
1430
+ proceed: undefined,
1431
+ reset: undefined,
1432
+ location: undefined
1433
+ };
1388
1434
  const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
1389
1435
  const isServer = !isBrowser; //#endregion
1390
1436
  ////////////////////////////////////////////////////////////////////////////////
@@ -1449,7 +1495,8 @@ function createRouter(init) {
1449
1495
  loaderData: init.hydrationData && init.hydrationData.loaderData || {},
1450
1496
  actionData: init.hydrationData && init.hydrationData.actionData || null,
1451
1497
  errors: init.hydrationData && init.hydrationData.errors || initialErrors,
1452
- fetchers: new Map()
1498
+ fetchers: new Map(),
1499
+ blockers: new Map()
1453
1500
  }; // -- Stateful internal variables to manage navigations --
1454
1501
  // Current navigation in progress (to be committed in completeNavigation)
1455
1502
 
@@ -1491,7 +1538,16 @@ function createRouter(init) {
1491
1538
  // promise resolves we update loaderData. If a new navigation starts we
1492
1539
  // cancel active deferreds for eliminated routes.
1493
1540
 
1494
- let activeDeferreds = new Map(); // Initialize the router, all side effects should be kicked off from here.
1541
+ let activeDeferreds = new Map(); // We ony support a single active blocker at the moment since we don't have
1542
+ // any compelling use cases for multi-blocker yet
1543
+
1544
+ let activeBlocker = null; // Store blocker functions in a separate Map outside of router state since
1545
+ // we don't need to update UI state if they change
1546
+
1547
+ let blockerFunctions = new Map(); // Flag to ignore the next history update, so we can revert the URL change on
1548
+ // a POP navigation that was blocked by the user without touching router state
1549
+
1550
+ let ignoreNextHistoryUpdate = false; // Initialize the router, all side effects should be kicked off from here.
1495
1551
  // Implemented as a Fluent API for ease of:
1496
1552
  // let router = createRouter(init).initialize();
1497
1553
 
@@ -1501,8 +1557,54 @@ function createRouter(init) {
1501
1557
  unlistenHistory = init.history.listen(_ref => {
1502
1558
  let {
1503
1559
  action: historyAction,
1504
- location
1560
+ location,
1561
+ delta
1505
1562
  } = _ref;
1563
+
1564
+ // Ignore this event if it was just us resetting the URL from a
1565
+ // blocked POP navigation
1566
+ if (ignoreNextHistoryUpdate) {
1567
+ ignoreNextHistoryUpdate = false;
1568
+ return;
1569
+ }
1570
+
1571
+ let blockerKey = shouldBlockNavigation({
1572
+ currentLocation: state.location,
1573
+ nextLocation: location,
1574
+ historyAction
1575
+ });
1576
+
1577
+ if (blockerKey) {
1578
+ // Restore the URL to match the current UI, but don't update router state
1579
+ ignoreNextHistoryUpdate = true;
1580
+ init.history.go(delta * -1); // Put the blocker into a blocked state
1581
+
1582
+ updateBlocker(blockerKey, {
1583
+ state: "blocked",
1584
+ location,
1585
+
1586
+ proceed() {
1587
+ updateBlocker(blockerKey, {
1588
+ state: "proceeding",
1589
+ proceed: undefined,
1590
+ reset: undefined,
1591
+ location
1592
+ }); // Re-do the same POP navigation we just blocked
1593
+
1594
+ init.history.go(delta);
1595
+ },
1596
+
1597
+ reset() {
1598
+ deleteBlocker(blockerKey);
1599
+ updateState({
1600
+ blockers: new Map(router.state.blockers)
1601
+ });
1602
+ }
1603
+
1604
+ });
1605
+ return;
1606
+ }
1607
+
1506
1608
  return startNavigation(historyAction, location);
1507
1609
  }); // Kick off initial data load if needed. Use Pop to avoid modifying history
1508
1610
 
@@ -1522,6 +1624,7 @@ function createRouter(init) {
1522
1624
  subscribers.clear();
1523
1625
  pendingNavigationController && pendingNavigationController.abort();
1524
1626
  state.fetchers.forEach((_, key) => deleteFetcher(key));
1627
+ state.blockers.forEach((_, key) => deleteBlocker(key));
1525
1628
  } // Subscribe to state updates for the router
1526
1629
 
1527
1630
 
@@ -1542,7 +1645,7 @@ function createRouter(init) {
1542
1645
 
1543
1646
 
1544
1647
  function completeNavigation(location, newState) {
1545
- var _location$state;
1648
+ var _location$state, _location$state2;
1546
1649
 
1547
1650
  // Deduce if we're in a loading/actionReload state:
1548
1651
  // - We have committed actionData in the store
@@ -1568,7 +1671,16 @@ function createRouter(init) {
1568
1671
  } // Always preserve any existing loaderData from re-used routes
1569
1672
 
1570
1673
 
1571
- let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData;
1674
+ let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData; // On a successful navigation we can assume we got through all blockers
1675
+ // so we can start fresh
1676
+
1677
+ for (let [key] of blockerFunctions) {
1678
+ deleteBlocker(key);
1679
+ } // Always respect the user flag. Otherwise don't reset on mutation
1680
+ // submission navigations unless they redirect
1681
+
1682
+
1683
+ let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
1572
1684
  updateState(_extends({}, newState, {
1573
1685
  actionData,
1574
1686
  loaderData,
@@ -1577,9 +1689,9 @@ function createRouter(init) {
1577
1689
  initialized: true,
1578
1690
  navigation: IDLE_NAVIGATION,
1579
1691
  revalidation: "idle",
1580
- // Don't restore on submission navigations
1581
- restoreScrollPosition: state.navigation.formData ? false : getSavedScrollPosition(location, newState.matches || state.matches),
1582
- preventScrollReset: pendingPreventScrollReset
1692
+ restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),
1693
+ preventScrollReset,
1694
+ blockers: new Map(state.blockers)
1583
1695
  }));
1584
1696
 
1585
1697
  if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) {
@@ -1610,13 +1722,14 @@ function createRouter(init) {
1610
1722
  submission,
1611
1723
  error
1612
1724
  } = normalizeNavigateOptions(to, opts);
1613
- let location = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
1725
+ let currentLocation = state.location;
1726
+ let nextLocation = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
1614
1727
  // URL from window.location, so we need to encode it here so the behavior
1615
1728
  // remains the same as POP and non-data-router usages. new URL() does all
1616
1729
  // the same encoding we'd get from a history.pushState/window.location read
1617
1730
  // without having to touch history
1618
1731
 
1619
- location = _extends({}, location, init.history.encodeLocation(location));
1732
+ nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation));
1620
1733
  let userReplace = opts && opts.replace != null ? opts.replace : undefined;
1621
1734
  let historyAction = Action.Push;
1622
1735
 
@@ -1631,7 +1744,41 @@ function createRouter(init) {
1631
1744
  }
1632
1745
 
1633
1746
  let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
1634
- return await startNavigation(historyAction, location, {
1747
+ let blockerKey = shouldBlockNavigation({
1748
+ currentLocation,
1749
+ nextLocation,
1750
+ historyAction
1751
+ });
1752
+
1753
+ if (blockerKey) {
1754
+ // Put the blocker into a blocked state
1755
+ updateBlocker(blockerKey, {
1756
+ state: "blocked",
1757
+ location: nextLocation,
1758
+
1759
+ proceed() {
1760
+ updateBlocker(blockerKey, {
1761
+ state: "proceeding",
1762
+ proceed: undefined,
1763
+ reset: undefined,
1764
+ location: nextLocation
1765
+ }); // Send the same navigation through
1766
+
1767
+ navigate(to, opts);
1768
+ },
1769
+
1770
+ reset() {
1771
+ deleteBlocker(blockerKey);
1772
+ updateState({
1773
+ blockers: new Map(state.blockers)
1774
+ });
1775
+ }
1776
+
1777
+ });
1778
+ return;
1779
+ }
1780
+
1781
+ return await startNavigation(historyAction, nextLocation, {
1635
1782
  submission,
1636
1783
  // Send through the formData serialization error if we have one so we can
1637
1784
  // render at the right error boundary after we match routes
@@ -2403,7 +2550,9 @@ function createRouter(init) {
2403
2550
  await startNavigation(redirectHistoryAction, redirectLocation, {
2404
2551
  submission: _extends({}, submission, {
2405
2552
  formAction: redirect.location
2406
- })
2553
+ }),
2554
+ // Preserve this flag across redirects
2555
+ preventScrollReset: pendingPreventScrollReset
2407
2556
  });
2408
2557
  } else {
2409
2558
  // Otherwise, we kick off a new loading navigation, preserving the
@@ -2416,7 +2565,9 @@ function createRouter(init) {
2416
2565
  formAction: submission ? submission.formAction : undefined,
2417
2566
  formEncType: submission ? submission.formEncType : undefined,
2418
2567
  formData: submission ? submission.formData : undefined
2419
- }
2568
+ },
2569
+ // Preserve this flag across redirects
2570
+ preventScrollReset: pendingPreventScrollReset
2420
2571
  });
2421
2572
  }
2422
2573
  }
@@ -2535,6 +2686,78 @@ function createRouter(init) {
2535
2686
  return yeetedKeys.length > 0;
2536
2687
  }
2537
2688
 
2689
+ function getBlocker(key, fn) {
2690
+ let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2691
+
2692
+ if (blockerFunctions.get(key) !== fn) {
2693
+ blockerFunctions.set(key, fn);
2694
+
2695
+ if (activeBlocker == null) {
2696
+ // This is now the active blocker
2697
+ activeBlocker = key;
2698
+ } else if (key !== activeBlocker) {
2699
+ warning(false, "A router only supports one blocker at a time");
2700
+ }
2701
+ }
2702
+
2703
+ return blocker;
2704
+ }
2705
+
2706
+ function deleteBlocker(key) {
2707
+ state.blockers.delete(key);
2708
+ blockerFunctions.delete(key);
2709
+
2710
+ if (activeBlocker === key) {
2711
+ activeBlocker = null;
2712
+ }
2713
+ } // Utility function to update blockers, ensuring valid state transitions
2714
+
2715
+
2716
+ function updateBlocker(key, newBlocker) {
2717
+ let blocker = state.blockers.get(key) || IDLE_BLOCKER; // Poor mans state machine :)
2718
+ // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM
2719
+
2720
+ invariant(blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", "Invalid blocker state transition: " + blocker.state + " -> " + newBlocker.state);
2721
+ state.blockers.set(key, newBlocker);
2722
+ updateState({
2723
+ blockers: new Map(state.blockers)
2724
+ });
2725
+ }
2726
+
2727
+ function shouldBlockNavigation(_ref10) {
2728
+ let {
2729
+ currentLocation,
2730
+ nextLocation,
2731
+ historyAction
2732
+ } = _ref10;
2733
+
2734
+ if (activeBlocker == null) {
2735
+ return;
2736
+ } // We only allow a single blocker at the moment. This will need to be
2737
+ // updated if we enhance to support multiple blockers in the future
2738
+
2739
+
2740
+ let blockerFunction = blockerFunctions.get(activeBlocker);
2741
+ invariant(blockerFunction, "Could not find a function for the active blocker");
2742
+ let blocker = state.blockers.get(activeBlocker);
2743
+
2744
+ if (blocker && blocker.state === "proceeding") {
2745
+ // If the blocker is currently proceeding, we don't need to re-check
2746
+ // it and can let this navigation continue
2747
+ return;
2748
+ } // At this point, we know we're unblocked/blocked so we need to check the
2749
+ // user-provided blocker function
2750
+
2751
+
2752
+ if (blockerFunction({
2753
+ currentLocation,
2754
+ nextLocation,
2755
+ historyAction
2756
+ })) {
2757
+ return activeBlocker;
2758
+ }
2759
+ }
2760
+
2538
2761
  function cancelActiveDeferreds(predicate) {
2539
2762
  let cancelledRouteIds = [];
2540
2763
  activeDeferreds.forEach((dfd, routeId) => {
@@ -2627,6 +2850,8 @@ function createRouter(init) {
2627
2850
  getFetcher,
2628
2851
  deleteFetcher,
2629
2852
  dispose,
2853
+ getBlocker,
2854
+ deleteBlocker,
2630
2855
  _internalFetchControllers: fetchControllers,
2631
2856
  _internalActiveDeferreds: activeDeferreds
2632
2857
  };
@@ -3147,8 +3372,8 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3147
3372
  cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(history, state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
3148
3373
 
3149
3374
  let revalidatingFetchers = [];
3150
- fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
3151
- let [href, match, fetchMatches] = _ref10;
3375
+ fetchLoadMatches && fetchLoadMatches.forEach((_ref11, key) => {
3376
+ let [href, match, fetchMatches] = _ref11;
3152
3377
 
3153
3378
  // This fetcher was cancelled from a prior action submission - force reload
3154
3379
  if (cancelledFetcherLoads.includes(key)) {
@@ -3748,5 +3973,5 @@ function getTargetMatch(matches, location) {
3748
3973
  return pathMatches[pathMatches.length - 1];
3749
3974
  } //#endregion
3750
3975
 
3751
- export { AbortedDeferredError, Action, ErrorResponse, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename, warning };
3976
+ export { AbortedDeferredError, Action, ErrorResponse, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename, warning };
3752
3977
  //# sourceMappingURL=router.js.map