@remix-run/router 1.9.0 → 1.10.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/router.cjs.js +103 -12
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +15 -1
- package/dist/router.js +96 -6
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +103 -12
- 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 +12 -4
- package/package.json +1 -1
- package/router.ts +168 -23
- package/utils.ts +13 -8
package/dist/router.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.10.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -576,8 +576,8 @@
|
|
|
576
576
|
*/
|
|
577
577
|
|
|
578
578
|
/**
|
|
579
|
-
* Users can specify either lowercase or uppercase form methods on
|
|
580
|
-
* useSubmit(),
|
|
579
|
+
* Users can specify either lowercase or uppercase form methods on `<Form>`,
|
|
580
|
+
* useSubmit(), `<fetcher.Form>`, etc.
|
|
581
581
|
*/
|
|
582
582
|
|
|
583
583
|
/**
|
|
@@ -1470,10 +1470,13 @@
|
|
|
1470
1470
|
response.headers.set("X-Remix-Reload-Document", "true");
|
|
1471
1471
|
return response;
|
|
1472
1472
|
};
|
|
1473
|
-
|
|
1474
1473
|
/**
|
|
1475
1474
|
* @private
|
|
1476
1475
|
* Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
|
|
1476
|
+
*
|
|
1477
|
+
* We don't export the class for public use since it's an implementation
|
|
1478
|
+
* detail, but we export the interface above so folks can build their own
|
|
1479
|
+
* abstractions around instances via isRouteErrorResponse()
|
|
1477
1480
|
*/
|
|
1478
1481
|
class ErrorResponseImpl {
|
|
1479
1482
|
constructor(status, statusText, data, internal) {
|
|
@@ -1492,9 +1495,6 @@
|
|
|
1492
1495
|
}
|
|
1493
1496
|
}
|
|
1494
1497
|
|
|
1495
|
-
// We don't want the class exported since usage of it at runtime is an
|
|
1496
|
-
// implementation detail, but we do want to export the shape so folks can
|
|
1497
|
-
// build their own abstractions around instances via isRouteErrorResponse()
|
|
1498
1498
|
/**
|
|
1499
1499
|
* Check if the given error is an ErrorResponse generated from a 4xx/5xx
|
|
1500
1500
|
* Response thrown from an action/loader
|
|
@@ -1614,6 +1614,7 @@
|
|
|
1614
1614
|
const defaultMapRouteProperties = route => ({
|
|
1615
1615
|
hasErrorBoundary: Boolean(route.hasErrorBoundary)
|
|
1616
1616
|
});
|
|
1617
|
+
const TRANSITIONS_STORAGE_KEY = "remix-router-transitions";
|
|
1617
1618
|
|
|
1618
1619
|
//#endregion
|
|
1619
1620
|
|
|
@@ -1722,6 +1723,15 @@
|
|
|
1722
1723
|
// AbortController for the active navigation
|
|
1723
1724
|
let pendingNavigationController;
|
|
1724
1725
|
|
|
1726
|
+
// Should the current navigation enable document.startViewTransition?
|
|
1727
|
+
let pendingViewTransitionEnabled = false;
|
|
1728
|
+
|
|
1729
|
+
// Store applied view transitions so we can apply them on POP
|
|
1730
|
+
let appliedViewTransitions = new Map();
|
|
1731
|
+
|
|
1732
|
+
// Cleanup function for persisting applied transitions to sessionStorage
|
|
1733
|
+
let removePageHideEventListener = null;
|
|
1734
|
+
|
|
1725
1735
|
// We use this to avoid touching history in completeNavigation if a
|
|
1726
1736
|
// revalidation is entirely uninterrupted
|
|
1727
1737
|
let isUninterruptedRevalidation = false;
|
|
@@ -1829,6 +1839,14 @@
|
|
|
1829
1839
|
}
|
|
1830
1840
|
return startNavigation(historyAction, location);
|
|
1831
1841
|
});
|
|
1842
|
+
if (isBrowser) {
|
|
1843
|
+
// FIXME: This feels gross. How can we cleanup the lines between
|
|
1844
|
+
// scrollRestoration/appliedTransitions persistance?
|
|
1845
|
+
restoreAppliedTransitions(routerWindow, appliedViewTransitions);
|
|
1846
|
+
let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions);
|
|
1847
|
+
routerWindow.addEventListener("pagehide", _saveAppliedTransitions);
|
|
1848
|
+
removePageHideEventListener = () => routerWindow.removeEventListener("pagehide", _saveAppliedTransitions);
|
|
1849
|
+
}
|
|
1832
1850
|
|
|
1833
1851
|
// Kick off initial data load if needed. Use Pop to avoid modifying history
|
|
1834
1852
|
// Note we don't do any handling of lazy here. For SPA's it'll get handled
|
|
@@ -1846,6 +1864,9 @@
|
|
|
1846
1864
|
if (unlistenHistory) {
|
|
1847
1865
|
unlistenHistory();
|
|
1848
1866
|
}
|
|
1867
|
+
if (removePageHideEventListener) {
|
|
1868
|
+
removePageHideEventListener();
|
|
1869
|
+
}
|
|
1849
1870
|
subscribers.clear();
|
|
1850
1871
|
pendingNavigationController && pendingNavigationController.abort();
|
|
1851
1872
|
state.fetchers.forEach((_, key) => deleteFetcher(key));
|
|
@@ -1859,9 +1880,11 @@
|
|
|
1859
1880
|
}
|
|
1860
1881
|
|
|
1861
1882
|
// Update our state and notify the calling context of the change
|
|
1862
|
-
function updateState(newState) {
|
|
1883
|
+
function updateState(newState, viewTransitionOpts) {
|
|
1863
1884
|
state = _extends({}, state, newState);
|
|
1864
|
-
subscribers.forEach(subscriber => subscriber(state
|
|
1885
|
+
subscribers.forEach(subscriber => subscriber(state, {
|
|
1886
|
+
unstable_viewTransitionOpts: viewTransitionOpts
|
|
1887
|
+
}));
|
|
1865
1888
|
}
|
|
1866
1889
|
|
|
1867
1890
|
// Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
|
|
@@ -1916,6 +1939,39 @@
|
|
|
1916
1939
|
} else if (pendingAction === Action.Replace) {
|
|
1917
1940
|
init.history.replace(location, location.state);
|
|
1918
1941
|
}
|
|
1942
|
+
let viewTransitionOpts;
|
|
1943
|
+
|
|
1944
|
+
// On POP, enable transitions if they were enabled on the original navigation
|
|
1945
|
+
if (pendingAction === Action.Pop) {
|
|
1946
|
+
// Forward takes precedence so they behave like the original navigation
|
|
1947
|
+
let priorPaths = appliedViewTransitions.get(state.location.pathname);
|
|
1948
|
+
if (priorPaths && priorPaths.has(location.pathname)) {
|
|
1949
|
+
viewTransitionOpts = {
|
|
1950
|
+
currentLocation: state.location,
|
|
1951
|
+
nextLocation: location
|
|
1952
|
+
};
|
|
1953
|
+
} else if (appliedViewTransitions.has(location.pathname)) {
|
|
1954
|
+
// If we don't have a previous forward nav, assume we're popping back to
|
|
1955
|
+
// the new location and enable if that location previously enabled
|
|
1956
|
+
viewTransitionOpts = {
|
|
1957
|
+
currentLocation: location,
|
|
1958
|
+
nextLocation: state.location
|
|
1959
|
+
};
|
|
1960
|
+
}
|
|
1961
|
+
} else if (pendingViewTransitionEnabled) {
|
|
1962
|
+
// Store the applied transition on PUSH/REPLACE
|
|
1963
|
+
let toPaths = appliedViewTransitions.get(state.location.pathname);
|
|
1964
|
+
if (toPaths) {
|
|
1965
|
+
toPaths.add(location.pathname);
|
|
1966
|
+
} else {
|
|
1967
|
+
toPaths = new Set([location.pathname]);
|
|
1968
|
+
appliedViewTransitions.set(state.location.pathname, toPaths);
|
|
1969
|
+
}
|
|
1970
|
+
viewTransitionOpts = {
|
|
1971
|
+
currentLocation: state.location,
|
|
1972
|
+
nextLocation: location
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1919
1975
|
updateState(_extends({}, newState, {
|
|
1920
1976
|
// matches, errors, fetchers go through as-is
|
|
1921
1977
|
actionData,
|
|
@@ -1928,11 +1984,12 @@
|
|
|
1928
1984
|
restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),
|
|
1929
1985
|
preventScrollReset,
|
|
1930
1986
|
blockers
|
|
1931
|
-
}));
|
|
1987
|
+
}), viewTransitionOpts);
|
|
1932
1988
|
|
|
1933
1989
|
// Reset stateful navigation vars
|
|
1934
1990
|
pendingAction = Action.Pop;
|
|
1935
1991
|
pendingPreventScrollReset = false;
|
|
1992
|
+
pendingViewTransitionEnabled = false;
|
|
1936
1993
|
isUninterruptedRevalidation = false;
|
|
1937
1994
|
isRevalidationRequired = false;
|
|
1938
1995
|
cancelledDeferredRoutes = [];
|
|
@@ -2009,7 +2066,8 @@
|
|
|
2009
2066
|
// render at the right error boundary after we match routes
|
|
2010
2067
|
pendingError: error,
|
|
2011
2068
|
preventScrollReset,
|
|
2012
|
-
replace: opts && opts.replace
|
|
2069
|
+
replace: opts && opts.replace,
|
|
2070
|
+
enableViewTransition: opts && opts.unstable_viewTransition
|
|
2013
2071
|
});
|
|
2014
2072
|
}
|
|
2015
2073
|
|
|
@@ -2062,6 +2120,7 @@
|
|
|
2062
2120
|
// and track whether we should reset scroll on completion
|
|
2063
2121
|
saveScrollPosition(state.location, state.matches);
|
|
2064
2122
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
2123
|
+
pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
|
|
2065
2124
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2066
2125
|
let loadingNavigation = opts && opts.overrideNavigation;
|
|
2067
2126
|
let matches = matchRoutes(routesToUse, location, basename);
|
|
@@ -3013,6 +3072,9 @@
|
|
|
3013
3072
|
get routes() {
|
|
3014
3073
|
return dataRoutes;
|
|
3015
3074
|
},
|
|
3075
|
+
get window() {
|
|
3076
|
+
return routerWindow;
|
|
3077
|
+
},
|
|
3016
3078
|
initialize,
|
|
3017
3079
|
subscribe,
|
|
3018
3080
|
enableScrollRestoration,
|
|
@@ -4209,7 +4271,7 @@
|
|
|
4209
4271
|
}
|
|
4210
4272
|
function getShortCircuitMatches(routes) {
|
|
4211
4273
|
// Prefer a root layout route if present, otherwise shim in a route object
|
|
4212
|
-
let route = routes.find(r => r.index || !r.path || r.path === "/") || {
|
|
4274
|
+
let route = routes.length === 1 ? routes[0] : routes.find(r => r.index || !r.path || r.path === "/") || {
|
|
4213
4275
|
id: "__shim-error-route__"
|
|
4214
4276
|
};
|
|
4215
4277
|
return {
|
|
@@ -4528,6 +4590,35 @@
|
|
|
4528
4590
|
};
|
|
4529
4591
|
return fetcher;
|
|
4530
4592
|
}
|
|
4593
|
+
function restoreAppliedTransitions(_window, transitions) {
|
|
4594
|
+
try {
|
|
4595
|
+
let sessionPositions = _window.sessionStorage.getItem(TRANSITIONS_STORAGE_KEY);
|
|
4596
|
+
if (sessionPositions) {
|
|
4597
|
+
let json = JSON.parse(sessionPositions);
|
|
4598
|
+
for (let [k, v] of Object.entries(json || {})) {
|
|
4599
|
+
if (v && Array.isArray(v)) {
|
|
4600
|
+
transitions.set(k, new Set(v || []));
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
4604
|
+
} catch (e) {
|
|
4605
|
+
// no-op, use default empty object
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
function persistAppliedTransitions(_window, transitions) {
|
|
4609
|
+
if (transitions.size > 0) {
|
|
4610
|
+
let json = {};
|
|
4611
|
+
for (let [k, v] of transitions) {
|
|
4612
|
+
json[k] = [...v];
|
|
4613
|
+
}
|
|
4614
|
+
try {
|
|
4615
|
+
_window.sessionStorage.setItem(TRANSITIONS_STORAGE_KEY, JSON.stringify(json));
|
|
4616
|
+
} catch (error) {
|
|
4617
|
+
warning(false, "Failed to save applied view transitions in sessionStorage (" + error + ").");
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
|
|
4531
4622
|
//#endregion
|
|
4532
4623
|
|
|
4533
4624
|
exports.AbortedDeferredError = AbortedDeferredError;
|