@remix-run/router 1.7.2 → 1.8.0
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/CHANGELOG.md +11 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +102 -43
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.js +42 -13
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +102 -43
- package/dist/router.umd.js.map +1 -1
- package/dist/router.umd.min.js +2 -2
- package/dist/router.umd.min.js.map +1 -1
- package/dist/utils.d.ts +7 -0
- package/history.ts +11 -0
- package/index.ts +1 -0
- package/package.json +2 -2
- package/router.ts +23 -10
- package/utils.ts +12 -0
package/dist/router.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.8.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -36,31 +36,36 @@
|
|
|
36
36
|
/**
|
|
37
37
|
* Actions represent the type of change to a location value.
|
|
38
38
|
*/
|
|
39
|
-
|
|
39
|
+
let Action = /*#__PURE__*/function (Action) {
|
|
40
|
+
Action["Pop"] = "POP";
|
|
41
|
+
Action["Push"] = "PUSH";
|
|
42
|
+
Action["Replace"] = "REPLACE";
|
|
43
|
+
return Action;
|
|
44
|
+
}({});
|
|
40
45
|
|
|
41
46
|
/**
|
|
42
47
|
* The pathname, search, and hash values of a URL.
|
|
43
48
|
*/
|
|
44
|
-
|
|
45
|
-
Action["Pop"] = "POP";
|
|
46
|
-
Action["Push"] = "PUSH";
|
|
47
|
-
Action["Replace"] = "REPLACE";
|
|
48
|
-
})(exports.Action || (exports.Action = {}));
|
|
49
|
+
|
|
49
50
|
/**
|
|
50
51
|
* An entry in a history stack. A location contains information about the
|
|
51
52
|
* URL path, as well as possibly some arbitrary state and a key.
|
|
52
53
|
*/
|
|
54
|
+
|
|
53
55
|
/**
|
|
54
56
|
* A change to the current location.
|
|
55
57
|
*/
|
|
58
|
+
|
|
56
59
|
/**
|
|
57
60
|
* A function that receives notifications about location changes.
|
|
58
61
|
*/
|
|
62
|
+
|
|
59
63
|
/**
|
|
60
64
|
* Describes a location that is the destination of some navigation, either via
|
|
61
65
|
* `history.push` or `history.replace`. May be either a URL or the pieces of a
|
|
62
66
|
* URL path.
|
|
63
67
|
*/
|
|
68
|
+
|
|
64
69
|
/**
|
|
65
70
|
* A history is an interface to the navigation stack. The history serves as the
|
|
66
71
|
* source of truth for the current location, as well as provides a set of
|
|
@@ -69,6 +74,7 @@
|
|
|
69
74
|
* It is similar to the DOM's `window.history` object, but with a smaller, more
|
|
70
75
|
* focused API.
|
|
71
76
|
*/
|
|
77
|
+
|
|
72
78
|
const PopStateEventType = "popstate";
|
|
73
79
|
//#endregion
|
|
74
80
|
|
|
@@ -101,7 +107,7 @@
|
|
|
101
107
|
let entries; // Declare so we can access from createMemoryLocation
|
|
102
108
|
entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined));
|
|
103
109
|
let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);
|
|
104
|
-
let action =
|
|
110
|
+
let action = Action.Pop;
|
|
105
111
|
let listener = null;
|
|
106
112
|
function clampIndex(n) {
|
|
107
113
|
return Math.min(Math.max(n, 0), entries.length - 1);
|
|
@@ -143,7 +149,7 @@
|
|
|
143
149
|
};
|
|
144
150
|
},
|
|
145
151
|
push(to, state) {
|
|
146
|
-
action =
|
|
152
|
+
action = Action.Push;
|
|
147
153
|
let nextLocation = createMemoryLocation(to, state);
|
|
148
154
|
index += 1;
|
|
149
155
|
entries.splice(index, entries.length, nextLocation);
|
|
@@ -156,7 +162,7 @@
|
|
|
156
162
|
}
|
|
157
163
|
},
|
|
158
164
|
replace(to, state) {
|
|
159
|
-
action =
|
|
165
|
+
action = Action.Replace;
|
|
160
166
|
let nextLocation = createMemoryLocation(to, state);
|
|
161
167
|
entries[index] = nextLocation;
|
|
162
168
|
if (v5Compat && listener) {
|
|
@@ -168,7 +174,7 @@
|
|
|
168
174
|
}
|
|
169
175
|
},
|
|
170
176
|
go(delta) {
|
|
171
|
-
action =
|
|
177
|
+
action = Action.Pop;
|
|
172
178
|
let nextIndex = clampIndex(index + delta);
|
|
173
179
|
let nextLocation = entries[nextIndex];
|
|
174
180
|
index = nextIndex;
|
|
@@ -267,6 +273,16 @@
|
|
|
267
273
|
search = "",
|
|
268
274
|
hash = ""
|
|
269
275
|
} = parsePath(window.location.hash.substr(1));
|
|
276
|
+
|
|
277
|
+
// Hash URL should always have a leading / just like window.location.pathname
|
|
278
|
+
// does, so if an app ends up at a route like /#something then we add a
|
|
279
|
+
// leading slash so all of our path-matching behaves the same as if it would
|
|
280
|
+
// in a browser router. This is particularly important when there exists a
|
|
281
|
+
// root splat route (<Route path="*">) since that matches internally against
|
|
282
|
+
// "/*" and we'd expect /#something to 404 in a hash router app.
|
|
283
|
+
if (!pathname.startsWith("/") && !pathname.startsWith(".")) {
|
|
284
|
+
pathname = "/" + pathname;
|
|
285
|
+
}
|
|
270
286
|
return createLocation("", {
|
|
271
287
|
pathname,
|
|
272
288
|
search,
|
|
@@ -401,7 +417,7 @@
|
|
|
401
417
|
v5Compat = false
|
|
402
418
|
} = options;
|
|
403
419
|
let globalHistory = window.history;
|
|
404
|
-
let action =
|
|
420
|
+
let action = Action.Pop;
|
|
405
421
|
let listener = null;
|
|
406
422
|
let index = getIndex();
|
|
407
423
|
// Index should only be null when we initialize. If not, it's because the
|
|
@@ -420,7 +436,7 @@
|
|
|
420
436
|
return state.idx;
|
|
421
437
|
}
|
|
422
438
|
function handlePop() {
|
|
423
|
-
action =
|
|
439
|
+
action = Action.Pop;
|
|
424
440
|
let nextIndex = getIndex();
|
|
425
441
|
let delta = nextIndex == null ? null : nextIndex - index;
|
|
426
442
|
index = nextIndex;
|
|
@@ -433,7 +449,7 @@
|
|
|
433
449
|
}
|
|
434
450
|
}
|
|
435
451
|
function push(to, state) {
|
|
436
|
-
action =
|
|
452
|
+
action = Action.Push;
|
|
437
453
|
let location = createLocation(history.location, to, state);
|
|
438
454
|
if (validateLocation) validateLocation(location, to);
|
|
439
455
|
index = getIndex() + 1;
|
|
@@ -464,7 +480,7 @@
|
|
|
464
480
|
}
|
|
465
481
|
}
|
|
466
482
|
function replace(to, state) {
|
|
467
|
-
action =
|
|
483
|
+
action = Action.Replace;
|
|
468
484
|
let location = createLocation(history.location, to, state);
|
|
469
485
|
if (validateLocation) validateLocation(location, to);
|
|
470
486
|
index = getIndex();
|
|
@@ -534,69 +550,85 @@
|
|
|
534
550
|
* Map of routeId -> data returned from a loader/action/error
|
|
535
551
|
*/
|
|
536
552
|
|
|
537
|
-
let ResultType
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* Successful result from a loader or action
|
|
541
|
-
*/
|
|
542
|
-
(function (ResultType) {
|
|
553
|
+
let ResultType = /*#__PURE__*/function (ResultType) {
|
|
543
554
|
ResultType["data"] = "data";
|
|
544
555
|
ResultType["deferred"] = "deferred";
|
|
545
556
|
ResultType["redirect"] = "redirect";
|
|
546
557
|
ResultType["error"] = "error";
|
|
547
|
-
|
|
558
|
+
return ResultType;
|
|
559
|
+
}({});
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Successful result from a loader or action
|
|
563
|
+
*/
|
|
564
|
+
|
|
548
565
|
/**
|
|
549
566
|
* Successful defer() result from a loader or action
|
|
550
567
|
*/
|
|
568
|
+
|
|
551
569
|
/**
|
|
552
570
|
* Redirect result from a loader or action
|
|
553
571
|
*/
|
|
572
|
+
|
|
554
573
|
/**
|
|
555
574
|
* Unsuccessful result from a loader or action
|
|
556
575
|
*/
|
|
576
|
+
|
|
557
577
|
/**
|
|
558
578
|
* Result from a loader or action - potentially successful or unsuccessful
|
|
559
579
|
*/
|
|
580
|
+
|
|
560
581
|
/**
|
|
561
582
|
* Users can specify either lowercase or uppercase form methods on <Form>,
|
|
562
583
|
* useSubmit(), <fetcher.Form>, etc.
|
|
563
584
|
*/
|
|
585
|
+
|
|
564
586
|
/**
|
|
565
587
|
* Active navigation/fetcher form methods are exposed in lowercase on the
|
|
566
588
|
* RouterState
|
|
567
589
|
*/
|
|
590
|
+
|
|
568
591
|
/**
|
|
569
592
|
* In v7, active navigation/fetcher form methods are exposed in uppercase on the
|
|
570
593
|
* RouterState. This is to align with the normalization done via fetch().
|
|
571
594
|
*/
|
|
595
|
+
|
|
572
596
|
// Thanks https://github.com/sindresorhus/type-fest!
|
|
597
|
+
|
|
573
598
|
/**
|
|
574
599
|
* @private
|
|
575
600
|
* Internal interface to pass around for action submissions, not intended for
|
|
576
601
|
* external consumption
|
|
577
602
|
*/
|
|
603
|
+
|
|
578
604
|
/**
|
|
579
605
|
* @private
|
|
580
606
|
* Arguments passed to route loader/action functions. Same for now but we keep
|
|
581
607
|
* this as a private implementation detail in case they diverge in the future.
|
|
582
608
|
*/
|
|
609
|
+
|
|
583
610
|
/**
|
|
584
611
|
* Arguments passed to loader functions
|
|
585
612
|
*/
|
|
613
|
+
|
|
586
614
|
/**
|
|
587
615
|
* Arguments passed to action functions
|
|
588
616
|
*/
|
|
617
|
+
|
|
589
618
|
/**
|
|
590
619
|
* Loaders and actions can return anything except `undefined` (`null` is a
|
|
591
620
|
* valid return value if there is no data to return). Responses are preferred
|
|
592
621
|
* and will ease any future migration to Remix
|
|
593
622
|
*/
|
|
623
|
+
|
|
594
624
|
/**
|
|
595
625
|
* Route loader function signature
|
|
596
626
|
*/
|
|
627
|
+
|
|
597
628
|
/**
|
|
598
629
|
* Route action function signature
|
|
599
630
|
*/
|
|
631
|
+
|
|
600
632
|
/**
|
|
601
633
|
* Route shouldRevalidate function signature. This runs after any submission
|
|
602
634
|
* (navigation or fetcher), so we flatten the navigation/fetcher submission
|
|
@@ -604,21 +636,25 @@
|
|
|
604
636
|
* or a fetcher, what really matters is the URLs and the formData since loaders
|
|
605
637
|
* have to re-run based on the data models that were potentially mutated.
|
|
606
638
|
*/
|
|
639
|
+
|
|
607
640
|
/**
|
|
608
641
|
* Function provided by the framework-aware layers to set `hasErrorBoundary`
|
|
609
642
|
* from the framework-aware `errorElement` prop
|
|
610
643
|
*
|
|
611
644
|
* @deprecated Use `mapRouteProperties` instead
|
|
612
645
|
*/
|
|
646
|
+
|
|
613
647
|
/**
|
|
614
648
|
* Function provided by the framework-aware layers to set any framework-specific
|
|
615
649
|
* properties from framework-agnostic properties
|
|
616
650
|
*/
|
|
651
|
+
|
|
617
652
|
/**
|
|
618
653
|
* Keys we cannot change from within a lazy() function. We spread all other keys
|
|
619
654
|
* onto the route. Either they're meaningful to the router, or they'll get
|
|
620
655
|
* ignored.
|
|
621
656
|
*/
|
|
657
|
+
|
|
622
658
|
const immutableRouteKeys = new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]);
|
|
623
659
|
|
|
624
660
|
/**
|
|
@@ -1416,6 +1452,17 @@
|
|
|
1416
1452
|
}));
|
|
1417
1453
|
};
|
|
1418
1454
|
|
|
1455
|
+
/**
|
|
1456
|
+
* A redirect response that will force a document reload to the new location.
|
|
1457
|
+
* Sets the status code and the `Location` header.
|
|
1458
|
+
* Defaults to "302 Found".
|
|
1459
|
+
*/
|
|
1460
|
+
const redirectDocument = (url, init) => {
|
|
1461
|
+
let response = redirect(url, init);
|
|
1462
|
+
response.headers.set("X-Remix-Reload-Document", "true");
|
|
1463
|
+
return response;
|
|
1464
|
+
};
|
|
1465
|
+
|
|
1419
1466
|
/**
|
|
1420
1467
|
* @private
|
|
1421
1468
|
* Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
|
|
@@ -1655,7 +1702,7 @@
|
|
|
1655
1702
|
|
|
1656
1703
|
// -- Stateful internal variables to manage navigations --
|
|
1657
1704
|
// Current navigation in progress (to be committed in completeNavigation)
|
|
1658
|
-
let pendingAction =
|
|
1705
|
+
let pendingAction = Action.Pop;
|
|
1659
1706
|
|
|
1660
1707
|
// Should the current navigation prevent the scroll reset if scroll cannot
|
|
1661
1708
|
// be restored?
|
|
@@ -1778,7 +1825,7 @@
|
|
|
1778
1825
|
// resolved prior to router creation since we can't go into a fallbackElement
|
|
1779
1826
|
// UI for SSR'd apps
|
|
1780
1827
|
if (!state.initialized) {
|
|
1781
|
-
startNavigation(
|
|
1828
|
+
startNavigation(Action.Pop, state.location);
|
|
1782
1829
|
}
|
|
1783
1830
|
return router;
|
|
1784
1831
|
}
|
|
@@ -1853,9 +1900,9 @@
|
|
|
1853
1900
|
dataRoutes = inFlightDataRoutes;
|
|
1854
1901
|
inFlightDataRoutes = undefined;
|
|
1855
1902
|
}
|
|
1856
|
-
if (isUninterruptedRevalidation) ; else if (pendingAction ===
|
|
1903
|
+
if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) {
|
|
1857
1904
|
init.history.push(location, location.state);
|
|
1858
|
-
} else if (pendingAction ===
|
|
1905
|
+
} else if (pendingAction === Action.Replace) {
|
|
1859
1906
|
init.history.replace(location, location.state);
|
|
1860
1907
|
}
|
|
1861
1908
|
updateState(_extends({}, newState, {
|
|
@@ -1873,7 +1920,7 @@
|
|
|
1873
1920
|
}));
|
|
1874
1921
|
|
|
1875
1922
|
// Reset stateful navigation vars
|
|
1876
|
-
pendingAction =
|
|
1923
|
+
pendingAction = Action.Pop;
|
|
1877
1924
|
pendingPreventScrollReset = false;
|
|
1878
1925
|
isUninterruptedRevalidation = false;
|
|
1879
1926
|
isRevalidationRequired = false;
|
|
@@ -1904,15 +1951,15 @@
|
|
|
1904
1951
|
// without having to touch history
|
|
1905
1952
|
nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation));
|
|
1906
1953
|
let userReplace = opts && opts.replace != null ? opts.replace : undefined;
|
|
1907
|
-
let historyAction =
|
|
1954
|
+
let historyAction = Action.Push;
|
|
1908
1955
|
if (userReplace === true) {
|
|
1909
|
-
historyAction =
|
|
1956
|
+
historyAction = Action.Replace;
|
|
1910
1957
|
} else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {
|
|
1911
1958
|
// By default on submissions to the current location we REPLACE so that
|
|
1912
1959
|
// users don't have to double-click the back button to get to the prior
|
|
1913
1960
|
// location. If the user redirects to a different location from the
|
|
1914
1961
|
// action/loader this will be ignored and the redirect will be a PUSH
|
|
1915
|
-
historyAction =
|
|
1962
|
+
historyAction = Action.Replace;
|
|
1916
1963
|
}
|
|
1917
1964
|
let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
|
|
1918
1965
|
let blockerKey = shouldBlockNavigation({
|
|
@@ -2159,7 +2206,7 @@
|
|
|
2159
2206
|
// back to PUSH so that the user can use the back button to get back to
|
|
2160
2207
|
// the pre-submission form location to try again
|
|
2161
2208
|
if ((opts && opts.replace) !== true) {
|
|
2162
|
-
pendingAction =
|
|
2209
|
+
pendingAction = Action.Push;
|
|
2163
2210
|
}
|
|
2164
2211
|
return {
|
|
2165
2212
|
// Send back an empty object we can use to clear out any prior actionData
|
|
@@ -2650,11 +2697,20 @@
|
|
|
2650
2697
|
_isFetchActionRedirect: true
|
|
2651
2698
|
} : {}));
|
|
2652
2699
|
invariant(redirectLocation, "Expected a location on the redirect navigation");
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2700
|
+
if (isBrowser) {
|
|
2701
|
+
let isDocumentReload = false;
|
|
2702
|
+
if (redirect.reloadDocument) {
|
|
2703
|
+
// Hard reload if the response contained X-Remix-Reload-Document
|
|
2704
|
+
isDocumentReload = true;
|
|
2705
|
+
} else if (ABSOLUTE_URL_REGEX.test(redirect.location)) {
|
|
2706
|
+
const url = init.history.createURL(redirect.location);
|
|
2707
|
+
isDocumentReload =
|
|
2708
|
+
// Hard reload if it's an absolute URL to a new origin
|
|
2709
|
+
url.origin !== routerWindow.location.origin ||
|
|
2710
|
+
// Hard reload if it's an absolute URL that does not match our basename
|
|
2711
|
+
stripBasename(url.pathname, basename) == null;
|
|
2712
|
+
}
|
|
2713
|
+
if (isDocumentReload) {
|
|
2658
2714
|
if (replace) {
|
|
2659
2715
|
routerWindow.location.replace(redirect.location);
|
|
2660
2716
|
} else {
|
|
@@ -2667,7 +2723,7 @@
|
|
|
2667
2723
|
// There's no need to abort on redirects, since we don't detect the
|
|
2668
2724
|
// redirect until the action/loaders have settled
|
|
2669
2725
|
pendingNavigationController = null;
|
|
2670
|
-
let redirectHistoryAction = replace === true ?
|
|
2726
|
+
let redirectHistoryAction = replace === true ? Action.Replace : Action.Push;
|
|
2671
2727
|
|
|
2672
2728
|
// Use the incoming submission if provided, fallback on the active one in
|
|
2673
2729
|
// state.navigation
|
|
@@ -3180,7 +3236,7 @@
|
|
|
3180
3236
|
// it to bail out and then return or throw here based on whether the user
|
|
3181
3237
|
// returned or threw
|
|
3182
3238
|
if (isQueryRouteResponse(e)) {
|
|
3183
|
-
if (e.type === ResultType.error
|
|
3239
|
+
if (e.type === ResultType.error) {
|
|
3184
3240
|
throw e.response;
|
|
3185
3241
|
}
|
|
3186
3242
|
return e.response;
|
|
@@ -3873,7 +3929,8 @@
|
|
|
3873
3929
|
type: ResultType.redirect,
|
|
3874
3930
|
status,
|
|
3875
3931
|
location,
|
|
3876
|
-
revalidate: result.headers.get("X-Remix-Revalidate") !== null
|
|
3932
|
+
revalidate: result.headers.get("X-Remix-Revalidate") !== null,
|
|
3933
|
+
reloadDocument: result.headers.get("X-Remix-Reload-Document") !== null
|
|
3877
3934
|
};
|
|
3878
3935
|
}
|
|
3879
3936
|
|
|
@@ -3881,11 +3938,11 @@
|
|
|
3881
3938
|
// without unwrapping. We do this with the QueryRouteResponse wrapper
|
|
3882
3939
|
// interface so we can know whether it was returned or thrown
|
|
3883
3940
|
if (opts.isRouteRequest) {
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
type: resultType || ResultType.data,
|
|
3941
|
+
let queryRouteResponse = {
|
|
3942
|
+
type: resultType === ResultType.error ? ResultType.error : ResultType.data,
|
|
3887
3943
|
response: result
|
|
3888
3944
|
};
|
|
3945
|
+
throw queryRouteResponse;
|
|
3889
3946
|
}
|
|
3890
3947
|
let data;
|
|
3891
3948
|
let contentType = result.headers.get("Content-Type");
|
|
@@ -4243,7 +4300,7 @@
|
|
|
4243
4300
|
return status >= 300 && status <= 399 && location != null;
|
|
4244
4301
|
}
|
|
4245
4302
|
function isQueryRouteResponse(obj) {
|
|
4246
|
-
return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error);
|
|
4303
|
+
return obj && isResponse(obj.response) && (obj.type === ResultType.data || obj.type === ResultType.error);
|
|
4247
4304
|
}
|
|
4248
4305
|
function isValidMethod(method) {
|
|
4249
4306
|
return validRequestMethods.has(method.toLowerCase());
|
|
@@ -4476,6 +4533,7 @@
|
|
|
4476
4533
|
//#endregion
|
|
4477
4534
|
|
|
4478
4535
|
exports.AbortedDeferredError = AbortedDeferredError;
|
|
4536
|
+
exports.Action = Action;
|
|
4479
4537
|
exports.ErrorResponse = ErrorResponse;
|
|
4480
4538
|
exports.IDLE_BLOCKER = IDLE_BLOCKER;
|
|
4481
4539
|
exports.IDLE_FETCHER = IDLE_FETCHER;
|
|
@@ -4505,6 +4563,7 @@
|
|
|
4505
4563
|
exports.normalizePathname = normalizePathname;
|
|
4506
4564
|
exports.parsePath = parsePath;
|
|
4507
4565
|
exports.redirect = redirect;
|
|
4566
|
+
exports.redirectDocument = redirectDocument;
|
|
4508
4567
|
exports.resolvePath = resolvePath;
|
|
4509
4568
|
exports.resolveTo = resolveTo;
|
|
4510
4569
|
exports.stripBasename = stripBasename;
|