react-router-dom 6.16.0 → 6.17.0-pre.1

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 CHANGED
@@ -1,5 +1,64 @@
1
1
  # `react-router-dom`
2
2
 
3
+ ## 6.17.0-pre.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies:
8
+ - `react-router@6.17.0-pre.1`
9
+
10
+ ## 6.17.0-pre.0
11
+
12
+ ### Minor Changes
13
+
14
+ - Add support for the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) via `document.startViewTransition` to enable CSS animated transitions on SPA navigations in your application. ([#10916](https://github.com/remix-run/react-router/pull/10916))
15
+
16
+ The simplest approach to enabling a View Transition in your React Router app is via the new `<Link unstable_viewTransition>` prop. This will cause the navigation DOM update to be wrapped in `document.startViewTransition` which will enable transitions for the DOM update. Without any additional CSS styles, you'll get a basic cross-fade animation for your page.
17
+
18
+ If you need to apply more fine-grained styles for your animations, you can leverage the `unstable_useViewTransitionState` hook which will tell you when a transition is in progress and you can use that to apply classes or styles:
19
+
20
+ ```jsx
21
+ function ImageLink(to, src, alt) {
22
+ let isTransitioning = unstable_useViewTransitionState(to);
23
+ return (
24
+ <Link to={to} unstable_viewTransition>
25
+ <img
26
+ src={src}
27
+ alt={alt}
28
+ style={{
29
+ viewTransitionName: isTransitioning ? "image-expand" : "",
30
+ }}
31
+ />
32
+ </Link>
33
+ );
34
+ }
35
+ ```
36
+
37
+ You can also use the `<NavLink unstable_viewTransition>` shorthand which will manage the hook usage for you and automatically add a `transitioning` class to the `<a>` during the transition:
38
+
39
+ ```css
40
+ a.transitioning img {
41
+ view-transition-name: "image-expand";
42
+ }
43
+ ```
44
+
45
+ ```jsx
46
+ <NavLink to={to} unstable_viewTransition>
47
+ <img src={src} alt={alt} />
48
+ </NavLink>
49
+ ```
50
+
51
+ For an example usage of View Transitions with React Router, check out [our fork](https://github.com/brophdawg11/react-router-records) of the [Astro Records](https://github.com/Charca/astro-records) demo.
52
+
53
+ For more information on using the View Transitions API, please refer to the [Smooth and simple transitions with the View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) guide from the Google Chrome team.
54
+
55
+ ### Patch Changes
56
+
57
+ - Log a warning and fail gracefully in `ScrollRestoration` when `sessionStorage` is unavailable ([#10848](https://github.com/remix-run/react-router/pull/10848))
58
+ - Updated dependencies:
59
+ - `@remix-run/router@1.10.0-pre.0`
60
+ - `react-router@6.17.0-pre.0`
61
+
3
62
  ## 6.16.0
4
63
 
5
64
  ### Minor Changes
package/dist/dom.d.ts CHANGED
@@ -77,6 +77,10 @@ export interface SubmitOptions {
77
77
  * navigation when using the <ScrollRestoration> component
78
78
  */
79
79
  preventScrollReset?: boolean;
80
+ /**
81
+ * Enable view transitions on this submission navigation
82
+ */
83
+ unstable_viewTransition?: boolean;
80
84
  }
81
85
  export declare function getFormSubmissionInfo(target: SubmitTarget, basename: string): {
82
86
  action: string | null;
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ export { createSearchParams };
12
12
  export type { ActionFunction, ActionFunctionArgs, AwaitProps, unstable_Blocker, unstable_BlockerFunction, DataRouteMatch, DataRouteObject, ErrorResponse, Fetcher, Hash, IndexRouteObject, IndexRouteProps, JsonFunction, LazyRouteFunction, LayoutRouteProps, LoaderFunction, LoaderFunctionArgs, Location, MemoryRouterProps, NavigateFunction, NavigateOptions, NavigateProps, Navigation, Navigator, NonIndexRouteObject, OutletProps, Params, ParamParseKey, Path, PathMatch, Pathname, PathPattern, PathRouteProps, RedirectFunction, RelativeRoutingType, RouteMatch, RouteObject, RouteProps, RouterProps, RouterProviderProps, RoutesProps, Search, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, To, UIMatch, } from "react-router";
13
13
  export { AbortedDeferredError, Await, MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, RouterProvider, Routes, createMemoryRouter, createPath, createRoutesFromChildren, createRoutesFromElements, defer, isRouteErrorResponse, generatePath, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, renderMatches, resolvePath, useActionData, useAsyncError, useAsyncValue, unstable_useBlocker, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes, } from "react-router";
14
14
  /** @internal */
15
- export { UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_NavigationContext, UNSAFE_LocationContext, UNSAFE_RouteContext, UNSAFE_useRouteId, } from "react-router";
15
+ export { UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_NavigationContext, UNSAFE_LocationContext, UNSAFE_RouteContext, UNSAFE_ViewTransitionContext, UNSAFE_useRouteId, } from "react-router";
16
16
  declare global {
17
17
  var __staticRouterHydrationData: HydrationState | undefined;
18
18
  }
@@ -69,29 +69,27 @@ export interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEle
69
69
  preventScrollReset?: boolean;
70
70
  relative?: RelativeRoutingType;
71
71
  to: To;
72
+ unstable_viewTransition?: boolean;
72
73
  }
73
74
  /**
74
- * The public API for rendering a history-aware <a>.
75
+ * The public API for rendering a history-aware `<a>`.
75
76
  */
76
77
  export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
78
+ type NavLinkRenderProps = {
79
+ isActive: boolean;
80
+ isPending: boolean;
81
+ isTransitioning: boolean;
82
+ };
77
83
  export interface NavLinkProps extends Omit<LinkProps, "className" | "style" | "children"> {
78
- children?: React.ReactNode | ((props: {
79
- isActive: boolean;
80
- isPending: boolean;
81
- }) => React.ReactNode);
84
+ children?: React.ReactNode | ((props: NavLinkRenderProps) => React.ReactNode);
82
85
  caseSensitive?: boolean;
83
- className?: string | ((props: {
84
- isActive: boolean;
85
- isPending: boolean;
86
- }) => string | undefined);
86
+ className?: string | ((props: NavLinkRenderProps) => string | undefined);
87
87
  end?: boolean;
88
- style?: React.CSSProperties | ((props: {
89
- isActive: boolean;
90
- isPending: boolean;
91
- }) => React.CSSProperties | undefined);
88
+ style?: React.CSSProperties | ((props: NavLinkRenderProps) => React.CSSProperties | undefined);
89
+ unstable_viewTransition?: boolean;
92
90
  }
93
91
  /**
94
- * A <Link> wrapper that knows if it's "active" or not.
92
+ * A `<Link>` wrapper that knows if it's "active" or not.
95
93
  */
96
94
  export declare const NavLink: React.ForwardRefExoticComponent<NavLinkProps & React.RefAttributes<HTMLAnchorElement>>;
97
95
  export interface FetcherFormProps extends React.FormHTMLAttributes<HTMLFormElement> {
@@ -141,6 +139,10 @@ export interface FormProps extends FetcherFormProps {
141
139
  * State object to add to the history stack entry for this navigation
142
140
  */
143
141
  state?: any;
142
+ /**
143
+ * Enable view transitions on this Form navigation
144
+ */
145
+ unstable_viewTransition?: boolean;
144
146
  }
145
147
  /**
146
148
  * A `@remix-run/router`-aware `<form>`. It behaves like a normal form except
@@ -166,12 +168,13 @@ export declare namespace ScrollRestoration {
166
168
  * you need to create custom `<Link>` components with the same click behavior we
167
169
  * use in our exported `<Link>`.
168
170
  */
169
- export declare function useLinkClickHandler<E extends Element = HTMLAnchorElement>(to: To, { target, replace: replaceProp, state, preventScrollReset, relative, }?: {
171
+ export declare function useLinkClickHandler<E extends Element = HTMLAnchorElement>(to: To, { target, replace: replaceProp, state, preventScrollReset, relative, unstable_viewTransition, }?: {
170
172
  target?: React.HTMLAttributeAnchorTarget;
171
173
  replace?: boolean;
172
174
  state?: any;
173
175
  preventScrollReset?: boolean;
174
176
  relative?: RelativeRoutingType;
177
+ unstable_viewTransition?: boolean;
175
178
  }): (event: React.MouseEvent<E, MouseEvent>) => void;
176
179
  /**
177
180
  * A convenient wrapper for reading and writing search parameters via the
@@ -261,3 +264,15 @@ declare function usePrompt({ when, message }: {
261
264
  message: string;
262
265
  }): void;
263
266
  export { usePrompt as unstable_usePrompt };
267
+ /**
268
+ * Return a boolean indicating if there is an active view transition to the
269
+ * given href. You can use this value to render CSS classes or viewTransitionName
270
+ * styles onto your elements
271
+ *
272
+ * @param href The destination href
273
+ * @param [opts.relative] Relative routing type ("route" | "path")
274
+ */
275
+ declare function useViewTransitionState(to: To, opts?: {
276
+ relative?: RelativeRoutingType;
277
+ }): boolean;
278
+ export { useViewTransitionState as unstable_useViewTransitionState };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * React Router DOM v6.16.0
2
+ * React Router DOM v6.17.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -9,9 +9,9 @@
9
9
  * @license MIT
10
10
  */
11
11
  import * as React from 'react';
12
- import { UNSAFE_mapRouteProperties, Router, UNSAFE_NavigationContext, useHref, useResolvedPath, useLocation, UNSAFE_DataRouterStateContext, useNavigate, createPath, UNSAFE_useRouteId, UNSAFE_RouteContext, useMatches, useNavigation, unstable_useBlocker, UNSAFE_DataRouterContext } from 'react-router';
13
- export { AbortedDeferredError, Await, MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, RouterProvider, Routes, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, UNSAFE_useRouteId, createMemoryRouter, createPath, createRoutesFromChildren, createRoutesFromElements, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, renderMatches, resolvePath, unstable_useBlocker, useActionData, useAsyncError, useAsyncValue, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes } from 'react-router';
14
- import { stripBasename, UNSAFE_warning, createRouter, createBrowserHistory, createHashHistory, UNSAFE_ErrorResponseImpl, UNSAFE_invariant, joinPaths } from '@remix-run/router';
12
+ import { UNSAFE_mapRouteProperties, Router, UNSAFE_NavigationContext, useHref, useResolvedPath, useLocation, UNSAFE_DataRouterStateContext, useNavigate, createPath, UNSAFE_useRouteId, UNSAFE_RouteContext, useMatches, useNavigation, unstable_useBlocker, UNSAFE_ViewTransitionContext, UNSAFE_DataRouterContext } from 'react-router';
13
+ export { AbortedDeferredError, Await, MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, RouterProvider, Routes, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, UNSAFE_ViewTransitionContext, UNSAFE_useRouteId, createMemoryRouter, createPath, createRoutesFromChildren, createRoutesFromElements, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, redirectDocument, renderMatches, resolvePath, unstable_useBlocker, useActionData, useAsyncError, useAsyncValue, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes } from 'react-router';
14
+ import { stripBasename, UNSAFE_warning, createRouter, createBrowserHistory, createHashHistory, UNSAFE_ErrorResponseImpl, UNSAFE_invariant, joinPaths, matchPath } from '@remix-run/router';
15
15
 
16
16
  function _extends() {
17
17
  _extends = Object.assign ? Object.assign.bind() : function (target) {
@@ -206,9 +206,9 @@ function getFormSubmissionInfo(target, basename) {
206
206
  };
207
207
  }
208
208
 
209
- const _excluded = ["onClick", "relative", "reloadDocument", "replace", "state", "target", "to", "preventScrollReset"],
210
- _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "children"],
211
- _excluded3 = ["reloadDocument", "replace", "state", "method", "action", "onSubmit", "submit", "relative", "preventScrollReset"];
209
+ const _excluded = ["onClick", "relative", "reloadDocument", "replace", "state", "target", "to", "preventScrollReset", "unstable_viewTransition"],
210
+ _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "unstable_viewTransition", "children"],
211
+ _excluded3 = ["reloadDocument", "replace", "state", "method", "action", "onSubmit", "submit", "relative", "preventScrollReset", "unstable_viewTransition"];
212
212
  function createBrowserRouter(routes, opts) {
213
213
  return createRouter({
214
214
  basename: opts == null ? void 0 : opts.basename,
@@ -220,7 +220,8 @@ function createBrowserRouter(routes, opts) {
220
220
  }),
221
221
  hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
222
222
  routes,
223
- mapRouteProperties: UNSAFE_mapRouteProperties
223
+ mapRouteProperties: UNSAFE_mapRouteProperties,
224
+ window: opts == null ? void 0 : opts.window
224
225
  }).initialize();
225
226
  }
226
227
  function createHashRouter(routes, opts) {
@@ -234,7 +235,8 @@ function createHashRouter(routes, opts) {
234
235
  }),
235
236
  hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
236
237
  routes,
237
- mapRouteProperties: UNSAFE_mapRouteProperties
238
+ mapRouteProperties: UNSAFE_mapRouteProperties,
239
+ window: opts == null ? void 0 : opts.window
238
240
  }).initialize();
239
241
  }
240
242
  function parseHydrationData() {
@@ -426,7 +428,7 @@ if (process.env.NODE_ENV !== "production") {
426
428
  const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
427
429
  const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
428
430
  /**
429
- * The public API for rendering a history-aware <a>.
431
+ * The public API for rendering a history-aware `<a>`.
430
432
  */
431
433
  const Link = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref4, ref) {
432
434
  let {
@@ -437,7 +439,8 @@ const Link = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref4, ref) {
437
439
  state,
438
440
  target,
439
441
  to,
440
- preventScrollReset
442
+ preventScrollReset,
443
+ unstable_viewTransition
441
444
  } = _ref4,
442
445
  rest = _objectWithoutPropertiesLoose(_ref4, _excluded);
443
446
  let {
@@ -476,7 +479,8 @@ const Link = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref4, ref) {
476
479
  state,
477
480
  target,
478
481
  preventScrollReset,
479
- relative
482
+ relative,
483
+ unstable_viewTransition
480
484
  });
481
485
  function handleClick(event) {
482
486
  if (onClick) onClick(event);
@@ -499,7 +503,7 @@ if (process.env.NODE_ENV !== "production") {
499
503
  Link.displayName = "Link";
500
504
  }
501
505
  /**
502
- * A <Link> wrapper that knows if it's "active" or not.
506
+ * A `<Link>` wrapper that knows if it's "active" or not.
503
507
  */
504
508
  const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref5, ref) {
505
509
  let {
@@ -509,6 +513,7 @@ const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref5, ref
509
513
  end = false,
510
514
  style: styleProp,
511
515
  to,
516
+ unstable_viewTransition,
512
517
  children
513
518
  } = _ref5,
514
519
  rest = _objectWithoutPropertiesLoose(_ref5, _excluded2);
@@ -520,6 +525,10 @@ const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref5, ref
520
525
  let {
521
526
  navigator
522
527
  } = React.useContext(UNSAFE_NavigationContext);
528
+ let isTransitioning = routerState != null &&
529
+ // Conditional usage is OK here because the usage of a data router is static
530
+ // eslint-disable-next-line react-hooks/rules-of-hooks
531
+ useViewTransitionState(path) && unstable_viewTransition === true;
523
532
  let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
524
533
  let locationPathname = location.pathname;
525
534
  let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
@@ -530,35 +539,32 @@ const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref5, ref
530
539
  }
531
540
  let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(toPathname.length) === "/";
532
541
  let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
542
+ let renderProps = {
543
+ isActive,
544
+ isPending,
545
+ isTransitioning
546
+ };
533
547
  let ariaCurrent = isActive ? ariaCurrentProp : undefined;
534
548
  let className;
535
549
  if (typeof classNameProp === "function") {
536
- className = classNameProp({
537
- isActive,
538
- isPending
539
- });
550
+ className = classNameProp(renderProps);
540
551
  } else {
541
552
  // If the className prop is not a function, we use a default `active`
542
553
  // class for <NavLink />s that are active. In v5 `active` was the default
543
554
  // value for `activeClassName`, but we are removing that API and can still
544
555
  // use the old default behavior for a cleaner upgrade path and keep the
545
556
  // simple styling rules working as they currently do.
546
- className = [classNameProp, isActive ? "active" : null, isPending ? "pending" : null].filter(Boolean).join(" ");
557
+ className = [classNameProp, isActive ? "active" : null, isPending ? "pending" : null, isTransitioning ? "transitioning" : null].filter(Boolean).join(" ");
547
558
  }
548
- let style = typeof styleProp === "function" ? styleProp({
549
- isActive,
550
- isPending
551
- }) : styleProp;
559
+ let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
552
560
  return /*#__PURE__*/React.createElement(Link, _extends({}, rest, {
553
561
  "aria-current": ariaCurrent,
554
562
  className: className,
555
563
  ref: ref,
556
564
  style: style,
557
- to: to
558
- }), typeof children === "function" ? children({
559
- isActive,
560
- isPending
561
- }) : children);
565
+ to: to,
566
+ unstable_viewTransition: unstable_viewTransition
567
+ }), typeof children === "function" ? children(renderProps) : children);
562
568
  });
563
569
  if (process.env.NODE_ENV !== "production") {
564
570
  NavLink.displayName = "NavLink";
@@ -589,7 +595,8 @@ const FormImpl = /*#__PURE__*/React.forwardRef((_ref6, forwardedRef) => {
589
595
  onSubmit,
590
596
  submit,
591
597
  relative,
592
- preventScrollReset
598
+ preventScrollReset,
599
+ unstable_viewTransition
593
600
  } = _ref6,
594
601
  props = _objectWithoutPropertiesLoose(_ref6, _excluded3);
595
602
  let formMethod = method.toLowerCase() === "get" ? "get" : "post";
@@ -607,7 +614,8 @@ const FormImpl = /*#__PURE__*/React.forwardRef((_ref6, forwardedRef) => {
607
614
  replace,
608
615
  state,
609
616
  relative,
610
- preventScrollReset
617
+ preventScrollReset,
618
+ unstable_viewTransition
611
619
  });
612
620
  };
613
621
  return /*#__PURE__*/React.createElement("form", _extends({
@@ -648,6 +656,8 @@ var DataRouterHook;
648
656
  DataRouterHook["UseSubmit"] = "useSubmit";
649
657
  DataRouterHook["UseSubmitFetcher"] = "useSubmitFetcher";
650
658
  DataRouterHook["UseFetcher"] = "useFetcher";
659
+ DataRouterHook["useViewTransitionStates"] = "useViewTransitionStates";
660
+ DataRouterHook["useViewTransitionState"] = "useViewTransitionState";
651
661
  })(DataRouterHook || (DataRouterHook = {}));
652
662
  var DataRouterStateHook;
653
663
  (function (DataRouterStateHook) {
@@ -678,7 +688,8 @@ function useLinkClickHandler(to, _temp) {
678
688
  replace: replaceProp,
679
689
  state,
680
690
  preventScrollReset,
681
- relative
691
+ relative,
692
+ unstable_viewTransition
682
693
  } = _temp === void 0 ? {} : _temp;
683
694
  let navigate = useNavigate();
684
695
  let location = useLocation();
@@ -695,10 +706,11 @@ function useLinkClickHandler(to, _temp) {
695
706
  replace,
696
707
  state,
697
708
  preventScrollReset,
698
- relative
709
+ relative,
710
+ unstable_viewTransition
699
711
  });
700
712
  }
701
- }, [location, navigate, path, replaceProp, state, target, to, preventScrollReset, relative]);
713
+ }, [location, navigate, path, replaceProp, state, target, to, preventScrollReset, relative, unstable_viewTransition]);
702
714
  }
703
715
  /**
704
716
  * A convenient wrapper for reading and writing search parameters via the
@@ -759,7 +771,8 @@ function useSubmit() {
759
771
  formEncType: options.encType || encType,
760
772
  replace: options.replace,
761
773
  state: options.state,
762
- fromRouteId: currentRouteId
774
+ fromRouteId: currentRouteId,
775
+ unstable_viewTransition: options.unstable_viewTransition
763
776
  });
764
777
  }, [router, basename, currentRouteId]);
765
778
  }
@@ -946,7 +959,11 @@ function useScrollRestoration(_temp3) {
946
959
  let key = (getKey ? getKey(location, matches) : null) || location.key;
947
960
  savedScrollPositions[key] = window.scrollY;
948
961
  }
949
- sessionStorage.setItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY, JSON.stringify(savedScrollPositions));
962
+ try {
963
+ sessionStorage.setItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY, JSON.stringify(savedScrollPositions));
964
+ } catch (error) {
965
+ process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (" + error + ").") : void 0;
966
+ }
950
967
  window.history.scrollRestoration = "auto";
951
968
  }, [storageKey, getKey, navigation.state, location, matches]));
952
969
  // Read in any saved scroll locations
@@ -1078,7 +1095,46 @@ function usePrompt(_ref8) {
1078
1095
  }
1079
1096
  }, [blocker, when]);
1080
1097
  }
1098
+ /**
1099
+ * Return a boolean indicating if there is an active view transition to the
1100
+ * given href. You can use this value to render CSS classes or viewTransitionName
1101
+ * styles onto your elements
1102
+ *
1103
+ * @param href The destination href
1104
+ * @param [opts.relative] Relative routing type ("route" | "path")
1105
+ */
1106
+ function useViewTransitionState(to, opts) {
1107
+ if (opts === void 0) {
1108
+ opts = {};
1109
+ }
1110
+ let vtContext = React.useContext(UNSAFE_ViewTransitionContext);
1111
+ let {
1112
+ basename
1113
+ } = useDataRouterContext(DataRouterHook.useViewTransitionState);
1114
+ let path = useResolvedPath(to, {
1115
+ relative: opts.relative
1116
+ });
1117
+ if (vtContext.isTransitioning) {
1118
+ let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
1119
+ let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
1120
+ // Transition is active if we're going to or coming from the indicated
1121
+ // destination. This ensures that other PUSH navigations that reverse
1122
+ // an indicated transition apply. I.e., on the list view you have:
1123
+ //
1124
+ // <NavLink to="/details/1" unstable_viewTransition>
1125
+ //
1126
+ // If you click the breadcrumb back to the list view:
1127
+ //
1128
+ // <NavLink to="/list" unstable_viewTransition>
1129
+ //
1130
+ // We should apply the transition because it's indicated as active going
1131
+ // from /list -> /details/1 and therefore should be active on the reverse
1132
+ // (even though this isn't strictly a POP reverse)
1133
+ return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
1134
+ }
1135
+ return false;
1136
+ }
1081
1137
  //#endregion
1082
1138
 
1083
- export { BrowserRouter, Form, HashRouter, Link, NavLink, ScrollRestoration, useScrollRestoration as UNSAFE_useScrollRestoration, createBrowserRouter, createHashRouter, createSearchParams, HistoryRouter as unstable_HistoryRouter, usePrompt as unstable_usePrompt, useBeforeUnload, useFetcher, useFetchers, useFormAction, useLinkClickHandler, useSearchParams, useSubmit };
1139
+ export { BrowserRouter, Form, HashRouter, Link, NavLink, ScrollRestoration, useScrollRestoration as UNSAFE_useScrollRestoration, createBrowserRouter, createHashRouter, createSearchParams, HistoryRouter as unstable_HistoryRouter, usePrompt as unstable_usePrompt, useViewTransitionState as unstable_useViewTransitionState, useBeforeUnload, useFetcher, useFetchers, useFormAction, useLinkClickHandler, useSearchParams, useSubmit };
1084
1140
  //# sourceMappingURL=index.js.map