source: imaps-frontend/node_modules/react-router-dom/dist/index.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 55.2 KB
Line 
1/**
2 * React Router DOM v6.26.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import * as React from 'react';
12import * as ReactDOM from 'react-dom';
13import { UNSAFE_mapRouteProperties, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, Router, UNSAFE_useRoutesImpl, UNSAFE_NavigationContext, useHref, useResolvedPath, useLocation, useNavigate, createPath, UNSAFE_useRouteId, UNSAFE_RouteContext, useMatches, useNavigation, useBlocker } from 'react-router';
14export { AbortedDeferredError, Await, MemoryRouter, Navigate, NavigationType, Outlet, Route, Router, 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, replace, resolvePath, useActionData, useAsyncError, useAsyncValue, useBlocker, useHref, useInRouterContext, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes } from 'react-router';
15import { stripBasename, UNSAFE_warning, createRouter, createBrowserHistory, createHashHistory, UNSAFE_ErrorResponseImpl, UNSAFE_invariant, joinPaths, IDLE_FETCHER, matchPath } from '@remix-run/router';
16export { UNSAFE_ErrorResponseImpl } from '@remix-run/router';
17
18function _extends() {
19 _extends = Object.assign ? Object.assign.bind() : function (target) {
20 for (var i = 1; i < arguments.length; i++) {
21 var source = arguments[i];
22 for (var key in source) {
23 if (Object.prototype.hasOwnProperty.call(source, key)) {
24 target[key] = source[key];
25 }
26 }
27 }
28 return target;
29 };
30 return _extends.apply(this, arguments);
31}
32function _objectWithoutPropertiesLoose(source, excluded) {
33 if (source == null) return {};
34 var target = {};
35 var sourceKeys = Object.keys(source);
36 var key, i;
37 for (i = 0; i < sourceKeys.length; i++) {
38 key = sourceKeys[i];
39 if (excluded.indexOf(key) >= 0) continue;
40 target[key] = source[key];
41 }
42 return target;
43}
44
45const defaultMethod = "get";
46const defaultEncType = "application/x-www-form-urlencoded";
47function isHtmlElement(object) {
48 return object != null && typeof object.tagName === "string";
49}
50function isButtonElement(object) {
51 return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
52}
53function isFormElement(object) {
54 return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
55}
56function isInputElement(object) {
57 return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
58}
59function isModifiedEvent(event) {
60 return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
61}
62function shouldProcessLinkClick(event, target) {
63 return event.button === 0 && (
64 // Ignore everything but left clicks
65 !target || target === "_self") &&
66 // Let browser handle "target=_blank" etc.
67 !isModifiedEvent(event) // Ignore clicks with modifier keys
68 ;
69}
70/**
71 * Creates a URLSearchParams object using the given initializer.
72 *
73 * This is identical to `new URLSearchParams(init)` except it also
74 * supports arrays as values in the object form of the initializer
75 * instead of just strings. This is convenient when you need multiple
76 * values for a given key, but don't want to use an array initializer.
77 *
78 * For example, instead of:
79 *
80 * let searchParams = new URLSearchParams([
81 * ['sort', 'name'],
82 * ['sort', 'price']
83 * ]);
84 *
85 * you can do:
86 *
87 * let searchParams = createSearchParams({
88 * sort: ['name', 'price']
89 * });
90 */
91function createSearchParams(init) {
92 if (init === void 0) {
93 init = "";
94 }
95 return new URLSearchParams(typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo, key) => {
96 let value = init[key];
97 return memo.concat(Array.isArray(value) ? value.map(v => [key, v]) : [[key, value]]);
98 }, []));
99}
100function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
101 let searchParams = createSearchParams(locationSearch);
102 if (defaultSearchParams) {
103 // Use `defaultSearchParams.forEach(...)` here instead of iterating of
104 // `defaultSearchParams.keys()` to work-around a bug in Firefox related to
105 // web extensions. Relevant Bugzilla tickets:
106 // https://bugzilla.mozilla.org/show_bug.cgi?id=1414602
107 // https://bugzilla.mozilla.org/show_bug.cgi?id=1023984
108 defaultSearchParams.forEach((_, key) => {
109 if (!searchParams.has(key)) {
110 defaultSearchParams.getAll(key).forEach(value => {
111 searchParams.append(key, value);
112 });
113 }
114 });
115 }
116 return searchParams;
117}
118// One-time check for submitter support
119let _formDataSupportsSubmitter = null;
120function isFormDataSubmitterSupported() {
121 if (_formDataSupportsSubmitter === null) {
122 try {
123 new FormData(document.createElement("form"),
124 // @ts-expect-error if FormData supports the submitter parameter, this will throw
125 0);
126 _formDataSupportsSubmitter = false;
127 } catch (e) {
128 _formDataSupportsSubmitter = true;
129 }
130 }
131 return _formDataSupportsSubmitter;
132}
133const supportedFormEncTypes = new Set(["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]);
134function getFormEncType(encType) {
135 if (encType != null && !supportedFormEncTypes.has(encType)) {
136 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "\"" + encType + "\" is not a valid `encType` for `<Form>`/`<fetcher.Form>` " + ("and will default to \"" + defaultEncType + "\"")) : void 0;
137 return null;
138 }
139 return encType;
140}
141function getFormSubmissionInfo(target, basename) {
142 let method;
143 let action;
144 let encType;
145 let formData;
146 let body;
147 if (isFormElement(target)) {
148 // When grabbing the action from the element, it will have had the basename
149 // prefixed to ensure non-JS scenarios work, so strip it since we'll
150 // re-prefix in the router
151 let attr = target.getAttribute("action");
152 action = attr ? stripBasename(attr, basename) : null;
153 method = target.getAttribute("method") || defaultMethod;
154 encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
155 formData = new FormData(target);
156 } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
157 let form = target.form;
158 if (form == null) {
159 throw new Error("Cannot submit a <button> or <input type=\"submit\"> without a <form>");
160 }
161 // <button>/<input type="submit"> may override attributes of <form>
162 // When grabbing the action from the element, it will have had the basename
163 // prefixed to ensure non-JS scenarios work, so strip it since we'll
164 // re-prefix in the router
165 let attr = target.getAttribute("formaction") || form.getAttribute("action");
166 action = attr ? stripBasename(attr, basename) : null;
167 method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
168 encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
169 // Build a FormData object populated from a form and submitter
170 formData = new FormData(form, target);
171 // If this browser doesn't support the `FormData(el, submitter)` format,
172 // then tack on the submitter value at the end. This is a lightweight
173 // solution that is not 100% spec compliant. For complete support in older
174 // browsers, consider using the `formdata-submitter-polyfill` package
175 if (!isFormDataSubmitterSupported()) {
176 let {
177 name,
178 type,
179 value
180 } = target;
181 if (type === "image") {
182 let prefix = name ? name + "." : "";
183 formData.append(prefix + "x", "0");
184 formData.append(prefix + "y", "0");
185 } else if (name) {
186 formData.append(name, value);
187 }
188 }
189 } else if (isHtmlElement(target)) {
190 throw new Error("Cannot submit element that is not <form>, <button>, or " + "<input type=\"submit|image\">");
191 } else {
192 method = defaultMethod;
193 action = null;
194 encType = defaultEncType;
195 body = target;
196 }
197 // Send body for <Form encType="text/plain" so we encode it into text
198 if (formData && encType === "text/plain") {
199 body = formData;
200 formData = undefined;
201 }
202 return {
203 action,
204 method: method.toLowerCase(),
205 encType,
206 formData,
207 body
208 };
209}
210
211const _excluded = ["onClick", "relative", "reloadDocument", "replace", "state", "target", "to", "preventScrollReset", "unstable_viewTransition"],
212 _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "unstable_viewTransition", "children"],
213 _excluded3 = ["fetcherKey", "navigate", "reloadDocument", "replace", "state", "method", "action", "onSubmit", "relative", "preventScrollReset", "unstable_viewTransition"];
214// HEY YOU! DON'T TOUCH THIS VARIABLE!
215//
216// It is replaced with the proper version at build time via a babel plugin in
217// the rollup config.
218//
219// Export a global property onto the window for React Router detection by the
220// Core Web Vitals Technology Report. This way they can configure the `wappalyzer`
221// to detect and properly classify live websites as being built with React Router:
222// https://github.com/HTTPArchive/wappalyzer/blob/main/src/technologies/r.json
223const REACT_ROUTER_VERSION = "6";
224try {
225 window.__reactRouterVersion = REACT_ROUTER_VERSION;
226} catch (e) {
227 // no-op
228}
229function createBrowserRouter(routes, opts) {
230 return createRouter({
231 basename: opts == null ? void 0 : opts.basename,
232 future: _extends({}, opts == null ? void 0 : opts.future, {
233 v7_prependBasename: true
234 }),
235 history: createBrowserHistory({
236 window: opts == null ? void 0 : opts.window
237 }),
238 hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
239 routes,
240 mapRouteProperties: UNSAFE_mapRouteProperties,
241 unstable_dataStrategy: opts == null ? void 0 : opts.unstable_dataStrategy,
242 unstable_patchRoutesOnMiss: opts == null ? void 0 : opts.unstable_patchRoutesOnMiss,
243 window: opts == null ? void 0 : opts.window
244 }).initialize();
245}
246function createHashRouter(routes, opts) {
247 return createRouter({
248 basename: opts == null ? void 0 : opts.basename,
249 future: _extends({}, opts == null ? void 0 : opts.future, {
250 v7_prependBasename: true
251 }),
252 history: createHashHistory({
253 window: opts == null ? void 0 : opts.window
254 }),
255 hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
256 routes,
257 mapRouteProperties: UNSAFE_mapRouteProperties,
258 unstable_dataStrategy: opts == null ? void 0 : opts.unstable_dataStrategy,
259 unstable_patchRoutesOnMiss: opts == null ? void 0 : opts.unstable_patchRoutesOnMiss,
260 window: opts == null ? void 0 : opts.window
261 }).initialize();
262}
263function parseHydrationData() {
264 var _window;
265 let state = (_window = window) == null ? void 0 : _window.__staticRouterHydrationData;
266 if (state && state.errors) {
267 state = _extends({}, state, {
268 errors: deserializeErrors(state.errors)
269 });
270 }
271 return state;
272}
273function deserializeErrors(errors) {
274 if (!errors) return null;
275 let entries = Object.entries(errors);
276 let serialized = {};
277 for (let [key, val] of entries) {
278 // Hey you! If you change this, please change the corresponding logic in
279 // serializeErrors in react-router-dom/server.tsx :)
280 if (val && val.__type === "RouteErrorResponse") {
281 serialized[key] = new UNSAFE_ErrorResponseImpl(val.status, val.statusText, val.data, val.internal === true);
282 } else if (val && val.__type === "Error") {
283 // Attempt to reconstruct the right type of Error (i.e., ReferenceError)
284 if (val.__subType) {
285 let ErrorConstructor = window[val.__subType];
286 if (typeof ErrorConstructor === "function") {
287 try {
288 // @ts-expect-error
289 let error = new ErrorConstructor(val.message);
290 // Wipe away the client-side stack trace. Nothing to fill it in with
291 // because we don't serialize SSR stack traces for security reasons
292 error.stack = "";
293 serialized[key] = error;
294 } catch (e) {
295 // no-op - fall through and create a normal Error
296 }
297 }
298 }
299 if (serialized[key] == null) {
300 let error = new Error(val.message);
301 // Wipe away the client-side stack trace. Nothing to fill it in with
302 // because we don't serialize SSR stack traces for security reasons
303 error.stack = "";
304 serialized[key] = error;
305 }
306 } else {
307 serialized[key] = val;
308 }
309 }
310 return serialized;
311}
312const ViewTransitionContext = /*#__PURE__*/React.createContext({
313 isTransitioning: false
314});
315if (process.env.NODE_ENV !== "production") {
316 ViewTransitionContext.displayName = "ViewTransition";
317}
318const FetchersContext = /*#__PURE__*/React.createContext(new Map());
319if (process.env.NODE_ENV !== "production") {
320 FetchersContext.displayName = "Fetchers";
321}
322//#endregion
323////////////////////////////////////////////////////////////////////////////////
324//#region Components
325////////////////////////////////////////////////////////////////////////////////
326/**
327 Webpack + React 17 fails to compile on any of the following because webpack
328 complains that `startTransition` doesn't exist in `React`:
329 * import { startTransition } from "react"
330 * import * as React from from "react";
331 "startTransition" in React ? React.startTransition(() => setState()) : setState()
332 * import * as React from from "react";
333 "startTransition" in React ? React["startTransition"](() => setState()) : setState()
334
335 Moving it to a constant such as the following solves the Webpack/React 17 issue:
336 * import * as React from from "react";
337 const START_TRANSITION = "startTransition";
338 START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()
339
340 However, that introduces webpack/terser minification issues in production builds
341 in React 18 where minification/obfuscation ends up removing the call of
342 React.startTransition entirely from the first half of the ternary. Grabbing
343 this exported reference once up front resolves that issue.
344
345 See https://github.com/remix-run/react-router/issues/10579
346*/
347const START_TRANSITION = "startTransition";
348const startTransitionImpl = React[START_TRANSITION];
349const FLUSH_SYNC = "flushSync";
350const flushSyncImpl = ReactDOM[FLUSH_SYNC];
351const USE_ID = "useId";
352const useIdImpl = React[USE_ID];
353function startTransitionSafe(cb) {
354 if (startTransitionImpl) {
355 startTransitionImpl(cb);
356 } else {
357 cb();
358 }
359}
360function flushSyncSafe(cb) {
361 if (flushSyncImpl) {
362 flushSyncImpl(cb);
363 } else {
364 cb();
365 }
366}
367class Deferred {
368 constructor() {
369 this.status = "pending";
370 this.promise = new Promise((resolve, reject) => {
371 this.resolve = value => {
372 if (this.status === "pending") {
373 this.status = "resolved";
374 resolve(value);
375 }
376 };
377 this.reject = reason => {
378 if (this.status === "pending") {
379 this.status = "rejected";
380 reject(reason);
381 }
382 };
383 });
384 }
385}
386/**
387 * Given a Remix Router instance, render the appropriate UI
388 */
389function RouterProvider(_ref) {
390 let {
391 fallbackElement,
392 router,
393 future
394 } = _ref;
395 let [state, setStateImpl] = React.useState(router.state);
396 let [pendingState, setPendingState] = React.useState();
397 let [vtContext, setVtContext] = React.useState({
398 isTransitioning: false
399 });
400 let [renderDfd, setRenderDfd] = React.useState();
401 let [transition, setTransition] = React.useState();
402 let [interruption, setInterruption] = React.useState();
403 let fetcherData = React.useRef(new Map());
404 let {
405 v7_startTransition
406 } = future || {};
407 let optInStartTransition = React.useCallback(cb => {
408 if (v7_startTransition) {
409 startTransitionSafe(cb);
410 } else {
411 cb();
412 }
413 }, [v7_startTransition]);
414 let setState = React.useCallback((newState, _ref2) => {
415 let {
416 deletedFetchers,
417 unstable_flushSync: flushSync,
418 unstable_viewTransitionOpts: viewTransitionOpts
419 } = _ref2;
420 deletedFetchers.forEach(key => fetcherData.current.delete(key));
421 newState.fetchers.forEach((fetcher, key) => {
422 if (fetcher.data !== undefined) {
423 fetcherData.current.set(key, fetcher.data);
424 }
425 });
426 let isViewTransitionUnavailable = router.window == null || router.window.document == null || typeof router.window.document.startViewTransition !== "function";
427 // If this isn't a view transition or it's not available in this browser,
428 // just update and be done with it
429 if (!viewTransitionOpts || isViewTransitionUnavailable) {
430 if (flushSync) {
431 flushSyncSafe(() => setStateImpl(newState));
432 } else {
433 optInStartTransition(() => setStateImpl(newState));
434 }
435 return;
436 }
437 // flushSync + startViewTransition
438 if (flushSync) {
439 // Flush through the context to mark DOM elements as transition=ing
440 flushSyncSafe(() => {
441 // Cancel any pending transitions
442 if (transition) {
443 renderDfd && renderDfd.resolve();
444 transition.skipTransition();
445 }
446 setVtContext({
447 isTransitioning: true,
448 flushSync: true,
449 currentLocation: viewTransitionOpts.currentLocation,
450 nextLocation: viewTransitionOpts.nextLocation
451 });
452 });
453 // Update the DOM
454 let t = router.window.document.startViewTransition(() => {
455 flushSyncSafe(() => setStateImpl(newState));
456 });
457 // Clean up after the animation completes
458 t.finished.finally(() => {
459 flushSyncSafe(() => {
460 setRenderDfd(undefined);
461 setTransition(undefined);
462 setPendingState(undefined);
463 setVtContext({
464 isTransitioning: false
465 });
466 });
467 });
468 flushSyncSafe(() => setTransition(t));
469 return;
470 }
471 // startTransition + startViewTransition
472 if (transition) {
473 // Interrupting an in-progress transition, cancel and let everything flush
474 // out, and then kick off a new transition from the interruption state
475 renderDfd && renderDfd.resolve();
476 transition.skipTransition();
477 setInterruption({
478 state: newState,
479 currentLocation: viewTransitionOpts.currentLocation,
480 nextLocation: viewTransitionOpts.nextLocation
481 });
482 } else {
483 // Completed navigation update with opted-in view transitions, let 'er rip
484 setPendingState(newState);
485 setVtContext({
486 isTransitioning: true,
487 flushSync: false,
488 currentLocation: viewTransitionOpts.currentLocation,
489 nextLocation: viewTransitionOpts.nextLocation
490 });
491 }
492 }, [router.window, transition, renderDfd, fetcherData, optInStartTransition]);
493 // Need to use a layout effect here so we are subscribed early enough to
494 // pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
495 React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
496 // When we start a view transition, create a Deferred we can use for the
497 // eventual "completed" render
498 React.useEffect(() => {
499 if (vtContext.isTransitioning && !vtContext.flushSync) {
500 setRenderDfd(new Deferred());
501 }
502 }, [vtContext]);
503 // Once the deferred is created, kick off startViewTransition() to update the
504 // DOM and then wait on the Deferred to resolve (indicating the DOM update has
505 // happened)
506 React.useEffect(() => {
507 if (renderDfd && pendingState && router.window) {
508 let newState = pendingState;
509 let renderPromise = renderDfd.promise;
510 let transition = router.window.document.startViewTransition(async () => {
511 optInStartTransition(() => setStateImpl(newState));
512 await renderPromise;
513 });
514 transition.finished.finally(() => {
515 setRenderDfd(undefined);
516 setTransition(undefined);
517 setPendingState(undefined);
518 setVtContext({
519 isTransitioning: false
520 });
521 });
522 setTransition(transition);
523 }
524 }, [optInStartTransition, pendingState, renderDfd, router.window]);
525 // When the new location finally renders and is committed to the DOM, this
526 // effect will run to resolve the transition
527 React.useEffect(() => {
528 if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
529 renderDfd.resolve();
530 }
531 }, [renderDfd, transition, state.location, pendingState]);
532 // If we get interrupted with a new navigation during a transition, we skip
533 // the active transition, let it cleanup, then kick it off again here
534 React.useEffect(() => {
535 if (!vtContext.isTransitioning && interruption) {
536 setPendingState(interruption.state);
537 setVtContext({
538 isTransitioning: true,
539 flushSync: false,
540 currentLocation: interruption.currentLocation,
541 nextLocation: interruption.nextLocation
542 });
543 setInterruption(undefined);
544 }
545 }, [vtContext.isTransitioning, interruption]);
546 React.useEffect(() => {
547 process.env.NODE_ENV !== "production" ? UNSAFE_warning(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using " + "`v7_partialHydration`, use a `HydrateFallback` component instead") : void 0;
548 // Only log this once on initial mount
549 // eslint-disable-next-line react-hooks/exhaustive-deps
550 }, []);
551 let navigator = React.useMemo(() => {
552 return {
553 createHref: router.createHref,
554 encodeLocation: router.encodeLocation,
555 go: n => router.navigate(n),
556 push: (to, state, opts) => router.navigate(to, {
557 state,
558 preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
559 }),
560 replace: (to, state, opts) => router.navigate(to, {
561 replace: true,
562 state,
563 preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
564 })
565 };
566 }, [router]);
567 let basename = router.basename || "/";
568 let dataRouterContext = React.useMemo(() => ({
569 router,
570 navigator,
571 static: false,
572 basename
573 }), [router, navigator, basename]);
574 let routerFuture = React.useMemo(() => ({
575 v7_relativeSplatPath: router.future.v7_relativeSplatPath
576 }), [router.future.v7_relativeSplatPath]);
577 // The fragment and {null} here are important! We need them to keep React 18's
578 // useId happy when we are server-rendering since we may have a <script> here
579 // containing the hydrated server-side staticContext (from StaticRouterProvider).
580 // useId relies on the component tree structure to generate deterministic id's
581 // so we need to ensure it remains the same on the client even though
582 // we don't need the <script> tag
583 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UNSAFE_DataRouterContext.Provider, {
584 value: dataRouterContext
585 }, /*#__PURE__*/React.createElement(UNSAFE_DataRouterStateContext.Provider, {
586 value: state
587 }, /*#__PURE__*/React.createElement(FetchersContext.Provider, {
588 value: fetcherData.current
589 }, /*#__PURE__*/React.createElement(ViewTransitionContext.Provider, {
590 value: vtContext
591 }, /*#__PURE__*/React.createElement(Router, {
592 basename: basename,
593 location: state.location,
594 navigationType: state.historyAction,
595 navigator: navigator,
596 future: routerFuture
597 }, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/React.createElement(MemoizedDataRoutes, {
598 routes: router.routes,
599 future: router.future,
600 state: state
601 }) : fallbackElement))))), null);
602}
603// Memoize to avoid re-renders when updating `ViewTransitionContext`
604const MemoizedDataRoutes = /*#__PURE__*/React.memo(DataRoutes);
605function DataRoutes(_ref3) {
606 let {
607 routes,
608 future,
609 state
610 } = _ref3;
611 return UNSAFE_useRoutesImpl(routes, undefined, state, future);
612}
613/**
614 * A `<Router>` for use in web browsers. Provides the cleanest URLs.
615 */
616function BrowserRouter(_ref4) {
617 let {
618 basename,
619 children,
620 future,
621 window
622 } = _ref4;
623 let historyRef = React.useRef();
624 if (historyRef.current == null) {
625 historyRef.current = createBrowserHistory({
626 window,
627 v5Compat: true
628 });
629 }
630 let history = historyRef.current;
631 let [state, setStateImpl] = React.useState({
632 action: history.action,
633 location: history.location
634 });
635 let {
636 v7_startTransition
637 } = future || {};
638 let setState = React.useCallback(newState => {
639 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
640 }, [setStateImpl, v7_startTransition]);
641 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
642 return /*#__PURE__*/React.createElement(Router, {
643 basename: basename,
644 children: children,
645 location: state.location,
646 navigationType: state.action,
647 navigator: history,
648 future: future
649 });
650}
651/**
652 * A `<Router>` for use in web browsers. Stores the location in the hash
653 * portion of the URL so it is not sent to the server.
654 */
655function HashRouter(_ref5) {
656 let {
657 basename,
658 children,
659 future,
660 window
661 } = _ref5;
662 let historyRef = React.useRef();
663 if (historyRef.current == null) {
664 historyRef.current = createHashHistory({
665 window,
666 v5Compat: true
667 });
668 }
669 let history = historyRef.current;
670 let [state, setStateImpl] = React.useState({
671 action: history.action,
672 location: history.location
673 });
674 let {
675 v7_startTransition
676 } = future || {};
677 let setState = React.useCallback(newState => {
678 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
679 }, [setStateImpl, v7_startTransition]);
680 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
681 return /*#__PURE__*/React.createElement(Router, {
682 basename: basename,
683 children: children,
684 location: state.location,
685 navigationType: state.action,
686 navigator: history,
687 future: future
688 });
689}
690/**
691 * A `<Router>` that accepts a pre-instantiated history object. It's important
692 * to note that using your own history object is highly discouraged and may add
693 * two versions of the history library to your bundles unless you use the same
694 * version of the history library that React Router uses internally.
695 */
696function HistoryRouter(_ref6) {
697 let {
698 basename,
699 children,
700 future,
701 history
702 } = _ref6;
703 let [state, setStateImpl] = React.useState({
704 action: history.action,
705 location: history.location
706 });
707 let {
708 v7_startTransition
709 } = future || {};
710 let setState = React.useCallback(newState => {
711 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
712 }, [setStateImpl, v7_startTransition]);
713 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
714 return /*#__PURE__*/React.createElement(Router, {
715 basename: basename,
716 children: children,
717 location: state.location,
718 navigationType: state.action,
719 navigator: history,
720 future: future
721 });
722}
723if (process.env.NODE_ENV !== "production") {
724 HistoryRouter.displayName = "unstable_HistoryRouter";
725}
726const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
727const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
728/**
729 * The public API for rendering a history-aware `<a>`.
730 */
731const Link = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref7, ref) {
732 let {
733 onClick,
734 relative,
735 reloadDocument,
736 replace,
737 state,
738 target,
739 to,
740 preventScrollReset,
741 unstable_viewTransition
742 } = _ref7,
743 rest = _objectWithoutPropertiesLoose(_ref7, _excluded);
744 let {
745 basename
746 } = React.useContext(UNSAFE_NavigationContext);
747 // Rendered into <a href> for absolute URLs
748 let absoluteHref;
749 let isExternal = false;
750 if (typeof to === "string" && ABSOLUTE_URL_REGEX.test(to)) {
751 // Render the absolute href server- and client-side
752 absoluteHref = to;
753 // Only check for external origins client-side
754 if (isBrowser) {
755 try {
756 let currentUrl = new URL(window.location.href);
757 let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
758 let path = stripBasename(targetUrl.pathname, basename);
759 if (targetUrl.origin === currentUrl.origin && path != null) {
760 // Strip the protocol/origin/basename for same-origin absolute URLs
761 to = path + targetUrl.search + targetUrl.hash;
762 } else {
763 isExternal = true;
764 }
765 } catch (e) {
766 // We can't do external URL detection without a valid URL
767 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "<Link to=\"" + to + "\"> contains an invalid URL which will probably break " + "when clicked - please update to a valid URL path.") : void 0;
768 }
769 }
770 }
771 // Rendered into <a href> for relative URLs
772 let href = useHref(to, {
773 relative
774 });
775 let internalOnClick = useLinkClickHandler(to, {
776 replace,
777 state,
778 target,
779 preventScrollReset,
780 relative,
781 unstable_viewTransition
782 });
783 function handleClick(event) {
784 if (onClick) onClick(event);
785 if (!event.defaultPrevented) {
786 internalOnClick(event);
787 }
788 }
789 return (
790 /*#__PURE__*/
791 // eslint-disable-next-line jsx-a11y/anchor-has-content
792 React.createElement("a", _extends({}, rest, {
793 href: absoluteHref || href,
794 onClick: isExternal || reloadDocument ? onClick : handleClick,
795 ref: ref,
796 target: target
797 }))
798 );
799});
800if (process.env.NODE_ENV !== "production") {
801 Link.displayName = "Link";
802}
803/**
804 * A `<Link>` wrapper that knows if it's "active" or not.
805 */
806const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref8, ref) {
807 let {
808 "aria-current": ariaCurrentProp = "page",
809 caseSensitive = false,
810 className: classNameProp = "",
811 end = false,
812 style: styleProp,
813 to,
814 unstable_viewTransition,
815 children
816 } = _ref8,
817 rest = _objectWithoutPropertiesLoose(_ref8, _excluded2);
818 let path = useResolvedPath(to, {
819 relative: rest.relative
820 });
821 let location = useLocation();
822 let routerState = React.useContext(UNSAFE_DataRouterStateContext);
823 let {
824 navigator,
825 basename
826 } = React.useContext(UNSAFE_NavigationContext);
827 let isTransitioning = routerState != null &&
828 // Conditional usage is OK here because the usage of a data router is static
829 // eslint-disable-next-line react-hooks/rules-of-hooks
830 useViewTransitionState(path) && unstable_viewTransition === true;
831 let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
832 let locationPathname = location.pathname;
833 let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
834 if (!caseSensitive) {
835 locationPathname = locationPathname.toLowerCase();
836 nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
837 toPathname = toPathname.toLowerCase();
838 }
839 if (nextLocationPathname && basename) {
840 nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
841 }
842 // If the `to` has a trailing slash, look at that exact spot. Otherwise,
843 // we're looking for a slash _after_ what's in `to`. For example:
844 //
845 // <NavLink to="/users"> and <NavLink to="/users/">
846 // both want to look for a / at index 6 to match URL `/users/matt`
847 const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
848 let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
849 let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
850 let renderProps = {
851 isActive,
852 isPending,
853 isTransitioning
854 };
855 let ariaCurrent = isActive ? ariaCurrentProp : undefined;
856 let className;
857 if (typeof classNameProp === "function") {
858 className = classNameProp(renderProps);
859 } else {
860 // If the className prop is not a function, we use a default `active`
861 // class for <NavLink />s that are active. In v5 `active` was the default
862 // value for `activeClassName`, but we are removing that API and can still
863 // use the old default behavior for a cleaner upgrade path and keep the
864 // simple styling rules working as they currently do.
865 className = [classNameProp, isActive ? "active" : null, isPending ? "pending" : null, isTransitioning ? "transitioning" : null].filter(Boolean).join(" ");
866 }
867 let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
868 return /*#__PURE__*/React.createElement(Link, _extends({}, rest, {
869 "aria-current": ariaCurrent,
870 className: className,
871 ref: ref,
872 style: style,
873 to: to,
874 unstable_viewTransition: unstable_viewTransition
875 }), typeof children === "function" ? children(renderProps) : children);
876});
877if (process.env.NODE_ENV !== "production") {
878 NavLink.displayName = "NavLink";
879}
880/**
881 * A `@remix-run/router`-aware `<form>`. It behaves like a normal form except
882 * that the interaction with the server is with `fetch` instead of new document
883 * requests, allowing components to add nicer UX to the page as the form is
884 * submitted and returns with data.
885 */
886const Form = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
887 let {
888 fetcherKey,
889 navigate,
890 reloadDocument,
891 replace,
892 state,
893 method = defaultMethod,
894 action,
895 onSubmit,
896 relative,
897 preventScrollReset,
898 unstable_viewTransition
899 } = _ref9,
900 props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
901 let submit = useSubmit();
902 let formAction = useFormAction(action, {
903 relative
904 });
905 let formMethod = method.toLowerCase() === "get" ? "get" : "post";
906 let submitHandler = event => {
907 onSubmit && onSubmit(event);
908 if (event.defaultPrevented) return;
909 event.preventDefault();
910 let submitter = event.nativeEvent.submitter;
911 let submitMethod = (submitter == null ? void 0 : submitter.getAttribute("formmethod")) || method;
912 submit(submitter || event.currentTarget, {
913 fetcherKey,
914 method: submitMethod,
915 navigate,
916 replace,
917 state,
918 relative,
919 preventScrollReset,
920 unstable_viewTransition
921 });
922 };
923 return /*#__PURE__*/React.createElement("form", _extends({
924 ref: forwardedRef,
925 method: formMethod,
926 action: formAction,
927 onSubmit: reloadDocument ? onSubmit : submitHandler
928 }, props));
929});
930if (process.env.NODE_ENV !== "production") {
931 Form.displayName = "Form";
932}
933/**
934 * This component will emulate the browser's scroll restoration on location
935 * changes.
936 */
937function ScrollRestoration(_ref10) {
938 let {
939 getKey,
940 storageKey
941 } = _ref10;
942 useScrollRestoration({
943 getKey,
944 storageKey
945 });
946 return null;
947}
948if (process.env.NODE_ENV !== "production") {
949 ScrollRestoration.displayName = "ScrollRestoration";
950}
951//#endregion
952////////////////////////////////////////////////////////////////////////////////
953//#region Hooks
954////////////////////////////////////////////////////////////////////////////////
955var DataRouterHook;
956(function (DataRouterHook) {
957 DataRouterHook["UseScrollRestoration"] = "useScrollRestoration";
958 DataRouterHook["UseSubmit"] = "useSubmit";
959 DataRouterHook["UseSubmitFetcher"] = "useSubmitFetcher";
960 DataRouterHook["UseFetcher"] = "useFetcher";
961 DataRouterHook["useViewTransitionState"] = "useViewTransitionState";
962})(DataRouterHook || (DataRouterHook = {}));
963var DataRouterStateHook;
964(function (DataRouterStateHook) {
965 DataRouterStateHook["UseFetcher"] = "useFetcher";
966 DataRouterStateHook["UseFetchers"] = "useFetchers";
967 DataRouterStateHook["UseScrollRestoration"] = "useScrollRestoration";
968})(DataRouterStateHook || (DataRouterStateHook = {}));
969// Internal hooks
970function getDataRouterConsoleError(hookName) {
971 return hookName + " must be used within a data router. See https://reactrouter.com/routers/picking-a-router.";
972}
973function useDataRouterContext(hookName) {
974 let ctx = React.useContext(UNSAFE_DataRouterContext);
975 !ctx ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
976 return ctx;
977}
978function useDataRouterState(hookName) {
979 let state = React.useContext(UNSAFE_DataRouterStateContext);
980 !state ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
981 return state;
982}
983// External hooks
984/**
985 * Handles the click behavior for router `<Link>` components. This is useful if
986 * you need to create custom `<Link>` components with the same click behavior we
987 * use in our exported `<Link>`.
988 */
989function useLinkClickHandler(to, _temp) {
990 let {
991 target,
992 replace: replaceProp,
993 state,
994 preventScrollReset,
995 relative,
996 unstable_viewTransition
997 } = _temp === void 0 ? {} : _temp;
998 let navigate = useNavigate();
999 let location = useLocation();
1000 let path = useResolvedPath(to, {
1001 relative
1002 });
1003 return React.useCallback(event => {
1004 if (shouldProcessLinkClick(event, target)) {
1005 event.preventDefault();
1006 // If the URL hasn't changed, a regular <a> will do a replace instead of
1007 // a push, so do the same here unless the replace prop is explicitly set
1008 let replace = replaceProp !== undefined ? replaceProp : createPath(location) === createPath(path);
1009 navigate(to, {
1010 replace,
1011 state,
1012 preventScrollReset,
1013 relative,
1014 unstable_viewTransition
1015 });
1016 }
1017 }, [location, navigate, path, replaceProp, state, target, to, preventScrollReset, relative, unstable_viewTransition]);
1018}
1019/**
1020 * A convenient wrapper for reading and writing search parameters via the
1021 * URLSearchParams interface.
1022 */
1023function useSearchParams(defaultInit) {
1024 process.env.NODE_ENV !== "production" ? UNSAFE_warning(typeof URLSearchParams !== "undefined", "You cannot use the `useSearchParams` hook in a browser that does not " + "support the URLSearchParams API. If you need to support Internet " + "Explorer 11, we recommend you load a polyfill such as " + "https://github.com/ungap/url-search-params.") : void 0;
1025 let defaultSearchParamsRef = React.useRef(createSearchParams(defaultInit));
1026 let hasSetSearchParamsRef = React.useRef(false);
1027 let location = useLocation();
1028 let searchParams = React.useMemo(() =>
1029 // Only merge in the defaults if we haven't yet called setSearchParams.
1030 // Once we call that we want those to take precedence, otherwise you can't
1031 // remove a param with setSearchParams({}) if it has an initial value
1032 getSearchParamsForLocation(location.search, hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current), [location.search]);
1033 let navigate = useNavigate();
1034 let setSearchParams = React.useCallback((nextInit, navigateOptions) => {
1035 const newSearchParams = createSearchParams(typeof nextInit === "function" ? nextInit(searchParams) : nextInit);
1036 hasSetSearchParamsRef.current = true;
1037 navigate("?" + newSearchParams, navigateOptions);
1038 }, [navigate, searchParams]);
1039 return [searchParams, setSearchParams];
1040}
1041function validateClientSideSubmission() {
1042 if (typeof document === "undefined") {
1043 throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead.");
1044 }
1045}
1046let fetcherId = 0;
1047let getUniqueFetcherId = () => "__" + String(++fetcherId) + "__";
1048/**
1049 * Returns a function that may be used to programmatically submit a form (or
1050 * some arbitrary data) to the server.
1051 */
1052function useSubmit() {
1053 let {
1054 router
1055 } = useDataRouterContext(DataRouterHook.UseSubmit);
1056 let {
1057 basename
1058 } = React.useContext(UNSAFE_NavigationContext);
1059 let currentRouteId = UNSAFE_useRouteId();
1060 return React.useCallback(function (target, options) {
1061 if (options === void 0) {
1062 options = {};
1063 }
1064 validateClientSideSubmission();
1065 let {
1066 action,
1067 method,
1068 encType,
1069 formData,
1070 body
1071 } = getFormSubmissionInfo(target, basename);
1072 if (options.navigate === false) {
1073 let key = options.fetcherKey || getUniqueFetcherId();
1074 router.fetch(key, currentRouteId, options.action || action, {
1075 preventScrollReset: options.preventScrollReset,
1076 formData,
1077 body,
1078 formMethod: options.method || method,
1079 formEncType: options.encType || encType,
1080 unstable_flushSync: options.unstable_flushSync
1081 });
1082 } else {
1083 router.navigate(options.action || action, {
1084 preventScrollReset: options.preventScrollReset,
1085 formData,
1086 body,
1087 formMethod: options.method || method,
1088 formEncType: options.encType || encType,
1089 replace: options.replace,
1090 state: options.state,
1091 fromRouteId: currentRouteId,
1092 unstable_flushSync: options.unstable_flushSync,
1093 unstable_viewTransition: options.unstable_viewTransition
1094 });
1095 }
1096 }, [router, basename, currentRouteId]);
1097}
1098// v7: Eventually we should deprecate this entirely in favor of using the
1099// router method directly?
1100function useFormAction(action, _temp2) {
1101 let {
1102 relative
1103 } = _temp2 === void 0 ? {} : _temp2;
1104 let {
1105 basename
1106 } = React.useContext(UNSAFE_NavigationContext);
1107 let routeContext = React.useContext(UNSAFE_RouteContext);
1108 !routeContext ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFormAction must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1109 let [match] = routeContext.matches.slice(-1);
1110 // Shallow clone path so we can modify it below, otherwise we modify the
1111 // object referenced by useMemo inside useResolvedPath
1112 let path = _extends({}, useResolvedPath(action ? action : ".", {
1113 relative
1114 }));
1115 // If no action was specified, browsers will persist current search params
1116 // when determining the path, so match that behavior
1117 // https://github.com/remix-run/remix/issues/927
1118 let location = useLocation();
1119 if (action == null) {
1120 // Safe to write to this directly here since if action was undefined, we
1121 // would have called useResolvedPath(".") which will never include a search
1122 path.search = location.search;
1123 // When grabbing search params from the URL, remove any included ?index param
1124 // since it might not apply to our contextual route. We add it back based
1125 // on match.route.index below
1126 let params = new URLSearchParams(path.search);
1127 if (params.has("index") && params.get("index") === "") {
1128 params.delete("index");
1129 path.search = params.toString() ? "?" + params.toString() : "";
1130 }
1131 }
1132 if ((!action || action === ".") && match.route.index) {
1133 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
1134 }
1135 // If we're operating within a basename, prepend it to the pathname prior
1136 // to creating the form action. If this is a root navigation, then just use
1137 // the raw basename which allows the basename to have full control over the
1138 // presence of a trailing slash on root actions
1139 if (basename !== "/") {
1140 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
1141 }
1142 return createPath(path);
1143}
1144// TODO: (v7) Change the useFetcher generic default from `any` to `unknown`
1145/**
1146 * Interacts with route loaders and actions without causing a navigation. Great
1147 * for any interaction that stays on the same page.
1148 */
1149function useFetcher(_temp3) {
1150 var _route$matches;
1151 let {
1152 key
1153 } = _temp3 === void 0 ? {} : _temp3;
1154 let {
1155 router
1156 } = useDataRouterContext(DataRouterHook.UseFetcher);
1157 let state = useDataRouterState(DataRouterStateHook.UseFetcher);
1158 let fetcherData = React.useContext(FetchersContext);
1159 let route = React.useContext(UNSAFE_RouteContext);
1160 let routeId = (_route$matches = route.matches[route.matches.length - 1]) == null ? void 0 : _route$matches.route.id;
1161 !fetcherData ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a FetchersContext") : UNSAFE_invariant(false) : void 0;
1162 !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1163 !(routeId != null) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher can only be used on routes that contain a unique \"id\"") : UNSAFE_invariant(false) : void 0;
1164 // Fetcher key handling
1165 // OK to call conditionally to feature detect `useId`
1166 // eslint-disable-next-line react-hooks/rules-of-hooks
1167 let defaultKey = useIdImpl ? useIdImpl() : "";
1168 let [fetcherKey, setFetcherKey] = React.useState(key || defaultKey);
1169 if (key && key !== fetcherKey) {
1170 setFetcherKey(key);
1171 } else if (!fetcherKey) {
1172 // We will only fall through here when `useId` is not available
1173 setFetcherKey(getUniqueFetcherId());
1174 }
1175 // Registration/cleanup
1176 React.useEffect(() => {
1177 router.getFetcher(fetcherKey);
1178 return () => {
1179 // Tell the router we've unmounted - if v7_fetcherPersist is enabled this
1180 // will not delete immediately but instead queue up a delete after the
1181 // fetcher returns to an `idle` state
1182 router.deleteFetcher(fetcherKey);
1183 };
1184 }, [router, fetcherKey]);
1185 // Fetcher additions
1186 let load = React.useCallback((href, opts) => {
1187 !routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
1188 router.fetch(fetcherKey, routeId, href, opts);
1189 }, [fetcherKey, routeId, router]);
1190 let submitImpl = useSubmit();
1191 let submit = React.useCallback((target, opts) => {
1192 submitImpl(target, _extends({}, opts, {
1193 navigate: false,
1194 fetcherKey
1195 }));
1196 }, [fetcherKey, submitImpl]);
1197 let FetcherForm = React.useMemo(() => {
1198 let FetcherForm = /*#__PURE__*/React.forwardRef((props, ref) => {
1199 return /*#__PURE__*/React.createElement(Form, _extends({}, props, {
1200 navigate: false,
1201 fetcherKey: fetcherKey,
1202 ref: ref
1203 }));
1204 });
1205 if (process.env.NODE_ENV !== "production") {
1206 FetcherForm.displayName = "fetcher.Form";
1207 }
1208 return FetcherForm;
1209 }, [fetcherKey]);
1210 // Exposed FetcherWithComponents
1211 let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;
1212 let data = fetcherData.get(fetcherKey);
1213 let fetcherWithComponents = React.useMemo(() => _extends({
1214 Form: FetcherForm,
1215 submit,
1216 load
1217 }, fetcher, {
1218 data
1219 }), [FetcherForm, submit, load, fetcher, data]);
1220 return fetcherWithComponents;
1221}
1222/**
1223 * Provides all fetchers currently on the page. Useful for layouts and parent
1224 * routes that need to provide pending/optimistic UI regarding the fetch.
1225 */
1226function useFetchers() {
1227 let state = useDataRouterState(DataRouterStateHook.UseFetchers);
1228 return Array.from(state.fetchers.entries()).map(_ref11 => {
1229 let [key, fetcher] = _ref11;
1230 return _extends({}, fetcher, {
1231 key
1232 });
1233 });
1234}
1235const SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
1236let savedScrollPositions = {};
1237/**
1238 * When rendered inside a RouterProvider, will restore scroll positions on navigations
1239 */
1240function useScrollRestoration(_temp4) {
1241 let {
1242 getKey,
1243 storageKey
1244 } = _temp4 === void 0 ? {} : _temp4;
1245 let {
1246 router
1247 } = useDataRouterContext(DataRouterHook.UseScrollRestoration);
1248 let {
1249 restoreScrollPosition,
1250 preventScrollReset
1251 } = useDataRouterState(DataRouterStateHook.UseScrollRestoration);
1252 let {
1253 basename
1254 } = React.useContext(UNSAFE_NavigationContext);
1255 let location = useLocation();
1256 let matches = useMatches();
1257 let navigation = useNavigation();
1258 // Trigger manual scroll restoration while we're active
1259 React.useEffect(() => {
1260 window.history.scrollRestoration = "manual";
1261 return () => {
1262 window.history.scrollRestoration = "auto";
1263 };
1264 }, []);
1265 // Save positions on pagehide
1266 usePageHide(React.useCallback(() => {
1267 if (navigation.state === "idle") {
1268 let key = (getKey ? getKey(location, matches) : null) || location.key;
1269 savedScrollPositions[key] = window.scrollY;
1270 }
1271 try {
1272 sessionStorage.setItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY, JSON.stringify(savedScrollPositions));
1273 } catch (error) {
1274 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (" + error + ").") : void 0;
1275 }
1276 window.history.scrollRestoration = "auto";
1277 }, [storageKey, getKey, navigation.state, location, matches]));
1278 // Read in any saved scroll locations
1279 if (typeof document !== "undefined") {
1280 // eslint-disable-next-line react-hooks/rules-of-hooks
1281 React.useLayoutEffect(() => {
1282 try {
1283 let sessionPositions = sessionStorage.getItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY);
1284 if (sessionPositions) {
1285 savedScrollPositions = JSON.parse(sessionPositions);
1286 }
1287 } catch (e) {
1288 // no-op, use default empty object
1289 }
1290 }, [storageKey]);
1291 // Enable scroll restoration in the router
1292 // eslint-disable-next-line react-hooks/rules-of-hooks
1293 React.useLayoutEffect(() => {
1294 let getKeyWithoutBasename = getKey && basename !== "/" ? (location, matches) => getKey( // Strip the basename to match useLocation()
1295 _extends({}, location, {
1296 pathname: stripBasename(location.pathname, basename) || location.pathname
1297 }), matches) : getKey;
1298 let disableScrollRestoration = router == null ? void 0 : router.enableScrollRestoration(savedScrollPositions, () => window.scrollY, getKeyWithoutBasename);
1299 return () => disableScrollRestoration && disableScrollRestoration();
1300 }, [router, basename, getKey]);
1301 // Restore scrolling when state.restoreScrollPosition changes
1302 // eslint-disable-next-line react-hooks/rules-of-hooks
1303 React.useLayoutEffect(() => {
1304 // Explicit false means don't do anything (used for submissions)
1305 if (restoreScrollPosition === false) {
1306 return;
1307 }
1308 // been here before, scroll to it
1309 if (typeof restoreScrollPosition === "number") {
1310 window.scrollTo(0, restoreScrollPosition);
1311 return;
1312 }
1313 // try to scroll to the hash
1314 if (location.hash) {
1315 let el = document.getElementById(decodeURIComponent(location.hash.slice(1)));
1316 if (el) {
1317 el.scrollIntoView();
1318 return;
1319 }
1320 }
1321 // Don't reset if this navigation opted out
1322 if (preventScrollReset === true) {
1323 return;
1324 }
1325 // otherwise go to the top on new locations
1326 window.scrollTo(0, 0);
1327 }, [location, restoreScrollPosition, preventScrollReset]);
1328 }
1329}
1330/**
1331 * Setup a callback to be fired on the window's `beforeunload` event. This is
1332 * useful for saving some data to `window.localStorage` just before the page
1333 * refreshes.
1334 *
1335 * Note: The `callback` argument should be a function created with
1336 * `React.useCallback()`.
1337 */
1338function useBeforeUnload(callback, options) {
1339 let {
1340 capture
1341 } = options || {};
1342 React.useEffect(() => {
1343 let opts = capture != null ? {
1344 capture
1345 } : undefined;
1346 window.addEventListener("beforeunload", callback, opts);
1347 return () => {
1348 window.removeEventListener("beforeunload", callback, opts);
1349 };
1350 }, [callback, capture]);
1351}
1352/**
1353 * Setup a callback to be fired on the window's `pagehide` event. This is
1354 * useful for saving some data to `window.localStorage` just before the page
1355 * refreshes. This event is better supported than beforeunload across browsers.
1356 *
1357 * Note: The `callback` argument should be a function created with
1358 * `React.useCallback()`.
1359 */
1360function usePageHide(callback, options) {
1361 let {
1362 capture
1363 } = options || {};
1364 React.useEffect(() => {
1365 let opts = capture != null ? {
1366 capture
1367 } : undefined;
1368 window.addEventListener("pagehide", callback, opts);
1369 return () => {
1370 window.removeEventListener("pagehide", callback, opts);
1371 };
1372 }, [callback, capture]);
1373}
1374/**
1375 * Wrapper around useBlocker to show a window.confirm prompt to users instead
1376 * of building a custom UI with useBlocker.
1377 *
1378 * Warning: This has *a lot of rough edges* and behaves very differently (and
1379 * very incorrectly in some cases) across browsers if user click addition
1380 * back/forward navigations while the confirm is open. Use at your own risk.
1381 */
1382function usePrompt(_ref12) {
1383 let {
1384 when,
1385 message
1386 } = _ref12;
1387 let blocker = useBlocker(when);
1388 React.useEffect(() => {
1389 if (blocker.state === "blocked") {
1390 let proceed = window.confirm(message);
1391 if (proceed) {
1392 // This timeout is needed to avoid a weird "race" on POP navigations
1393 // between the `window.history` revert navigation and the result of
1394 // `window.confirm`
1395 setTimeout(blocker.proceed, 0);
1396 } else {
1397 blocker.reset();
1398 }
1399 }
1400 }, [blocker, message]);
1401 React.useEffect(() => {
1402 if (blocker.state === "blocked" && !when) {
1403 blocker.reset();
1404 }
1405 }, [blocker, when]);
1406}
1407/**
1408 * Return a boolean indicating if there is an active view transition to the
1409 * given href. You can use this value to render CSS classes or viewTransitionName
1410 * styles onto your elements
1411 *
1412 * @param href The destination href
1413 * @param [opts.relative] Relative routing type ("route" | "path")
1414 */
1415function useViewTransitionState(to, opts) {
1416 if (opts === void 0) {
1417 opts = {};
1418 }
1419 let vtContext = React.useContext(ViewTransitionContext);
1420 !(vtContext != null) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "`unstable_useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. " + "Did you accidentally import `RouterProvider` from `react-router`?") : UNSAFE_invariant(false) : void 0;
1421 let {
1422 basename
1423 } = useDataRouterContext(DataRouterHook.useViewTransitionState);
1424 let path = useResolvedPath(to, {
1425 relative: opts.relative
1426 });
1427 if (!vtContext.isTransitioning) {
1428 return false;
1429 }
1430 let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
1431 let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
1432 // Transition is active if we're going to or coming from the indicated
1433 // destination. This ensures that other PUSH navigations that reverse
1434 // an indicated transition apply. I.e., on the list view you have:
1435 //
1436 // <NavLink to="/details/1" unstable_viewTransition>
1437 //
1438 // If you click the breadcrumb back to the list view:
1439 //
1440 // <NavLink to="/list" unstable_viewTransition>
1441 //
1442 // We should apply the transition because it's indicated as active going
1443 // from /list -> /details/1 and therefore should be active on the reverse
1444 // (even though this isn't strictly a POP reverse)
1445 return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
1446}
1447//#endregion
1448
1449export { BrowserRouter, Form, HashRouter, Link, NavLink, RouterProvider, ScrollRestoration, FetchersContext as UNSAFE_FetchersContext, ViewTransitionContext as UNSAFE_ViewTransitionContext, 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 };
1450//# sourceMappingURL=index.js.map
Note: See TracBrowser for help on using the repository browser.