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

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

Pred finalna verzija

  • Property mode set to 100644
File size: 55.4 KB
Line 
1/**
2 * React Router DOM v6.28.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_logV6DeprecationWarnings, 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", "viewTransition"],
212 _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "viewTransition", "children"],
213 _excluded3 = ["fetcherKey", "navigate", "reloadDocument", "replace", "state", "method", "action", "onSubmit", "relative", "preventScrollReset", "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 dataStrategy: opts == null ? void 0 : opts.dataStrategy,
242 patchRoutesOnNavigation: opts == null ? void 0 : opts.patchRoutesOnNavigation,
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 dataStrategy: opts == null ? void 0 : opts.dataStrategy,
259 patchRoutesOnNavigation: opts == null ? void 0 : opts.patchRoutesOnNavigation,
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 flushSync: flushSync,
418 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 React.useEffect(() => UNSAFE_logV6DeprecationWarnings(future, router.future), [future, router.future]);
578 // The fragment and {null} here are important! We need them to keep React 18's
579 // useId happy when we are server-rendering since we may have a <script> here
580 // containing the hydrated server-side staticContext (from StaticRouterProvider).
581 // useId relies on the component tree structure to generate deterministic id's
582 // so we need to ensure it remains the same on the client even though
583 // we don't need the <script> tag
584 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UNSAFE_DataRouterContext.Provider, {
585 value: dataRouterContext
586 }, /*#__PURE__*/React.createElement(UNSAFE_DataRouterStateContext.Provider, {
587 value: state
588 }, /*#__PURE__*/React.createElement(FetchersContext.Provider, {
589 value: fetcherData.current
590 }, /*#__PURE__*/React.createElement(ViewTransitionContext.Provider, {
591 value: vtContext
592 }, /*#__PURE__*/React.createElement(Router, {
593 basename: basename,
594 location: state.location,
595 navigationType: state.historyAction,
596 navigator: navigator,
597 future: routerFuture
598 }, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/React.createElement(MemoizedDataRoutes, {
599 routes: router.routes,
600 future: router.future,
601 state: state
602 }) : fallbackElement))))), null);
603}
604// Memoize to avoid re-renders when updating `ViewTransitionContext`
605const MemoizedDataRoutes = /*#__PURE__*/React.memo(DataRoutes);
606function DataRoutes(_ref3) {
607 let {
608 routes,
609 future,
610 state
611 } = _ref3;
612 return UNSAFE_useRoutesImpl(routes, undefined, state, future);
613}
614/**
615 * A `<Router>` for use in web browsers. Provides the cleanest URLs.
616 */
617function BrowserRouter(_ref4) {
618 let {
619 basename,
620 children,
621 future,
622 window
623 } = _ref4;
624 let historyRef = React.useRef();
625 if (historyRef.current == null) {
626 historyRef.current = createBrowserHistory({
627 window,
628 v5Compat: true
629 });
630 }
631 let history = historyRef.current;
632 let [state, setStateImpl] = React.useState({
633 action: history.action,
634 location: history.location
635 });
636 let {
637 v7_startTransition
638 } = future || {};
639 let setState = React.useCallback(newState => {
640 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
641 }, [setStateImpl, v7_startTransition]);
642 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
643 React.useEffect(() => UNSAFE_logV6DeprecationWarnings(future), [future]);
644 return /*#__PURE__*/React.createElement(Router, {
645 basename: basename,
646 children: children,
647 location: state.location,
648 navigationType: state.action,
649 navigator: history,
650 future: future
651 });
652}
653/**
654 * A `<Router>` for use in web browsers. Stores the location in the hash
655 * portion of the URL so it is not sent to the server.
656 */
657function HashRouter(_ref5) {
658 let {
659 basename,
660 children,
661 future,
662 window
663 } = _ref5;
664 let historyRef = React.useRef();
665 if (historyRef.current == null) {
666 historyRef.current = createHashHistory({
667 window,
668 v5Compat: true
669 });
670 }
671 let history = historyRef.current;
672 let [state, setStateImpl] = React.useState({
673 action: history.action,
674 location: history.location
675 });
676 let {
677 v7_startTransition
678 } = future || {};
679 let setState = React.useCallback(newState => {
680 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
681 }, [setStateImpl, v7_startTransition]);
682 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
683 React.useEffect(() => UNSAFE_logV6DeprecationWarnings(future), [future]);
684 return /*#__PURE__*/React.createElement(Router, {
685 basename: basename,
686 children: children,
687 location: state.location,
688 navigationType: state.action,
689 navigator: history,
690 future: future
691 });
692}
693/**
694 * A `<Router>` that accepts a pre-instantiated history object. It's important
695 * to note that using your own history object is highly discouraged and may add
696 * two versions of the history library to your bundles unless you use the same
697 * version of the history library that React Router uses internally.
698 */
699function HistoryRouter(_ref6) {
700 let {
701 basename,
702 children,
703 future,
704 history
705 } = _ref6;
706 let [state, setStateImpl] = React.useState({
707 action: history.action,
708 location: history.location
709 });
710 let {
711 v7_startTransition
712 } = future || {};
713 let setState = React.useCallback(newState => {
714 v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
715 }, [setStateImpl, v7_startTransition]);
716 React.useLayoutEffect(() => history.listen(setState), [history, setState]);
717 React.useEffect(() => UNSAFE_logV6DeprecationWarnings(future), [future]);
718 return /*#__PURE__*/React.createElement(Router, {
719 basename: basename,
720 children: children,
721 location: state.location,
722 navigationType: state.action,
723 navigator: history,
724 future: future
725 });
726}
727if (process.env.NODE_ENV !== "production") {
728 HistoryRouter.displayName = "unstable_HistoryRouter";
729}
730const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
731const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
732/**
733 * The public API for rendering a history-aware `<a>`.
734 */
735const Link = /*#__PURE__*/React.forwardRef(function LinkWithRef(_ref7, ref) {
736 let {
737 onClick,
738 relative,
739 reloadDocument,
740 replace,
741 state,
742 target,
743 to,
744 preventScrollReset,
745 viewTransition
746 } = _ref7,
747 rest = _objectWithoutPropertiesLoose(_ref7, _excluded);
748 let {
749 basename
750 } = React.useContext(UNSAFE_NavigationContext);
751 // Rendered into <a href> for absolute URLs
752 let absoluteHref;
753 let isExternal = false;
754 if (typeof to === "string" && ABSOLUTE_URL_REGEX.test(to)) {
755 // Render the absolute href server- and client-side
756 absoluteHref = to;
757 // Only check for external origins client-side
758 if (isBrowser) {
759 try {
760 let currentUrl = new URL(window.location.href);
761 let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
762 let path = stripBasename(targetUrl.pathname, basename);
763 if (targetUrl.origin === currentUrl.origin && path != null) {
764 // Strip the protocol/origin/basename for same-origin absolute URLs
765 to = path + targetUrl.search + targetUrl.hash;
766 } else {
767 isExternal = true;
768 }
769 } catch (e) {
770 // We can't do external URL detection without a valid URL
771 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;
772 }
773 }
774 }
775 // Rendered into <a href> for relative URLs
776 let href = useHref(to, {
777 relative
778 });
779 let internalOnClick = useLinkClickHandler(to, {
780 replace,
781 state,
782 target,
783 preventScrollReset,
784 relative,
785 viewTransition
786 });
787 function handleClick(event) {
788 if (onClick) onClick(event);
789 if (!event.defaultPrevented) {
790 internalOnClick(event);
791 }
792 }
793 return (
794 /*#__PURE__*/
795 // eslint-disable-next-line jsx-a11y/anchor-has-content
796 React.createElement("a", _extends({}, rest, {
797 href: absoluteHref || href,
798 onClick: isExternal || reloadDocument ? onClick : handleClick,
799 ref: ref,
800 target: target
801 }))
802 );
803});
804if (process.env.NODE_ENV !== "production") {
805 Link.displayName = "Link";
806}
807/**
808 * A `<Link>` wrapper that knows if it's "active" or not.
809 */
810const NavLink = /*#__PURE__*/React.forwardRef(function NavLinkWithRef(_ref8, ref) {
811 let {
812 "aria-current": ariaCurrentProp = "page",
813 caseSensitive = false,
814 className: classNameProp = "",
815 end = false,
816 style: styleProp,
817 to,
818 viewTransition,
819 children
820 } = _ref8,
821 rest = _objectWithoutPropertiesLoose(_ref8, _excluded2);
822 let path = useResolvedPath(to, {
823 relative: rest.relative
824 });
825 let location = useLocation();
826 let routerState = React.useContext(UNSAFE_DataRouterStateContext);
827 let {
828 navigator,
829 basename
830 } = React.useContext(UNSAFE_NavigationContext);
831 let isTransitioning = routerState != null &&
832 // Conditional usage is OK here because the usage of a data router is static
833 // eslint-disable-next-line react-hooks/rules-of-hooks
834 useViewTransitionState(path) && viewTransition === true;
835 let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
836 let locationPathname = location.pathname;
837 let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
838 if (!caseSensitive) {
839 locationPathname = locationPathname.toLowerCase();
840 nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
841 toPathname = toPathname.toLowerCase();
842 }
843 if (nextLocationPathname && basename) {
844 nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
845 }
846 // If the `to` has a trailing slash, look at that exact spot. Otherwise,
847 // we're looking for a slash _after_ what's in `to`. For example:
848 //
849 // <NavLink to="/users"> and <NavLink to="/users/">
850 // both want to look for a / at index 6 to match URL `/users/matt`
851 const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
852 let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
853 let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
854 let renderProps = {
855 isActive,
856 isPending,
857 isTransitioning
858 };
859 let ariaCurrent = isActive ? ariaCurrentProp : undefined;
860 let className;
861 if (typeof classNameProp === "function") {
862 className = classNameProp(renderProps);
863 } else {
864 // If the className prop is not a function, we use a default `active`
865 // class for <NavLink />s that are active. In v5 `active` was the default
866 // value for `activeClassName`, but we are removing that API and can still
867 // use the old default behavior for a cleaner upgrade path and keep the
868 // simple styling rules working as they currently do.
869 className = [classNameProp, isActive ? "active" : null, isPending ? "pending" : null, isTransitioning ? "transitioning" : null].filter(Boolean).join(" ");
870 }
871 let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
872 return /*#__PURE__*/React.createElement(Link, _extends({}, rest, {
873 "aria-current": ariaCurrent,
874 className: className,
875 ref: ref,
876 style: style,
877 to: to,
878 viewTransition: viewTransition
879 }), typeof children === "function" ? children(renderProps) : children);
880});
881if (process.env.NODE_ENV !== "production") {
882 NavLink.displayName = "NavLink";
883}
884/**
885 * A `@remix-run/router`-aware `<form>`. It behaves like a normal form except
886 * that the interaction with the server is with `fetch` instead of new document
887 * requests, allowing components to add nicer UX to the page as the form is
888 * submitted and returns with data.
889 */
890const Form = /*#__PURE__*/React.forwardRef((_ref9, forwardedRef) => {
891 let {
892 fetcherKey,
893 navigate,
894 reloadDocument,
895 replace,
896 state,
897 method = defaultMethod,
898 action,
899 onSubmit,
900 relative,
901 preventScrollReset,
902 viewTransition
903 } = _ref9,
904 props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
905 let submit = useSubmit();
906 let formAction = useFormAction(action, {
907 relative
908 });
909 let formMethod = method.toLowerCase() === "get" ? "get" : "post";
910 let submitHandler = event => {
911 onSubmit && onSubmit(event);
912 if (event.defaultPrevented) return;
913 event.preventDefault();
914 let submitter = event.nativeEvent.submitter;
915 let submitMethod = (submitter == null ? void 0 : submitter.getAttribute("formmethod")) || method;
916 submit(submitter || event.currentTarget, {
917 fetcherKey,
918 method: submitMethod,
919 navigate,
920 replace,
921 state,
922 relative,
923 preventScrollReset,
924 viewTransition
925 });
926 };
927 return /*#__PURE__*/React.createElement("form", _extends({
928 ref: forwardedRef,
929 method: formMethod,
930 action: formAction,
931 onSubmit: reloadDocument ? onSubmit : submitHandler
932 }, props));
933});
934if (process.env.NODE_ENV !== "production") {
935 Form.displayName = "Form";
936}
937/**
938 * This component will emulate the browser's scroll restoration on location
939 * changes.
940 */
941function ScrollRestoration(_ref10) {
942 let {
943 getKey,
944 storageKey
945 } = _ref10;
946 useScrollRestoration({
947 getKey,
948 storageKey
949 });
950 return null;
951}
952if (process.env.NODE_ENV !== "production") {
953 ScrollRestoration.displayName = "ScrollRestoration";
954}
955//#endregion
956////////////////////////////////////////////////////////////////////////////////
957//#region Hooks
958////////////////////////////////////////////////////////////////////////////////
959var DataRouterHook;
960(function (DataRouterHook) {
961 DataRouterHook["UseScrollRestoration"] = "useScrollRestoration";
962 DataRouterHook["UseSubmit"] = "useSubmit";
963 DataRouterHook["UseSubmitFetcher"] = "useSubmitFetcher";
964 DataRouterHook["UseFetcher"] = "useFetcher";
965 DataRouterHook["useViewTransitionState"] = "useViewTransitionState";
966})(DataRouterHook || (DataRouterHook = {}));
967var DataRouterStateHook;
968(function (DataRouterStateHook) {
969 DataRouterStateHook["UseFetcher"] = "useFetcher";
970 DataRouterStateHook["UseFetchers"] = "useFetchers";
971 DataRouterStateHook["UseScrollRestoration"] = "useScrollRestoration";
972})(DataRouterStateHook || (DataRouterStateHook = {}));
973// Internal hooks
974function getDataRouterConsoleError(hookName) {
975 return hookName + " must be used within a data router. See https://reactrouter.com/v6/routers/picking-a-router.";
976}
977function useDataRouterContext(hookName) {
978 let ctx = React.useContext(UNSAFE_DataRouterContext);
979 !ctx ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
980 return ctx;
981}
982function useDataRouterState(hookName) {
983 let state = React.useContext(UNSAFE_DataRouterStateContext);
984 !state ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, getDataRouterConsoleError(hookName)) : UNSAFE_invariant(false) : void 0;
985 return state;
986}
987// External hooks
988/**
989 * Handles the click behavior for router `<Link>` components. This is useful if
990 * you need to create custom `<Link>` components with the same click behavior we
991 * use in our exported `<Link>`.
992 */
993function useLinkClickHandler(to, _temp) {
994 let {
995 target,
996 replace: replaceProp,
997 state,
998 preventScrollReset,
999 relative,
1000 viewTransition
1001 } = _temp === void 0 ? {} : _temp;
1002 let navigate = useNavigate();
1003 let location = useLocation();
1004 let path = useResolvedPath(to, {
1005 relative
1006 });
1007 return React.useCallback(event => {
1008 if (shouldProcessLinkClick(event, target)) {
1009 event.preventDefault();
1010 // If the URL hasn't changed, a regular <a> will do a replace instead of
1011 // a push, so do the same here unless the replace prop is explicitly set
1012 let replace = replaceProp !== undefined ? replaceProp : createPath(location) === createPath(path);
1013 navigate(to, {
1014 replace,
1015 state,
1016 preventScrollReset,
1017 relative,
1018 viewTransition
1019 });
1020 }
1021 }, [location, navigate, path, replaceProp, state, target, to, preventScrollReset, relative, viewTransition]);
1022}
1023/**
1024 * A convenient wrapper for reading and writing search parameters via the
1025 * URLSearchParams interface.
1026 */
1027function useSearchParams(defaultInit) {
1028 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;
1029 let defaultSearchParamsRef = React.useRef(createSearchParams(defaultInit));
1030 let hasSetSearchParamsRef = React.useRef(false);
1031 let location = useLocation();
1032 let searchParams = React.useMemo(() =>
1033 // Only merge in the defaults if we haven't yet called setSearchParams.
1034 // Once we call that we want those to take precedence, otherwise you can't
1035 // remove a param with setSearchParams({}) if it has an initial value
1036 getSearchParamsForLocation(location.search, hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current), [location.search]);
1037 let navigate = useNavigate();
1038 let setSearchParams = React.useCallback((nextInit, navigateOptions) => {
1039 const newSearchParams = createSearchParams(typeof nextInit === "function" ? nextInit(searchParams) : nextInit);
1040 hasSetSearchParamsRef.current = true;
1041 navigate("?" + newSearchParams, navigateOptions);
1042 }, [navigate, searchParams]);
1043 return [searchParams, setSearchParams];
1044}
1045function validateClientSideSubmission() {
1046 if (typeof document === "undefined") {
1047 throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead.");
1048 }
1049}
1050let fetcherId = 0;
1051let getUniqueFetcherId = () => "__" + String(++fetcherId) + "__";
1052/**
1053 * Returns a function that may be used to programmatically submit a form (or
1054 * some arbitrary data) to the server.
1055 */
1056function useSubmit() {
1057 let {
1058 router
1059 } = useDataRouterContext(DataRouterHook.UseSubmit);
1060 let {
1061 basename
1062 } = React.useContext(UNSAFE_NavigationContext);
1063 let currentRouteId = UNSAFE_useRouteId();
1064 return React.useCallback(function (target, options) {
1065 if (options === void 0) {
1066 options = {};
1067 }
1068 validateClientSideSubmission();
1069 let {
1070 action,
1071 method,
1072 encType,
1073 formData,
1074 body
1075 } = getFormSubmissionInfo(target, basename);
1076 if (options.navigate === false) {
1077 let key = options.fetcherKey || getUniqueFetcherId();
1078 router.fetch(key, currentRouteId, options.action || action, {
1079 preventScrollReset: options.preventScrollReset,
1080 formData,
1081 body,
1082 formMethod: options.method || method,
1083 formEncType: options.encType || encType,
1084 flushSync: options.flushSync
1085 });
1086 } else {
1087 router.navigate(options.action || action, {
1088 preventScrollReset: options.preventScrollReset,
1089 formData,
1090 body,
1091 formMethod: options.method || method,
1092 formEncType: options.encType || encType,
1093 replace: options.replace,
1094 state: options.state,
1095 fromRouteId: currentRouteId,
1096 flushSync: options.flushSync,
1097 viewTransition: options.viewTransition
1098 });
1099 }
1100 }, [router, basename, currentRouteId]);
1101}
1102// v7: Eventually we should deprecate this entirely in favor of using the
1103// router method directly?
1104function useFormAction(action, _temp2) {
1105 let {
1106 relative
1107 } = _temp2 === void 0 ? {} : _temp2;
1108 let {
1109 basename
1110 } = React.useContext(UNSAFE_NavigationContext);
1111 let routeContext = React.useContext(UNSAFE_RouteContext);
1112 !routeContext ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFormAction must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1113 let [match] = routeContext.matches.slice(-1);
1114 // Shallow clone path so we can modify it below, otherwise we modify the
1115 // object referenced by useMemo inside useResolvedPath
1116 let path = _extends({}, useResolvedPath(action ? action : ".", {
1117 relative
1118 }));
1119 // If no action was specified, browsers will persist current search params
1120 // when determining the path, so match that behavior
1121 // https://github.com/remix-run/remix/issues/927
1122 let location = useLocation();
1123 if (action == null) {
1124 // Safe to write to this directly here since if action was undefined, we
1125 // would have called useResolvedPath(".") which will never include a search
1126 path.search = location.search;
1127 // When grabbing search params from the URL, remove any included ?index param
1128 // since it might not apply to our contextual route. We add it back based
1129 // on match.route.index below
1130 let params = new URLSearchParams(path.search);
1131 let indexValues = params.getAll("index");
1132 let hasNakedIndexParam = indexValues.some(v => v === "");
1133 if (hasNakedIndexParam) {
1134 params.delete("index");
1135 indexValues.filter(v => v).forEach(v => params.append("index", v));
1136 let qs = params.toString();
1137 path.search = qs ? "?" + qs : "";
1138 }
1139 }
1140 if ((!action || action === ".") && match.route.index) {
1141 path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
1142 }
1143 // If we're operating within a basename, prepend it to the pathname prior
1144 // to creating the form action. If this is a root navigation, then just use
1145 // the raw basename which allows the basename to have full control over the
1146 // presence of a trailing slash on root actions
1147 if (basename !== "/") {
1148 path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
1149 }
1150 return createPath(path);
1151}
1152// TODO: (v7) Change the useFetcher generic default from `any` to `unknown`
1153/**
1154 * Interacts with route loaders and actions without causing a navigation. Great
1155 * for any interaction that stays on the same page.
1156 */
1157function useFetcher(_temp3) {
1158 var _route$matches;
1159 let {
1160 key
1161 } = _temp3 === void 0 ? {} : _temp3;
1162 let {
1163 router
1164 } = useDataRouterContext(DataRouterHook.UseFetcher);
1165 let state = useDataRouterState(DataRouterStateHook.UseFetcher);
1166 let fetcherData = React.useContext(FetchersContext);
1167 let route = React.useContext(UNSAFE_RouteContext);
1168 let routeId = (_route$matches = route.matches[route.matches.length - 1]) == null ? void 0 : _route$matches.route.id;
1169 !fetcherData ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a FetchersContext") : UNSAFE_invariant(false) : void 0;
1170 !route ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "useFetcher must be used inside a RouteContext") : UNSAFE_invariant(false) : void 0;
1171 !(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;
1172 // Fetcher key handling
1173 // OK to call conditionally to feature detect `useId`
1174 // eslint-disable-next-line react-hooks/rules-of-hooks
1175 let defaultKey = useIdImpl ? useIdImpl() : "";
1176 let [fetcherKey, setFetcherKey] = React.useState(key || defaultKey);
1177 if (key && key !== fetcherKey) {
1178 setFetcherKey(key);
1179 } else if (!fetcherKey) {
1180 // We will only fall through here when `useId` is not available
1181 setFetcherKey(getUniqueFetcherId());
1182 }
1183 // Registration/cleanup
1184 React.useEffect(() => {
1185 router.getFetcher(fetcherKey);
1186 return () => {
1187 // Tell the router we've unmounted - if v7_fetcherPersist is enabled this
1188 // will not delete immediately but instead queue up a delete after the
1189 // fetcher returns to an `idle` state
1190 router.deleteFetcher(fetcherKey);
1191 };
1192 }, [router, fetcherKey]);
1193 // Fetcher additions
1194 let load = React.useCallback((href, opts) => {
1195 !routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
1196 router.fetch(fetcherKey, routeId, href, opts);
1197 }, [fetcherKey, routeId, router]);
1198 let submitImpl = useSubmit();
1199 let submit = React.useCallback((target, opts) => {
1200 submitImpl(target, _extends({}, opts, {
1201 navigate: false,
1202 fetcherKey
1203 }));
1204 }, [fetcherKey, submitImpl]);
1205 let FetcherForm = React.useMemo(() => {
1206 let FetcherForm = /*#__PURE__*/React.forwardRef((props, ref) => {
1207 return /*#__PURE__*/React.createElement(Form, _extends({}, props, {
1208 navigate: false,
1209 fetcherKey: fetcherKey,
1210 ref: ref
1211 }));
1212 });
1213 if (process.env.NODE_ENV !== "production") {
1214 FetcherForm.displayName = "fetcher.Form";
1215 }
1216 return FetcherForm;
1217 }, [fetcherKey]);
1218 // Exposed FetcherWithComponents
1219 let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;
1220 let data = fetcherData.get(fetcherKey);
1221 let fetcherWithComponents = React.useMemo(() => _extends({
1222 Form: FetcherForm,
1223 submit,
1224 load
1225 }, fetcher, {
1226 data
1227 }), [FetcherForm, submit, load, fetcher, data]);
1228 return fetcherWithComponents;
1229}
1230/**
1231 * Provides all fetchers currently on the page. Useful for layouts and parent
1232 * routes that need to provide pending/optimistic UI regarding the fetch.
1233 */
1234function useFetchers() {
1235 let state = useDataRouterState(DataRouterStateHook.UseFetchers);
1236 return Array.from(state.fetchers.entries()).map(_ref11 => {
1237 let [key, fetcher] = _ref11;
1238 return _extends({}, fetcher, {
1239 key
1240 });
1241 });
1242}
1243const SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
1244let savedScrollPositions = {};
1245/**
1246 * When rendered inside a RouterProvider, will restore scroll positions on navigations
1247 */
1248function useScrollRestoration(_temp4) {
1249 let {
1250 getKey,
1251 storageKey
1252 } = _temp4 === void 0 ? {} : _temp4;
1253 let {
1254 router
1255 } = useDataRouterContext(DataRouterHook.UseScrollRestoration);
1256 let {
1257 restoreScrollPosition,
1258 preventScrollReset
1259 } = useDataRouterState(DataRouterStateHook.UseScrollRestoration);
1260 let {
1261 basename
1262 } = React.useContext(UNSAFE_NavigationContext);
1263 let location = useLocation();
1264 let matches = useMatches();
1265 let navigation = useNavigation();
1266 // Trigger manual scroll restoration while we're active
1267 React.useEffect(() => {
1268 window.history.scrollRestoration = "manual";
1269 return () => {
1270 window.history.scrollRestoration = "auto";
1271 };
1272 }, []);
1273 // Save positions on pagehide
1274 usePageHide(React.useCallback(() => {
1275 if (navigation.state === "idle") {
1276 let key = (getKey ? getKey(location, matches) : null) || location.key;
1277 savedScrollPositions[key] = window.scrollY;
1278 }
1279 try {
1280 sessionStorage.setItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY, JSON.stringify(savedScrollPositions));
1281 } catch (error) {
1282 process.env.NODE_ENV !== "production" ? UNSAFE_warning(false, "Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (" + error + ").") : void 0;
1283 }
1284 window.history.scrollRestoration = "auto";
1285 }, [storageKey, getKey, navigation.state, location, matches]));
1286 // Read in any saved scroll locations
1287 if (typeof document !== "undefined") {
1288 // eslint-disable-next-line react-hooks/rules-of-hooks
1289 React.useLayoutEffect(() => {
1290 try {
1291 let sessionPositions = sessionStorage.getItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY);
1292 if (sessionPositions) {
1293 savedScrollPositions = JSON.parse(sessionPositions);
1294 }
1295 } catch (e) {
1296 // no-op, use default empty object
1297 }
1298 }, [storageKey]);
1299 // Enable scroll restoration in the router
1300 // eslint-disable-next-line react-hooks/rules-of-hooks
1301 React.useLayoutEffect(() => {
1302 let getKeyWithoutBasename = getKey && basename !== "/" ? (location, matches) => getKey( // Strip the basename to match useLocation()
1303 _extends({}, location, {
1304 pathname: stripBasename(location.pathname, basename) || location.pathname
1305 }), matches) : getKey;
1306 let disableScrollRestoration = router == null ? void 0 : router.enableScrollRestoration(savedScrollPositions, () => window.scrollY, getKeyWithoutBasename);
1307 return () => disableScrollRestoration && disableScrollRestoration();
1308 }, [router, basename, getKey]);
1309 // Restore scrolling when state.restoreScrollPosition changes
1310 // eslint-disable-next-line react-hooks/rules-of-hooks
1311 React.useLayoutEffect(() => {
1312 // Explicit false means don't do anything (used for submissions)
1313 if (restoreScrollPosition === false) {
1314 return;
1315 }
1316 // been here before, scroll to it
1317 if (typeof restoreScrollPosition === "number") {
1318 window.scrollTo(0, restoreScrollPosition);
1319 return;
1320 }
1321 // try to scroll to the hash
1322 if (location.hash) {
1323 let el = document.getElementById(decodeURIComponent(location.hash.slice(1)));
1324 if (el) {
1325 el.scrollIntoView();
1326 return;
1327 }
1328 }
1329 // Don't reset if this navigation opted out
1330 if (preventScrollReset === true) {
1331 return;
1332 }
1333 // otherwise go to the top on new locations
1334 window.scrollTo(0, 0);
1335 }, [location, restoreScrollPosition, preventScrollReset]);
1336 }
1337}
1338/**
1339 * Setup a callback to be fired on the window's `beforeunload` event. This is
1340 * useful for saving some data to `window.localStorage` just before the page
1341 * refreshes.
1342 *
1343 * Note: The `callback` argument should be a function created with
1344 * `React.useCallback()`.
1345 */
1346function useBeforeUnload(callback, options) {
1347 let {
1348 capture
1349 } = options || {};
1350 React.useEffect(() => {
1351 let opts = capture != null ? {
1352 capture
1353 } : undefined;
1354 window.addEventListener("beforeunload", callback, opts);
1355 return () => {
1356 window.removeEventListener("beforeunload", callback, opts);
1357 };
1358 }, [callback, capture]);
1359}
1360/**
1361 * Setup a callback to be fired on the window's `pagehide` event. This is
1362 * useful for saving some data to `window.localStorage` just before the page
1363 * refreshes. This event is better supported than beforeunload across browsers.
1364 *
1365 * Note: The `callback` argument should be a function created with
1366 * `React.useCallback()`.
1367 */
1368function usePageHide(callback, options) {
1369 let {
1370 capture
1371 } = options || {};
1372 React.useEffect(() => {
1373 let opts = capture != null ? {
1374 capture
1375 } : undefined;
1376 window.addEventListener("pagehide", callback, opts);
1377 return () => {
1378 window.removeEventListener("pagehide", callback, opts);
1379 };
1380 }, [callback, capture]);
1381}
1382/**
1383 * Wrapper around useBlocker to show a window.confirm prompt to users instead
1384 * of building a custom UI with useBlocker.
1385 *
1386 * Warning: This has *a lot of rough edges* and behaves very differently (and
1387 * very incorrectly in some cases) across browsers if user click addition
1388 * back/forward navigations while the confirm is open. Use at your own risk.
1389 */
1390function usePrompt(_ref12) {
1391 let {
1392 when,
1393 message
1394 } = _ref12;
1395 let blocker = useBlocker(when);
1396 React.useEffect(() => {
1397 if (blocker.state === "blocked") {
1398 let proceed = window.confirm(message);
1399 if (proceed) {
1400 // This timeout is needed to avoid a weird "race" on POP navigations
1401 // between the `window.history` revert navigation and the result of
1402 // `window.confirm`
1403 setTimeout(blocker.proceed, 0);
1404 } else {
1405 blocker.reset();
1406 }
1407 }
1408 }, [blocker, message]);
1409 React.useEffect(() => {
1410 if (blocker.state === "blocked" && !when) {
1411 blocker.reset();
1412 }
1413 }, [blocker, when]);
1414}
1415/**
1416 * Return a boolean indicating if there is an active view transition to the
1417 * given href. You can use this value to render CSS classes or viewTransitionName
1418 * styles onto your elements
1419 *
1420 * @param href The destination href
1421 * @param [opts.relative] Relative routing type ("route" | "path")
1422 */
1423function useViewTransitionState(to, opts) {
1424 if (opts === void 0) {
1425 opts = {};
1426 }
1427 let vtContext = React.useContext(ViewTransitionContext);
1428 !(vtContext != null) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. " + "Did you accidentally import `RouterProvider` from `react-router`?") : UNSAFE_invariant(false) : void 0;
1429 let {
1430 basename
1431 } = useDataRouterContext(DataRouterHook.useViewTransitionState);
1432 let path = useResolvedPath(to, {
1433 relative: opts.relative
1434 });
1435 if (!vtContext.isTransitioning) {
1436 return false;
1437 }
1438 let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
1439 let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
1440 // Transition is active if we're going to or coming from the indicated
1441 // destination. This ensures that other PUSH navigations that reverse
1442 // an indicated transition apply. I.e., on the list view you have:
1443 //
1444 // <NavLink to="/details/1" viewTransition>
1445 //
1446 // If you click the breadcrumb back to the list view:
1447 //
1448 // <NavLink to="/list" viewTransition>
1449 //
1450 // We should apply the transition because it's indicated as active going
1451 // from /list -> /details/1 and therefore should be active on the reverse
1452 // (even though this isn't strictly a POP reverse)
1453 return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
1454}
1455//#endregion
1456
1457export { 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, useBeforeUnload, useFetcher, useFetchers, useFormAction, useLinkClickHandler, useSearchParams, useSubmit, useViewTransitionState };
1458//# sourceMappingURL=index.js.map
Note: See TracBrowser for help on using the repository browser.