You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					3757 lines
				
				130 KiB
			
		
		
			
		
	
	
					3757 lines
				
				130 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @remix-run/router v1.2.1
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright (c) Remix Software Inc.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This source code is licensed under the MIT license found in the
							 | 
						||
| 
								 | 
							
								 * LICENSE.md file in the root directory of this source tree.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @license MIT
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								(function (global, factory) {
							 | 
						||
| 
								 | 
							
								  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
							 | 
						||
| 
								 | 
							
								  typeof define === 'function' && define.amd ? define(['exports'], factory) :
							 | 
						||
| 
								 | 
							
								  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RemixRouter = {}));
							 | 
						||
| 
								 | 
							
								})(this, (function (exports) { 'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function _extends() {
							 | 
						||
| 
								 | 
							
								    _extends = Object.assign ? Object.assign.bind() : function (target) {
							 | 
						||
| 
								 | 
							
								      for (var i = 1; i < arguments.length; i++) {
							 | 
						||
| 
								 | 
							
								        var source = arguments[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (var key in source) {
							 | 
						||
| 
								 | 
							
								          if (Object.prototype.hasOwnProperty.call(source, key)) {
							 | 
						||
| 
								 | 
							
								            target[key] = source[key];
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return target;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    return _extends.apply(this, arguments);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region Types and Constants
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Actions represent the type of change to a location value.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  exports.Action = void 0;
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * The pathname, search, and hash values of a URL.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  (function (Action) {
							 | 
						||
| 
								 | 
							
								    Action["Pop"] = "POP";
							 | 
						||
| 
								 | 
							
								    Action["Push"] = "PUSH";
							 | 
						||
| 
								 | 
							
								    Action["Replace"] = "REPLACE";
							 | 
						||
| 
								 | 
							
								  })(exports.Action || (exports.Action = {}));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const PopStateEventType = "popstate"; //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region Memory History
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * A user-supplied object that describes a location. Used when providing
							 | 
						||
| 
								 | 
							
								   * entries to `createMemoryHistory` via its `initialEntries` option.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Memory history stores the current location in memory. It is designed for use
							 | 
						||
| 
								 | 
							
								   * in stateful non-browser environments like tests and React Native.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function createMemoryHistory(options) {
							 | 
						||
| 
								 | 
							
								    if (options === void 0) {
							 | 
						||
| 
								 | 
							
								      options = {};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      initialEntries = ["/"],
							 | 
						||
| 
								 | 
							
								      initialIndex,
							 | 
						||
| 
								 | 
							
								      v5Compat = false
							 | 
						||
| 
								 | 
							
								    } = options;
							 | 
						||
| 
								 | 
							
								    let entries; // Declare so we can access from createMemoryLocation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined));
							 | 
						||
| 
								 | 
							
								    let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);
							 | 
						||
| 
								 | 
							
								    let action = exports.Action.Pop;
							 | 
						||
| 
								 | 
							
								    let listener = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function clampIndex(n) {
							 | 
						||
| 
								 | 
							
								      return Math.min(Math.max(n, 0), entries.length - 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function getCurrentLocation() {
							 | 
						||
| 
								 | 
							
								      return entries[index];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function createMemoryLocation(to, state, key) {
							 | 
						||
| 
								 | 
							
								      if (state === void 0) {
							 | 
						||
| 
								 | 
							
								        state = null;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let location = createLocation(entries ? getCurrentLocation().pathname : "/", to, state, key);
							 | 
						||
| 
								 | 
							
								      warning$1(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to));
							 | 
						||
| 
								 | 
							
								      return location;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let history = {
							 | 
						||
| 
								 | 
							
								      get index() {
							 | 
						||
| 
								 | 
							
								        return index;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      get action() {
							 | 
						||
| 
								 | 
							
								        return action;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      get location() {
							 | 
						||
| 
								 | 
							
								        return getCurrentLocation();
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      createHref(to) {
							 | 
						||
| 
								 | 
							
								        return typeof to === "string" ? to : createPath(to);
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      encodeLocation(to) {
							 | 
						||
| 
								 | 
							
								        let path = typeof to === "string" ? parsePath(to) : to;
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          pathname: path.pathname || "",
							 | 
						||
| 
								 | 
							
								          search: path.search || "",
							 | 
						||
| 
								 | 
							
								          hash: path.hash || ""
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      push(to, state) {
							 | 
						||
| 
								 | 
							
								        action = exports.Action.Push;
							 | 
						||
| 
								 | 
							
								        let nextLocation = createMemoryLocation(to, state);
							 | 
						||
| 
								 | 
							
								        index += 1;
							 | 
						||
| 
								 | 
							
								        entries.splice(index, entries.length, nextLocation);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (v5Compat && listener) {
							 | 
						||
| 
								 | 
							
								          listener({
							 | 
						||
| 
								 | 
							
								            action,
							 | 
						||
| 
								 | 
							
								            location: nextLocation
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      replace(to, state) {
							 | 
						||
| 
								 | 
							
								        action = exports.Action.Replace;
							 | 
						||
| 
								 | 
							
								        let nextLocation = createMemoryLocation(to, state);
							 | 
						||
| 
								 | 
							
								        entries[index] = nextLocation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (v5Compat && listener) {
							 | 
						||
| 
								 | 
							
								          listener({
							 | 
						||
| 
								 | 
							
								            action,
							 | 
						||
| 
								 | 
							
								            location: nextLocation
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      go(delta) {
							 | 
						||
| 
								 | 
							
								        action = exports.Action.Pop;
							 | 
						||
| 
								 | 
							
								        index = clampIndex(index + delta);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (listener) {
							 | 
						||
| 
								 | 
							
								          listener({
							 | 
						||
| 
								 | 
							
								            action,
							 | 
						||
| 
								 | 
							
								            location: getCurrentLocation()
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      listen(fn) {
							 | 
						||
| 
								 | 
							
								        listener = fn;
							 | 
						||
| 
								 | 
							
								        return () => {
							 | 
						||
| 
								 | 
							
								          listener = null;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    return history;
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region Browser History
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * A browser history stores the current location in regular URLs in a web
							 | 
						||
| 
								 | 
							
								   * browser environment. This is the standard for most web apps and provides the
							 | 
						||
| 
								 | 
							
								   * cleanest URLs the browser's address bar.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Browser history stores the location in regular URLs. This is the standard for
							 | 
						||
| 
								 | 
							
								   * most web apps, but it requires some configuration on the server to ensure you
							 | 
						||
| 
								 | 
							
								   * serve the same app at multiple URLs.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function createBrowserHistory(options) {
							 | 
						||
| 
								 | 
							
								    if (options === void 0) {
							 | 
						||
| 
								 | 
							
								      options = {};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function createBrowserLocation(window, globalHistory) {
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        pathname,
							 | 
						||
| 
								 | 
							
								        search,
							 | 
						||
| 
								 | 
							
								        hash
							 | 
						||
| 
								 | 
							
								      } = window.location;
							 | 
						||
| 
								 | 
							
								      return createLocation("", {
							 | 
						||
| 
								 | 
							
								        pathname,
							 | 
						||
| 
								 | 
							
								        search,
							 | 
						||
| 
								 | 
							
								        hash
							 | 
						||
| 
								 | 
							
								      }, // state defaults to `null` because `window.history.state` does
							 | 
						||
| 
								 | 
							
								      globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function createBrowserHref(window, to) {
							 | 
						||
| 
								 | 
							
								      return typeof to === "string" ? to : createPath(to);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options);
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region Hash History
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * A hash history stores the current location in the fragment identifier portion
							 | 
						||
| 
								 | 
							
								   * of the URL in a web browser environment.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * This is ideal for apps that do not control the server for some reason
							 | 
						||
| 
								 | 
							
								   * (because the fragment identifier is never sent to the server), including some
							 | 
						||
| 
								 | 
							
								   * shared hosting environments that do not provide fine-grained controls over
							 | 
						||
| 
								 | 
							
								   * which pages are served at which URLs.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Hash history stores the location in window.location.hash. This makes it ideal
							 | 
						||
| 
								 | 
							
								   * for situations where you don't want to send the location to the server for
							 | 
						||
| 
								 | 
							
								   * some reason, either because you do cannot configure it or the URL space is
							 | 
						||
| 
								 | 
							
								   * reserved for something else.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function createHashHistory(options) {
							 | 
						||
| 
								 | 
							
								    if (options === void 0) {
							 | 
						||
| 
								 | 
							
								      options = {};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function createHashLocation(window, globalHistory) {
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        pathname = "/",
							 | 
						||
| 
								 | 
							
								        search = "",
							 | 
						||
| 
								 | 
							
								        hash = ""
							 | 
						||
| 
								 | 
							
								      } = parsePath(window.location.hash.substr(1));
							 | 
						||
| 
								 | 
							
								      return createLocation("", {
							 | 
						||
| 
								 | 
							
								        pathname,
							 | 
						||
| 
								 | 
							
								        search,
							 | 
						||
| 
								 | 
							
								        hash
							 | 
						||
| 
								 | 
							
								      }, // state defaults to `null` because `window.history.state` does
							 | 
						||
| 
								 | 
							
								      globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function createHashHref(window, to) {
							 | 
						||
| 
								 | 
							
								      let base = window.document.querySelector("base");
							 | 
						||
| 
								 | 
							
								      let href = "";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (base && base.getAttribute("href")) {
							 | 
						||
| 
								 | 
							
								        let url = window.location.href;
							 | 
						||
| 
								 | 
							
								        let hashIndex = url.indexOf("#");
							 | 
						||
| 
								 | 
							
								        href = hashIndex === -1 ? url : url.slice(0, hashIndex);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return href + "#" + (typeof to === "string" ? to : createPath(to));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function validateHashLocation(location, to) {
							 | 
						||
| 
								 | 
							
								      warning$1(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options);
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region UTILS
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function invariant(value, message) {
							 | 
						||
| 
								 | 
							
								    if (value === false || value === null || typeof value === "undefined") {
							 | 
						||
| 
								 | 
							
								      throw new Error(message);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function warning$1(cond, message) {
							 | 
						||
| 
								 | 
							
								    if (!cond) {
							 | 
						||
| 
								 | 
							
								      // eslint-disable-next-line no-console
							 | 
						||
| 
								 | 
							
								      if (typeof console !== "undefined") console.warn(message);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        // Welcome to debugging history!
							 | 
						||
| 
								 | 
							
								        //
							 | 
						||
| 
								 | 
							
								        // This error is thrown as a convenience so you can more easily
							 | 
						||
| 
								 | 
							
								        // find the source for a warning that appears in the console by
							 | 
						||
| 
								 | 
							
								        // enabling "pause on exceptions" in your JavaScript debugger.
							 | 
						||
| 
								 | 
							
								        throw new Error(message); // eslint-disable-next-line no-empty
							 | 
						||
| 
								 | 
							
								      } catch (e) {}
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createKey() {
							 | 
						||
| 
								 | 
							
								    return Math.random().toString(36).substr(2, 8);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * For browser-based histories, we combine the state and key into an object
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getHistoryState(location) {
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      usr: location.state,
							 | 
						||
| 
								 | 
							
								      key: location.key
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Creates a Location object with a unique key from the given Path
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createLocation(current, to, state, key) {
							 | 
						||
| 
								 | 
							
								    if (state === void 0) {
							 | 
						||
| 
								 | 
							
								      state = null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let location = _extends({
							 | 
						||
| 
								 | 
							
								      pathname: typeof current === "string" ? current : current.pathname,
							 | 
						||
| 
								 | 
							
								      search: "",
							 | 
						||
| 
								 | 
							
								      hash: ""
							 | 
						||
| 
								 | 
							
								    }, typeof to === "string" ? parsePath(to) : to, {
							 | 
						||
| 
								 | 
							
								      state,
							 | 
						||
| 
								 | 
							
								      // TODO: This could be cleaned up.  push/replace should probably just take
							 | 
						||
| 
								 | 
							
								      // full Locations now and avoid the need to run through this flow at all
							 | 
						||
| 
								 | 
							
								      // But that's a pretty big refactor to the current test suite so going to
							 | 
						||
| 
								 | 
							
								      // keep as is for the time being and just let any incoming keys take precedence
							 | 
						||
| 
								 | 
							
								      key: to && to.key || key || createKey()
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return location;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Creates a string URL path from the given pathname, search, and hash components.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createPath(_ref) {
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      pathname = "/",
							 | 
						||
| 
								 | 
							
								      search = "",
							 | 
						||
| 
								 | 
							
								      hash = ""
							 | 
						||
| 
								 | 
							
								    } = _ref;
							 | 
						||
| 
								 | 
							
								    if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
							 | 
						||
| 
								 | 
							
								    if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
							 | 
						||
| 
								 | 
							
								    return pathname;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Parses a string URL path into its separate pathname, search, and hash components.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function parsePath(path) {
							 | 
						||
| 
								 | 
							
								    let parsedPath = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (path) {
							 | 
						||
| 
								 | 
							
								      let hashIndex = path.indexOf("#");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (hashIndex >= 0) {
							 | 
						||
| 
								 | 
							
								        parsedPath.hash = path.substr(hashIndex);
							 | 
						||
| 
								 | 
							
								        path = path.substr(0, hashIndex);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let searchIndex = path.indexOf("?");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (searchIndex >= 0) {
							 | 
						||
| 
								 | 
							
								        parsedPath.search = path.substr(searchIndex);
							 | 
						||
| 
								 | 
							
								        path = path.substr(0, searchIndex);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (path) {
							 | 
						||
| 
								 | 
							
								        parsedPath.pathname = path;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return parsedPath;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  function createClientSideURL(location) {
							 | 
						||
| 
								 | 
							
								    // window.location.origin is "null" (the literal string value) in Firefox
							 | 
						||
| 
								 | 
							
								    // under certain conditions, notably when serving from a local HTML file
							 | 
						||
| 
								 | 
							
								    // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
							 | 
						||
| 
								 | 
							
								    let base = typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.origin !== "null" ? window.location.origin : window.location.href;
							 | 
						||
| 
								 | 
							
								    let href = typeof location === "string" ? location : createPath(location);
							 | 
						||
| 
								 | 
							
								    invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
							 | 
						||
| 
								 | 
							
								    return new URL(href, base);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
							 | 
						||
| 
								 | 
							
								    if (options === void 0) {
							 | 
						||
| 
								 | 
							
								      options = {};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      window = document.defaultView,
							 | 
						||
| 
								 | 
							
								      v5Compat = false
							 | 
						||
| 
								 | 
							
								    } = options;
							 | 
						||
| 
								 | 
							
								    let globalHistory = window.history;
							 | 
						||
| 
								 | 
							
								    let action = exports.Action.Pop;
							 | 
						||
| 
								 | 
							
								    let listener = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function handlePop() {
							 | 
						||
| 
								 | 
							
								      action = exports.Action.Pop;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (listener) {
							 | 
						||
| 
								 | 
							
								        listener({
							 | 
						||
| 
								 | 
							
								          action,
							 | 
						||
| 
								 | 
							
								          location: history.location
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function push(to, state) {
							 | 
						||
| 
								 | 
							
								      action = exports.Action.Push;
							 | 
						||
| 
								 | 
							
								      let location = createLocation(history.location, to, state);
							 | 
						||
| 
								 | 
							
								      if (validateLocation) validateLocation(location, to);
							 | 
						||
| 
								 | 
							
								      let historyState = getHistoryState(location);
							 | 
						||
| 
								 | 
							
								      let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        globalHistory.pushState(historyState, "", url);
							 | 
						||
| 
								 | 
							
								      } catch (error) {
							 | 
						||
| 
								 | 
							
								        // They are going to lose state here, but there is no real
							 | 
						||
| 
								 | 
							
								        // way to warn them about it since the page will refresh...
							 | 
						||
| 
								 | 
							
								        window.location.assign(url);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (v5Compat && listener) {
							 | 
						||
| 
								 | 
							
								        listener({
							 | 
						||
| 
								 | 
							
								          action,
							 | 
						||
| 
								 | 
							
								          location: history.location
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function replace(to, state) {
							 | 
						||
| 
								 | 
							
								      action = exports.Action.Replace;
							 | 
						||
| 
								 | 
							
								      let location = createLocation(history.location, to, state);
							 | 
						||
| 
								 | 
							
								      if (validateLocation) validateLocation(location, to);
							 | 
						||
| 
								 | 
							
								      let historyState = getHistoryState(location);
							 | 
						||
| 
								 | 
							
								      let url = history.createHref(location);
							 | 
						||
| 
								 | 
							
								      globalHistory.replaceState(historyState, "", url);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (v5Compat && listener) {
							 | 
						||
| 
								 | 
							
								        listener({
							 | 
						||
| 
								 | 
							
								          action,
							 | 
						||
| 
								 | 
							
								          location: history.location
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let history = {
							 | 
						||
| 
								 | 
							
								      get action() {
							 | 
						||
| 
								 | 
							
								        return action;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      get location() {
							 | 
						||
| 
								 | 
							
								        return getLocation(window, globalHistory);
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      listen(fn) {
							 | 
						||
| 
								 | 
							
								        if (listener) {
							 | 
						||
| 
								 | 
							
								          throw new Error("A history only accepts one active listener");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        window.addEventListener(PopStateEventType, handlePop);
							 | 
						||
| 
								 | 
							
								        listener = fn;
							 | 
						||
| 
								 | 
							
								        return () => {
							 | 
						||
| 
								 | 
							
								          window.removeEventListener(PopStateEventType, handlePop);
							 | 
						||
| 
								 | 
							
								          listener = null;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      createHref(to) {
							 | 
						||
| 
								 | 
							
								        return createHref(window, to);
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      encodeLocation(to) {
							 | 
						||
| 
								 | 
							
								        // Encode a Location the same way window.location would
							 | 
						||
| 
								 | 
							
								        let url = createClientSideURL(typeof to === "string" ? to : createPath(to));
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          pathname: url.pathname,
							 | 
						||
| 
								 | 
							
								          search: url.search,
							 | 
						||
| 
								 | 
							
								          hash: url.hash
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      push,
							 | 
						||
| 
								 | 
							
								      replace,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      go(n) {
							 | 
						||
| 
								 | 
							
								        return globalHistory.go(n);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    return history;
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Map of routeId -> data returned from a loader/action/error
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let ResultType;
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Successful result from a loader or action
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  (function (ResultType) {
							 | 
						||
| 
								 | 
							
								    ResultType["data"] = "data";
							 | 
						||
| 
								 | 
							
								    ResultType["deferred"] = "deferred";
							 | 
						||
| 
								 | 
							
								    ResultType["redirect"] = "redirect";
							 | 
						||
| 
								 | 
							
								    ResultType["error"] = "error";
							 | 
						||
| 
								 | 
							
								  })(ResultType || (ResultType = {}));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isIndexRoute(route) {
							 | 
						||
| 
								 | 
							
								    return route.index === true;
							 | 
						||
| 
								 | 
							
								  } // Walk the route tree generating unique IDs where necessary so we are working
							 | 
						||
| 
								 | 
							
								  // solely with AgnosticDataRouteObject's within the Router
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function convertRoutesToDataRoutes(routes, parentPath, allIds) {
							 | 
						||
| 
								 | 
							
								    if (parentPath === void 0) {
							 | 
						||
| 
								 | 
							
								      parentPath = [];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (allIds === void 0) {
							 | 
						||
| 
								 | 
							
								      allIds = new Set();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return routes.map((route, index) => {
							 | 
						||
| 
								 | 
							
								      let treePath = [...parentPath, index];
							 | 
						||
| 
								 | 
							
								      let id = typeof route.id === "string" ? route.id : treePath.join("-");
							 | 
						||
| 
								 | 
							
								      invariant(route.index !== true || !route.children, "Cannot specify children on an index route");
							 | 
						||
| 
								 | 
							
								      invariant(!allIds.has(id), "Found a route id collision on id \"" + id + "\".  Route " + "id's must be globally unique within Data Router usages");
							 | 
						||
| 
								 | 
							
								      allIds.add(id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isIndexRoute(route)) {
							 | 
						||
| 
								 | 
							
								        let indexRoute = _extends({}, route, {
							 | 
						||
| 
								 | 
							
								          id
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return indexRoute;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        let pathOrLayoutRoute = _extends({}, route, {
							 | 
						||
| 
								 | 
							
								          id,
							 | 
						||
| 
								 | 
							
								          children: route.children ? convertRoutesToDataRoutes(route.children, treePath, allIds) : undefined
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return pathOrLayoutRoute;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Matches the given routes to a location and returns the match data.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://reactrouter.com/utils/match-routes
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function matchRoutes(routes, locationArg, basename) {
							 | 
						||
| 
								 | 
							
								    if (basename === void 0) {
							 | 
						||
| 
								 | 
							
								      basename = "/";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
							 | 
						||
| 
								 | 
							
								    let pathname = stripBasename(location.pathname || "/", basename);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (pathname == null) {
							 | 
						||
| 
								 | 
							
								      return null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let branches = flattenRoutes(routes);
							 | 
						||
| 
								 | 
							
								    rankRouteBranches(branches);
							 | 
						||
| 
								 | 
							
								    let matches = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let i = 0; matches == null && i < branches.length; ++i) {
							 | 
						||
| 
								 | 
							
								      matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location
							 | 
						||
| 
								 | 
							
								      // or from router.navigate, but we want to match against the unencoded
							 | 
						||
| 
								 | 
							
								      // paths in the route definitions.  Memory router locations won't be
							 | 
						||
| 
								 | 
							
								      // encoded here but there also shouldn't be anything to decode so this
							 | 
						||
| 
								 | 
							
								      // should be a safe operation.  This avoids needing matchRoutes to be
							 | 
						||
| 
								 | 
							
								      // history-aware.
							 | 
						||
| 
								 | 
							
								      safelyDecodeURI(pathname));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return matches;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function flattenRoutes(routes, branches, parentsMeta, parentPath) {
							 | 
						||
| 
								 | 
							
								    if (branches === void 0) {
							 | 
						||
| 
								 | 
							
								      branches = [];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (parentsMeta === void 0) {
							 | 
						||
| 
								 | 
							
								      parentsMeta = [];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (parentPath === void 0) {
							 | 
						||
| 
								 | 
							
								      parentPath = "";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let flattenRoute = (route, index, relativePath) => {
							 | 
						||
| 
								 | 
							
								      let meta = {
							 | 
						||
| 
								 | 
							
								        relativePath: relativePath === undefined ? route.path || "" : relativePath,
							 | 
						||
| 
								 | 
							
								        caseSensitive: route.caseSensitive === true,
							 | 
						||
| 
								 | 
							
								        childrenIndex: index,
							 | 
						||
| 
								 | 
							
								        route
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (meta.relativePath.startsWith("/")) {
							 | 
						||
| 
								 | 
							
								        invariant(meta.relativePath.startsWith(parentPath), "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes.");
							 | 
						||
| 
								 | 
							
								        meta.relativePath = meta.relativePath.slice(parentPath.length);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let path = joinPaths([parentPath, meta.relativePath]);
							 | 
						||
| 
								 | 
							
								      let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
							 | 
						||
| 
								 | 
							
								      // route tree depth-first and child routes appear before their parents in
							 | 
						||
| 
								 | 
							
								      // the "flattened" version.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (route.children && route.children.length > 0) {
							 | 
						||
| 
								 | 
							
								        invariant( // Our types know better, but runtime JS may not!
							 | 
						||
| 
								 | 
							
								        // @ts-expect-error
							 | 
						||
| 
								 | 
							
								        route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\"."));
							 | 
						||
| 
								 | 
							
								        flattenRoutes(route.children, branches, routesMeta, path);
							 | 
						||
| 
								 | 
							
								      } // Routes without a path shouldn't ever match by themselves unless they are
							 | 
						||
| 
								 | 
							
								      // index routes, so don't add them to the list of possible branches.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (route.path == null && !route.index) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      branches.push({
							 | 
						||
| 
								 | 
							
								        path,
							 | 
						||
| 
								 | 
							
								        score: computeScore(path, route.index),
							 | 
						||
| 
								 | 
							
								        routesMeta
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    routes.forEach((route, index) => {
							 | 
						||
| 
								 | 
							
								      var _route$path;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // coarse-grain check for optional params
							 | 
						||
| 
								 | 
							
								      if (route.path === "" || !((_route$path = route.path) != null && _route$path.includes("?"))) {
							 | 
						||
| 
								 | 
							
								        flattenRoute(route, index);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        for (let exploded of explodeOptionalSegments(route.path)) {
							 | 
						||
| 
								 | 
							
								          flattenRoute(route, index, exploded);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    return branches;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Computes all combinations of optional path segments for a given path,
							 | 
						||
| 
								 | 
							
								   * excluding combinations that are ambiguous and of lower priority.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * For example, `/one/:two?/three/:four?/:five?` explodes to:
							 | 
						||
| 
								 | 
							
								   * - `/one/three`
							 | 
						||
| 
								 | 
							
								   * - `/one/:two/three`
							 | 
						||
| 
								 | 
							
								   * - `/one/three/:four`
							 | 
						||
| 
								 | 
							
								   * - `/one/three/:five`
							 | 
						||
| 
								 | 
							
								   * - `/one/:two/three/:four`
							 | 
						||
| 
								 | 
							
								   * - `/one/:two/three/:five`
							 | 
						||
| 
								 | 
							
								   * - `/one/three/:four/:five`
							 | 
						||
| 
								 | 
							
								   * - `/one/:two/three/:four/:five`
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function explodeOptionalSegments(path) {
							 | 
						||
| 
								 | 
							
								    let segments = path.split("/");
							 | 
						||
| 
								 | 
							
								    if (segments.length === 0) return [];
							 | 
						||
| 
								 | 
							
								    let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let isOptional = first.endsWith("?"); // Compute the corresponding required segment: `foo?` -> `foo`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let required = first.replace(/\?$/, "");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (rest.length === 0) {
							 | 
						||
| 
								 | 
							
								      // Intepret empty string as omitting an optional segment
							 | 
						||
| 
								 | 
							
								      // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`
							 | 
						||
| 
								 | 
							
								      return isOptional ? [required, ""] : [required];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let restExploded = explodeOptionalSegments(rest.join("/"));
							 | 
						||
| 
								 | 
							
								    let result = []; // All child paths with the prefix.  Do this for all children before the
							 | 
						||
| 
								 | 
							
								    // optional version for all children so we get consistent ordering where the
							 | 
						||
| 
								 | 
							
								    // parent optional aspect is preferred as required.  Otherwise, we can get
							 | 
						||
| 
								 | 
							
								    // child sections interspersed where deeper optional segments are higher than
							 | 
						||
| 
								 | 
							
								    // parent optional segments, where for example, /:two would explodes _earlier_
							 | 
						||
| 
								 | 
							
								    // then /:one.  By always including the parent as required _for all children_
							 | 
						||
| 
								 | 
							
								    // first, we avoid this issue
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/"))); // Then if this is an optional value, add all child versions without
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (isOptional) {
							 | 
						||
| 
								 | 
							
								      result.push(...restExploded);
							 | 
						||
| 
								 | 
							
								    } // for absolute paths, ensure `/` instead of empty segment
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result.map(exploded => path.startsWith("/") && exploded === "" ? "/" : exploded);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function rankRouteBranches(branches) {
							 | 
						||
| 
								 | 
							
								    branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
							 | 
						||
| 
								 | 
							
								    : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const paramRe = /^:\w+$/;
							 | 
						||
| 
								 | 
							
								  const dynamicSegmentValue = 3;
							 | 
						||
| 
								 | 
							
								  const indexRouteValue = 2;
							 | 
						||
| 
								 | 
							
								  const emptySegmentValue = 1;
							 | 
						||
| 
								 | 
							
								  const staticSegmentValue = 10;
							 | 
						||
| 
								 | 
							
								  const splatPenalty = -2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const isSplat = s => s === "*";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function computeScore(path, index) {
							 | 
						||
| 
								 | 
							
								    let segments = path.split("/");
							 | 
						||
| 
								 | 
							
								    let initialScore = segments.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (segments.some(isSplat)) {
							 | 
						||
| 
								 | 
							
								      initialScore += splatPenalty;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (index) {
							 | 
						||
| 
								 | 
							
								      initialScore += indexRouteValue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function compareIndexes(a, b) {
							 | 
						||
| 
								 | 
							
								    let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
							 | 
						||
| 
								 | 
							
								    return siblings ? // If two routes are siblings, we should try to match the earlier sibling
							 | 
						||
| 
								 | 
							
								    // first. This allows people to have fine-grained control over the matching
							 | 
						||
| 
								 | 
							
								    // behavior by simply putting routes with identical paths in the order they
							 | 
						||
| 
								 | 
							
								    // want them tried.
							 | 
						||
| 
								 | 
							
								    a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
							 | 
						||
| 
								 | 
							
								    // so they sort equally.
							 | 
						||
| 
								 | 
							
								    0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function matchRouteBranch(branch, pathname) {
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      routesMeta
							 | 
						||
| 
								 | 
							
								    } = branch;
							 | 
						||
| 
								 | 
							
								    let matchedParams = {};
							 | 
						||
| 
								 | 
							
								    let matchedPathname = "/";
							 | 
						||
| 
								 | 
							
								    let matches = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < routesMeta.length; ++i) {
							 | 
						||
| 
								 | 
							
								      let meta = routesMeta[i];
							 | 
						||
| 
								 | 
							
								      let end = i === routesMeta.length - 1;
							 | 
						||
| 
								 | 
							
								      let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
							 | 
						||
| 
								 | 
							
								      let match = matchPath({
							 | 
						||
| 
								 | 
							
								        path: meta.relativePath,
							 | 
						||
| 
								 | 
							
								        caseSensitive: meta.caseSensitive,
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								      }, remainingPathname);
							 | 
						||
| 
								 | 
							
								      if (!match) return null;
							 | 
						||
| 
								 | 
							
								      Object.assign(matchedParams, match.params);
							 | 
						||
| 
								 | 
							
								      let route = meta.route;
							 | 
						||
| 
								 | 
							
								      matches.push({
							 | 
						||
| 
								 | 
							
								        // TODO: Can this as be avoided?
							 | 
						||
| 
								 | 
							
								        params: matchedParams,
							 | 
						||
| 
								 | 
							
								        pathname: joinPaths([matchedPathname, match.pathname]),
							 | 
						||
| 
								 | 
							
								        pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
							 | 
						||
| 
								 | 
							
								        route
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (match.pathnameBase !== "/") {
							 | 
						||
| 
								 | 
							
								        matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return matches;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Returns a path with params interpolated.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://reactrouter.com/utils/generate-path
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function generatePath(originalPath, params) {
							 | 
						||
| 
								 | 
							
								    if (params === void 0) {
							 | 
						||
| 
								 | 
							
								      params = {};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let path = originalPath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {
							 | 
						||
| 
								 | 
							
								      warning(false, "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
							 | 
						||
| 
								 | 
							
								      path = path.replace(/\*$/, "/*");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return path.replace(/^:(\w+)/g, (_, key) => {
							 | 
						||
| 
								 | 
							
								      invariant(params[key] != null, "Missing \":" + key + "\" param");
							 | 
						||
| 
								 | 
							
								      return params[key];
							 | 
						||
| 
								 | 
							
								    }).replace(/\/:(\w+)/g, (_, key) => {
							 | 
						||
| 
								 | 
							
								      invariant(params[key] != null, "Missing \":" + key + "\" param");
							 | 
						||
| 
								 | 
							
								      return "/" + params[key];
							 | 
						||
| 
								 | 
							
								    }).replace(/(\/?)\*/, (_, prefix, __, str) => {
							 | 
						||
| 
								 | 
							
								      const star = "*";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (params[star] == null) {
							 | 
						||
| 
								 | 
							
								        // If no splat was provided, trim the trailing slash _unless_ it's
							 | 
						||
| 
								 | 
							
								        // the entire path
							 | 
						||
| 
								 | 
							
								        return str === "/*" ? "/" : "";
							 | 
						||
| 
								 | 
							
								      } // Apply the splat
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return "" + prefix + params[star];
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * A PathPattern is used to match on some portion of a URL pathname.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Performs pattern matching on a URL pathname and returns information about
							 | 
						||
| 
								 | 
							
								   * the match.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://reactrouter.com/utils/match-path
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function matchPath(pattern, pathname) {
							 | 
						||
| 
								 | 
							
								    if (typeof pattern === "string") {
							 | 
						||
| 
								 | 
							
								      pattern = {
							 | 
						||
| 
								 | 
							
								        path: pattern,
							 | 
						||
| 
								 | 
							
								        caseSensitive: false,
							 | 
						||
| 
								 | 
							
								        end: true
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
							 | 
						||
| 
								 | 
							
								    let match = pathname.match(matcher);
							 | 
						||
| 
								 | 
							
								    if (!match) return null;
							 | 
						||
| 
								 | 
							
								    let matchedPathname = match[0];
							 | 
						||
| 
								 | 
							
								    let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
							 | 
						||
| 
								 | 
							
								    let captureGroups = match.slice(1);
							 | 
						||
| 
								 | 
							
								    let params = paramNames.reduce((memo, paramName, index) => {
							 | 
						||
| 
								 | 
							
								      // We need to compute the pathnameBase here using the raw splat value
							 | 
						||
| 
								 | 
							
								      // instead of using params["*"] later because it will be decoded then
							 | 
						||
| 
								 | 
							
								      if (paramName === "*") {
							 | 
						||
| 
								 | 
							
								        let splatValue = captureGroups[index] || "";
							 | 
						||
| 
								 | 
							
								        pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
							 | 
						||
| 
								 | 
							
								      return memo;
							 | 
						||
| 
								 | 
							
								    }, {});
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      params,
							 | 
						||
| 
								 | 
							
								      pathname: matchedPathname,
							 | 
						||
| 
								 | 
							
								      pathnameBase,
							 | 
						||
| 
								 | 
							
								      pattern
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function compilePath(path, caseSensitive, end) {
							 | 
						||
| 
								 | 
							
								    if (caseSensitive === void 0) {
							 | 
						||
| 
								 | 
							
								      caseSensitive = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (end === void 0) {
							 | 
						||
| 
								 | 
							
								      end = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
							 | 
						||
| 
								 | 
							
								    let paramNames = [];
							 | 
						||
| 
								 | 
							
								    let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
							 | 
						||
| 
								 | 
							
								    .replace(/^\/*/, "/") // Make sure it has a leading /
							 | 
						||
| 
								 | 
							
								    .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
							 | 
						||
| 
								 | 
							
								    .replace(/\/:(\w+)/g, (_, paramName) => {
							 | 
						||
| 
								 | 
							
								      paramNames.push(paramName);
							 | 
						||
| 
								 | 
							
								      return "/([^\\/]+)";
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (path.endsWith("*")) {
							 | 
						||
| 
								 | 
							
								      paramNames.push("*");
							 | 
						||
| 
								 | 
							
								      regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
							 | 
						||
| 
								 | 
							
								      : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"]
							 | 
						||
| 
								 | 
							
								    } else if (end) {
							 | 
						||
| 
								 | 
							
								      // When matching to the end, ignore trailing slashes
							 | 
						||
| 
								 | 
							
								      regexpSource += "\\/*$";
							 | 
						||
| 
								 | 
							
								    } else if (path !== "" && path !== "/") {
							 | 
						||
| 
								 | 
							
								      // If our path is non-empty and contains anything beyond an initial slash,
							 | 
						||
| 
								 | 
							
								      // then we have _some_ form of path in our regex so we should expect to
							 | 
						||
| 
								 | 
							
								      // match only if we find the end of this path segment.  Look for an optional
							 | 
						||
| 
								 | 
							
								      // non-captured trailing slash (to match a portion of the URL) or the end
							 | 
						||
| 
								 | 
							
								      // of the path (if we've matched to the end).  We used to do this with a
							 | 
						||
| 
								 | 
							
								      // word boundary but that gives false positives on routes like
							 | 
						||
| 
								 | 
							
								      // /user-preferences since `-` counts as a word boundary.
							 | 
						||
| 
								 | 
							
								      regexpSource += "(?:(?=\\/|$))";
							 | 
						||
| 
								 | 
							
								    } else ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
							 | 
						||
| 
								 | 
							
								    return [matcher, paramNames];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function safelyDecodeURI(value) {
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      return decodeURI(value);
							 | 
						||
| 
								 | 
							
								    } catch (error) {
							 | 
						||
| 
								 | 
							
								      warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ")."));
							 | 
						||
| 
								 | 
							
								      return value;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function safelyDecodeURIComponent(value, paramName) {
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      return decodeURIComponent(value);
							 | 
						||
| 
								 | 
							
								    } catch (error) {
							 | 
						||
| 
								 | 
							
								      warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ")."));
							 | 
						||
| 
								 | 
							
								      return value;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function stripBasename(pathname, basename) {
							 | 
						||
| 
								 | 
							
								    if (basename === "/") return pathname;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
							 | 
						||
| 
								 | 
							
								      return null;
							 | 
						||
| 
								 | 
							
								    } // We want to leave trailing slash behavior in the user's control, so if they
							 | 
						||
| 
								 | 
							
								    // specify a basename with a trailing slash, we should support it
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
							 | 
						||
| 
								 | 
							
								    let nextChar = pathname.charAt(startIndex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (nextChar && nextChar !== "/") {
							 | 
						||
| 
								 | 
							
								      // pathname does not start with basename/
							 | 
						||
| 
								 | 
							
								      return null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return pathname.slice(startIndex) || "/";
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function warning(cond, message) {
							 | 
						||
| 
								 | 
							
								    if (!cond) {
							 | 
						||
| 
								 | 
							
								      // eslint-disable-next-line no-console
							 | 
						||
| 
								 | 
							
								      if (typeof console !== "undefined") console.warn(message);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        // Welcome to debugging React Router!
							 | 
						||
| 
								 | 
							
								        //
							 | 
						||
| 
								 | 
							
								        // This error is thrown as a convenience so you can more easily
							 | 
						||
| 
								 | 
							
								        // find the source for a warning that appears in the console by
							 | 
						||
| 
								 | 
							
								        // enabling "pause on exceptions" in your JavaScript debugger.
							 | 
						||
| 
								 | 
							
								        throw new Error(message); // eslint-disable-next-line no-empty
							 | 
						||
| 
								 | 
							
								      } catch (e) {}
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Returns a resolved path object relative to the given pathname.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @see https://reactrouter.com/utils/resolve-path
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function resolvePath(to, fromPathname) {
							 | 
						||
| 
								 | 
							
								    if (fromPathname === void 0) {
							 | 
						||
| 
								 | 
							
								      fromPathname = "/";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      pathname: toPathname,
							 | 
						||
| 
								 | 
							
								      search = "",
							 | 
						||
| 
								 | 
							
								      hash = ""
							 | 
						||
| 
								 | 
							
								    } = typeof to === "string" ? parsePath(to) : to;
							 | 
						||
| 
								 | 
							
								    let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      pathname,
							 | 
						||
| 
								 | 
							
								      search: normalizeSearch(search),
							 | 
						||
| 
								 | 
							
								      hash: normalizeHash(hash)
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function resolvePathname(relativePath, fromPathname) {
							 | 
						||
| 
								 | 
							
								    let segments = fromPathname.replace(/\/+$/, "").split("/");
							 | 
						||
| 
								 | 
							
								    let relativeSegments = relativePath.split("/");
							 | 
						||
| 
								 | 
							
								    relativeSegments.forEach(segment => {
							 | 
						||
| 
								 | 
							
								      if (segment === "..") {
							 | 
						||
| 
								 | 
							
								        // Keep the root "" segment so the pathname starts at /
							 | 
						||
| 
								 | 
							
								        if (segments.length > 1) segments.pop();
							 | 
						||
| 
								 | 
							
								      } else if (segment !== ".") {
							 | 
						||
| 
								 | 
							
								        segments.push(segment);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    return segments.length > 1 ? segments.join("/") : "/";
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getInvalidPathError(char, field, dest, path) {
							 | 
						||
| 
								 | 
							
								    return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "].  Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in <Link to=\"...\"> and the router will parse it for you.";
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * When processing relative navigation we want to ignore ancestor routes that
							 | 
						||
| 
								 | 
							
								   * do not contribute to the path, such that index/pathless layout routes don't
							 | 
						||
| 
								 | 
							
								   * interfere.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * For example, when moving a route element into an index route and/or a
							 | 
						||
| 
								 | 
							
								   * pathless layout route, relative link behavior contained within should stay
							 | 
						||
| 
								 | 
							
								   * the same.  Both of the following examples should link back to the root:
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   *   <Route path="/">
							 | 
						||
| 
								 | 
							
								   *     <Route path="accounts" element={<Link to=".."}>
							 | 
						||
| 
								 | 
							
								   *   </Route>
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   *   <Route path="/">
							 | 
						||
| 
								 | 
							
								   *     <Route path="accounts">
							 | 
						||
| 
								 | 
							
								   *       <Route element={<AccountsLayout />}>       // <-- Does not contribute
							 | 
						||
| 
								 | 
							
								   *         <Route index element={<Link to=".."} />  // <-- Does not contribute
							 | 
						||
| 
								 | 
							
								   *       </Route
							 | 
						||
| 
								 | 
							
								   *     </Route>
							 | 
						||
| 
								 | 
							
								   *   </Route>
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getPathContributingMatches(matches) {
							 | 
						||
| 
								 | 
							
								    return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
							 | 
						||
| 
								 | 
							
								    if (isPathRelative === void 0) {
							 | 
						||
| 
								 | 
							
								      isPathRelative = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let to;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (typeof toArg === "string") {
							 | 
						||
| 
								 | 
							
								      to = parsePath(toArg);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      to = _extends({}, toArg);
							 | 
						||
| 
								 | 
							
								      invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
							 | 
						||
| 
								 | 
							
								      invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
							 | 
						||
| 
								 | 
							
								      invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let isEmptyPath = toArg === "" || to.pathname === "";
							 | 
						||
| 
								 | 
							
								    let toPathname = isEmptyPath ? "/" : to.pathname;
							 | 
						||
| 
								 | 
							
								    let from; // Routing is relative to the current pathname if explicitly requested.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // If a pathname is explicitly provided in `to`, it should be relative to the
							 | 
						||
| 
								 | 
							
								    // route context. This is explained in `Note on `<Link to>` values` in our
							 | 
						||
| 
								 | 
							
								    // migration guide from v5 as a means of disambiguation between `to` values
							 | 
						||
| 
								 | 
							
								    // that begin with `/` and those that do not. However, this is problematic for
							 | 
						||
| 
								 | 
							
								    // `to` values that do not provide a pathname. `to` can simply be a search or
							 | 
						||
| 
								 | 
							
								    // hash string, in which case we should assume that the navigation is relative
							 | 
						||
| 
								 | 
							
								    // to the current location's pathname and *not* the route pathname.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (isPathRelative || toPathname == null) {
							 | 
						||
| 
								 | 
							
								      from = locationPathname;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      let routePathnameIndex = routePathnames.length - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (toPathname.startsWith("..")) {
							 | 
						||
| 
								 | 
							
								        let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
							 | 
						||
| 
								 | 
							
								        // URL segment".  This is a key difference from how <a href> works and a
							 | 
						||
| 
								 | 
							
								        // major reason we call this a "to" value instead of a "href".
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        while (toSegments[0] === "..") {
							 | 
						||
| 
								 | 
							
								          toSegments.shift();
							 | 
						||
| 
								 | 
							
								          routePathnameIndex -= 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        to.pathname = toSegments.join("/");
							 | 
						||
| 
								 | 
							
								      } // If there are more ".." segments than parent routes, resolve relative to
							 | 
						||
| 
								 | 
							
								      // the root / URL.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original "to" had one
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); // Or if this was a link to the current path which has a trailing slash
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
							 | 
						||
| 
								 | 
							
								      path.pathname += "/";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return path;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getToPathname(to) {
							 | 
						||
| 
								 | 
							
								    // Empty strings should be treated the same as / paths
							 | 
						||
| 
								 | 
							
								    return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * This is a shortcut for creating `application/json` responses. Converts `data`
							 | 
						||
| 
								 | 
							
								   * to JSON and sets the `Content-Type` header.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  const json = function json(data, init) {
							 | 
						||
| 
								 | 
							
								    if (init === void 0) {
							 | 
						||
| 
								 | 
							
								      init = {};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let responseInit = typeof init === "number" ? {
							 | 
						||
| 
								 | 
							
								      status: init
							 | 
						||
| 
								 | 
							
								    } : init;
							 | 
						||
| 
								 | 
							
								    let headers = new Headers(responseInit.headers);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!headers.has("Content-Type")) {
							 | 
						||
| 
								 | 
							
								      headers.set("Content-Type", "application/json; charset=utf-8");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return new Response(JSON.stringify(data), _extends({}, responseInit, {
							 | 
						||
| 
								 | 
							
								      headers
							 | 
						||
| 
								 | 
							
								    }));
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  class AbortedDeferredError extends Error {}
							 | 
						||
| 
								 | 
							
								  class DeferredData {
							 | 
						||
| 
								 | 
							
								    constructor(data) {
							 | 
						||
| 
								 | 
							
								      this.pendingKeys = new Set();
							 | 
						||
| 
								 | 
							
								      this.subscriber = undefined;
							 | 
						||
| 
								 | 
							
								      invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early
							 | 
						||
| 
								 | 
							
								      // cancellation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let reject;
							 | 
						||
| 
								 | 
							
								      this.abortPromise = new Promise((_, r) => reject = r);
							 | 
						||
| 
								 | 
							
								      this.controller = new AbortController();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this.controller.signal.addEventListener("abort", onAbort);
							 | 
						||
| 
								 | 
							
								      this.data = Object.entries(data).reduce((acc, _ref) => {
							 | 
						||
| 
								 | 
							
								        let [key, value] = _ref;
							 | 
						||
| 
								 | 
							
								        return Object.assign(acc, {
							 | 
						||
| 
								 | 
							
								          [key]: this.trackPromise(key, value)
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }, {});
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    trackPromise(key, value) {
							 | 
						||
| 
								 | 
							
								      if (!(value instanceof Promise)) {
							 | 
						||
| 
								 | 
							
								        return value;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this.pendingKeys.add(key); // We store a little wrapper promise that will be extended with
							 | 
						||
| 
								 | 
							
								      // _data/_error props upon resolve/reject
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on
							 | 
						||
| 
								 | 
							
								      // errors or aborted deferred values
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      promise.catch(() => {});
							 | 
						||
| 
								 | 
							
								      Object.defineProperty(promise, "_tracked", {
							 | 
						||
| 
								 | 
							
								        get: () => true
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      return promise;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    onSettle(promise, key, error, data) {
							 | 
						||
| 
								 | 
							
								      if (this.controller.signal.aborted && error instanceof AbortedDeferredError) {
							 | 
						||
| 
								 | 
							
								        this.unlistenAbortSignal();
							 | 
						||
| 
								 | 
							
								        Object.defineProperty(promise, "_error", {
							 | 
						||
| 
								 | 
							
								          get: () => error
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return Promise.reject(error);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this.pendingKeys.delete(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (this.done) {
							 | 
						||
| 
								 | 
							
								        // Nothing left to abort!
							 | 
						||
| 
								 | 
							
								        this.unlistenAbortSignal();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const subscriber = this.subscriber;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (error) {
							 | 
						||
| 
								 | 
							
								        Object.defineProperty(promise, "_error", {
							 | 
						||
| 
								 | 
							
								          get: () => error
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        subscriber && subscriber(false);
							 | 
						||
| 
								 | 
							
								        return Promise.reject(error);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Object.defineProperty(promise, "_data", {
							 | 
						||
| 
								 | 
							
								        get: () => data
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      subscriber && subscriber(false);
							 | 
						||
| 
								 | 
							
								      return data;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    subscribe(fn) {
							 | 
						||
| 
								 | 
							
								      this.subscriber = fn;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    cancel() {
							 | 
						||
| 
								 | 
							
								      this.controller.abort();
							 | 
						||
| 
								 | 
							
								      this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k));
							 | 
						||
| 
								 | 
							
								      let subscriber = this.subscriber;
							 | 
						||
| 
								 | 
							
								      subscriber && subscriber(true);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async resolveData(signal) {
							 | 
						||
| 
								 | 
							
								      let aborted = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!this.done) {
							 | 
						||
| 
								 | 
							
								        let onAbort = () => this.cancel();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        signal.addEventListener("abort", onAbort);
							 | 
						||
| 
								 | 
							
								        aborted = await new Promise(resolve => {
							 | 
						||
| 
								 | 
							
								          this.subscribe(aborted => {
							 | 
						||
| 
								 | 
							
								            signal.removeEventListener("abort", onAbort);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (aborted || this.done) {
							 | 
						||
| 
								 | 
							
								              resolve(aborted);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return aborted;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    get done() {
							 | 
						||
| 
								 | 
							
								      return this.pendingKeys.size === 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    get unwrappedData() {
							 | 
						||
| 
								 | 
							
								      invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds");
							 | 
						||
| 
								 | 
							
								      return Object.entries(this.data).reduce((acc, _ref2) => {
							 | 
						||
| 
								 | 
							
								        let [key, value] = _ref2;
							 | 
						||
| 
								 | 
							
								        return Object.assign(acc, {
							 | 
						||
| 
								 | 
							
								          [key]: unwrapTrackedPromise(value)
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }, {});
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isTrackedPromise(value) {
							 | 
						||
| 
								 | 
							
								    return value instanceof Promise && value._tracked === true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function unwrapTrackedPromise(value) {
							 | 
						||
| 
								 | 
							
								    if (!isTrackedPromise(value)) {
							 | 
						||
| 
								 | 
							
								      return value;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (value._error) {
							 | 
						||
| 
								 | 
							
								      throw value._error;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return value._data;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function defer(data) {
							 | 
						||
| 
								 | 
							
								    return new DeferredData(data);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * A redirect response. Sets the status code and the `Location` header.
							 | 
						||
| 
								 | 
							
								   * Defaults to "302 Found".
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  const redirect = function redirect(url, init) {
							 | 
						||
| 
								 | 
							
								    if (init === void 0) {
							 | 
						||
| 
								 | 
							
								      init = 302;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let responseInit = init;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (typeof responseInit === "number") {
							 | 
						||
| 
								 | 
							
								      responseInit = {
							 | 
						||
| 
								 | 
							
								        status: responseInit
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    } else if (typeof responseInit.status === "undefined") {
							 | 
						||
| 
								 | 
							
								      responseInit.status = 302;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let headers = new Headers(responseInit.headers);
							 | 
						||
| 
								 | 
							
								    headers.set("Location", url);
							 | 
						||
| 
								 | 
							
								    return new Response(null, _extends({}, responseInit, {
							 | 
						||
| 
								 | 
							
								      headers
							 | 
						||
| 
								 | 
							
								    }));
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class ErrorResponse {
							 | 
						||
| 
								 | 
							
								    constructor(status, statusText, data, internal) {
							 | 
						||
| 
								 | 
							
								      if (internal === void 0) {
							 | 
						||
| 
								 | 
							
								        internal = false;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      this.status = status;
							 | 
						||
| 
								 | 
							
								      this.statusText = statusText || "";
							 | 
						||
| 
								 | 
							
								      this.internal = internal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (data instanceof Error) {
							 | 
						||
| 
								 | 
							
								        this.data = data.toString();
							 | 
						||
| 
								 | 
							
								        this.error = data;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        this.data = data;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Check if the given error is an ErrorResponse generated from a 4xx/5xx
							 | 
						||
| 
								 | 
							
								   * Response throw from an action/loader
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isRouteErrorResponse(e) {
							 | 
						||
| 
								 | 
							
								    return e instanceof ErrorResponse;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //#region Types and Constants
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * A Router instance manages all navigation and data loading/mutations
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const validMutationMethodsArr = ["post", "put", "patch", "delete"];
							 | 
						||
| 
								 | 
							
								  const validMutationMethods = new Set(validMutationMethodsArr);
							 | 
						||
| 
								 | 
							
								  const validRequestMethodsArr = ["get", ...validMutationMethodsArr];
							 | 
						||
| 
								 | 
							
								  const validRequestMethods = new Set(validRequestMethodsArr);
							 | 
						||
| 
								 | 
							
								  const redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
							 | 
						||
| 
								 | 
							
								  const redirectPreserveMethodStatusCodes = new Set([307, 308]);
							 | 
						||
| 
								 | 
							
								  const IDLE_NAVIGATION = {
							 | 
						||
| 
								 | 
							
								    state: "idle",
							 | 
						||
| 
								 | 
							
								    location: undefined,
							 | 
						||
| 
								 | 
							
								    formMethod: undefined,
							 | 
						||
| 
								 | 
							
								    formAction: undefined,
							 | 
						||
| 
								 | 
							
								    formEncType: undefined,
							 | 
						||
| 
								 | 
							
								    formData: undefined
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  const IDLE_FETCHER = {
							 | 
						||
| 
								 | 
							
								    state: "idle",
							 | 
						||
| 
								 | 
							
								    data: undefined,
							 | 
						||
| 
								 | 
							
								    formMethod: undefined,
							 | 
						||
| 
								 | 
							
								    formAction: undefined,
							 | 
						||
| 
								 | 
							
								    formEncType: undefined,
							 | 
						||
| 
								 | 
							
								    formData: undefined
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								  const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
							 | 
						||
| 
								 | 
							
								  const isServer = !isBrowser; //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region createRouter
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Create a router and listen to history POP navigations
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createRouter(init) {
							 | 
						||
| 
								 | 
							
								    invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
							 | 
						||
| 
								 | 
							
								    let dataRoutes = convertRoutesToDataRoutes(init.routes); // Cleanup function for history
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let unlistenHistory = null; // Externally-provided functions to call on all state changes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let getScrollRestorationKey = null; // Externally-provided function to get current scroll position
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration.  Because
							 | 
						||
| 
								 | 
							
								    // we don't get the saved positions from <ScrollRestoration /> until _after_
							 | 
						||
| 
								 | 
							
								    // the initial render, we need to manually trigger a separate updateState to
							 | 
						||
| 
								 | 
							
								    // send along the restoreScrollPosition
							 | 
						||
| 
								 | 
							
								    // Set to true if we have `hydrationData` since we assume we were SSR'd and that
							 | 
						||
| 
								 | 
							
								    // SSR did the initial scroll restoration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let initialScrollRestored = init.hydrationData != null;
							 | 
						||
| 
								 | 
							
								    let initialMatches = matchRoutes(dataRoutes, init.history.location, init.basename);
							 | 
						||
| 
								 | 
							
								    let initialErrors = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (initialMatches == null) {
							 | 
						||
| 
								 | 
							
								      // If we do not match a user-provided-route, fall back to the root
							 | 
						||
| 
								 | 
							
								      // to allow the error boundary to take over
							 | 
						||
| 
								 | 
							
								      let error = getInternalRouterError(404, {
							 | 
						||
| 
								 | 
							
								        pathname: init.history.location.pathname
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        matches,
							 | 
						||
| 
								 | 
							
								        route
							 | 
						||
| 
								 | 
							
								      } = getShortCircuitMatches(dataRoutes);
							 | 
						||
| 
								 | 
							
								      initialMatches = matches;
							 | 
						||
| 
								 | 
							
								      initialErrors = {
							 | 
						||
| 
								 | 
							
								        [route.id]: error
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let initialized = !initialMatches.some(m => m.route.loader) || init.hydrationData != null;
							 | 
						||
| 
								 | 
							
								    let router;
							 | 
						||
| 
								 | 
							
								    let state = {
							 | 
						||
| 
								 | 
							
								      historyAction: init.history.action,
							 | 
						||
| 
								 | 
							
								      location: init.history.location,
							 | 
						||
| 
								 | 
							
								      matches: initialMatches,
							 | 
						||
| 
								 | 
							
								      initialized,
							 | 
						||
| 
								 | 
							
								      navigation: IDLE_NAVIGATION,
							 | 
						||
| 
								 | 
							
								      // Don't restore on initial updateState() if we were SSR'd
							 | 
						||
| 
								 | 
							
								      restoreScrollPosition: init.hydrationData != null ? false : null,
							 | 
						||
| 
								 | 
							
								      preventScrollReset: false,
							 | 
						||
| 
								 | 
							
								      revalidation: "idle",
							 | 
						||
| 
								 | 
							
								      loaderData: init.hydrationData && init.hydrationData.loaderData || {},
							 | 
						||
| 
								 | 
							
								      actionData: init.hydrationData && init.hydrationData.actionData || null,
							 | 
						||
| 
								 | 
							
								      errors: init.hydrationData && init.hydrationData.errors || initialErrors,
							 | 
						||
| 
								 | 
							
								      fetchers: new Map()
							 | 
						||
| 
								 | 
							
								    }; // -- Stateful internal variables to manage navigations --
							 | 
						||
| 
								 | 
							
								    // Current navigation in progress (to be committed in completeNavigation)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let pendingAction = exports.Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot
							 | 
						||
| 
								 | 
							
								    // be restored?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let pendingPreventScrollReset = false; // AbortController for the active navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a
							 | 
						||
| 
								 | 
							
								    // revalidation is entirely uninterrupted
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders:
							 | 
						||
| 
								 | 
							
								    //  - submissions (completed or interrupted)
							 | 
						||
| 
								 | 
							
								    //  - useRevalidate()
							 | 
						||
| 
								 | 
							
								    //  - X-Remix-Revalidate (from redirect)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due
							 | 
						||
| 
								 | 
							
								    // to a cancelled deferred on action submission
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an
							 | 
						||
| 
								 | 
							
								    // action navigation and require revalidation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let fetchControllers = new Map(); // Track loads based on the order in which they started
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against
							 | 
						||
| 
								 | 
							
								    // the globally incrementing load when a fetcher load lands after a completed
							 | 
						||
| 
								 | 
							
								    // navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations from their actions
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches.  When a
							 | 
						||
| 
								 | 
							
								    // route loader returns defer() we stick one in here.  Then, when a nested
							 | 
						||
| 
								 | 
							
								    // promise resolves we update loaderData.  If a new navigation starts we
							 | 
						||
| 
								 | 
							
								    // cancel active deferreds for eliminated routes.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let activeDeferreds = new Map(); // Initialize the router, all side effects should be kicked off from here.
							 | 
						||
| 
								 | 
							
								    // Implemented as a Fluent API for ease of:
							 | 
						||
| 
								 | 
							
								    //   let router = createRouter(init).initialize();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function initialize() {
							 | 
						||
| 
								 | 
							
								      // If history informs us of a POP navigation, start the navigation but do not update
							 | 
						||
| 
								 | 
							
								      // state.  We'll update our own state once the navigation completes
							 | 
						||
| 
								 | 
							
								      unlistenHistory = init.history.listen(_ref => {
							 | 
						||
| 
								 | 
							
								        let {
							 | 
						||
| 
								 | 
							
								          action: historyAction,
							 | 
						||
| 
								 | 
							
								          location
							 | 
						||
| 
								 | 
							
								        } = _ref;
							 | 
						||
| 
								 | 
							
								        return startNavigation(historyAction, location);
							 | 
						||
| 
								 | 
							
								      }); // Kick off initial data load if needed.  Use Pop to avoid modifying history
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!state.initialized) {
							 | 
						||
| 
								 | 
							
								        startNavigation(exports.Action.Pop, state.location);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return router;
							 | 
						||
| 
								 | 
							
								    } // Clean up a router and it's side effects
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function dispose() {
							 | 
						||
| 
								 | 
							
								      if (unlistenHistory) {
							 | 
						||
| 
								 | 
							
								        unlistenHistory();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      subscribers.clear();
							 | 
						||
| 
								 | 
							
								      pendingNavigationController && pendingNavigationController.abort();
							 | 
						||
| 
								 | 
							
								      state.fetchers.forEach((_, key) => deleteFetcher(key));
							 | 
						||
| 
								 | 
							
								    } // Subscribe to state updates for the router
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function subscribe(fn) {
							 | 
						||
| 
								 | 
							
								      subscribers.add(fn);
							 | 
						||
| 
								 | 
							
								      return () => subscribers.delete(fn);
							 | 
						||
| 
								 | 
							
								    } // Update our state and notify the calling context of the change
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function updateState(newState) {
							 | 
						||
| 
								 | 
							
								      state = _extends({}, state, newState);
							 | 
						||
| 
								 | 
							
								      subscribers.forEach(subscriber => subscriber(state));
							 | 
						||
| 
								 | 
							
								    } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
							 | 
						||
| 
								 | 
							
								    // and setting state.[historyAction/location/matches] to the new route.
							 | 
						||
| 
								 | 
							
								    // - Location is a required param
							 | 
						||
| 
								 | 
							
								    // - Navigation will always be set to IDLE_NAVIGATION
							 | 
						||
| 
								 | 
							
								    // - Can pass any other state in newState
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function completeNavigation(location, newState) {
							 | 
						||
| 
								 | 
							
								      var _location$state;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Deduce if we're in a loading/actionReload state:
							 | 
						||
| 
								 | 
							
								      // - We have committed actionData in the store
							 | 
						||
| 
								 | 
							
								      // - The current navigation was a mutation submission
							 | 
						||
| 
								 | 
							
								      // - We're past the submitting state and into the loading state
							 | 
						||
| 
								 | 
							
								      // - The location being loaded is not the result of a redirect
							 | 
						||
| 
								 | 
							
								      let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && ((_location$state = location.state) == null ? void 0 : _location$state._isRedirect) !== true;
							 | 
						||
| 
								 | 
							
								      let actionData;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (newState.actionData) {
							 | 
						||
| 
								 | 
							
								        if (Object.keys(newState.actionData).length > 0) {
							 | 
						||
| 
								 | 
							
								          actionData = newState.actionData;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          // Empty actionData -> clear prior actionData due to an action error
							 | 
						||
| 
								 | 
							
								          actionData = null;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (isActionReload) {
							 | 
						||
| 
								 | 
							
								        // Keep the current data if we're wrapping up the action reload
							 | 
						||
| 
								 | 
							
								        actionData = state.actionData;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        // Clear actionData on any other completed navigations
							 | 
						||
| 
								 | 
							
								        actionData = null;
							 | 
						||
| 
								 | 
							
								      } // Always preserve any existing loaderData from re-used routes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData;
							 | 
						||
| 
								 | 
							
								      updateState(_extends({}, newState, {
							 | 
						||
| 
								 | 
							
								        // matches, errors, fetchers go through as-is
							 | 
						||
| 
								 | 
							
								        actionData,
							 | 
						||
| 
								 | 
							
								        loaderData,
							 | 
						||
| 
								 | 
							
								        historyAction: pendingAction,
							 | 
						||
| 
								 | 
							
								        location,
							 | 
						||
| 
								 | 
							
								        initialized: true,
							 | 
						||
| 
								 | 
							
								        navigation: IDLE_NAVIGATION,
							 | 
						||
| 
								 | 
							
								        revalidation: "idle",
							 | 
						||
| 
								 | 
							
								        // Don't restore on submission navigations
							 | 
						||
| 
								 | 
							
								        restoreScrollPosition: state.navigation.formData ? false : getSavedScrollPosition(location, newState.matches || state.matches),
							 | 
						||
| 
								 | 
							
								        preventScrollReset: pendingPreventScrollReset
							 | 
						||
| 
								 | 
							
								      }));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isUninterruptedRevalidation) ; else if (pendingAction === exports.Action.Pop) ; else if (pendingAction === exports.Action.Push) {
							 | 
						||
| 
								 | 
							
								        init.history.push(location, location.state);
							 | 
						||
| 
								 | 
							
								      } else if (pendingAction === exports.Action.Replace) {
							 | 
						||
| 
								 | 
							
								        init.history.replace(location, location.state);
							 | 
						||
| 
								 | 
							
								      } // Reset stateful navigation vars
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      pendingAction = exports.Action.Pop;
							 | 
						||
| 
								 | 
							
								      pendingPreventScrollReset = false;
							 | 
						||
| 
								 | 
							
								      isUninterruptedRevalidation = false;
							 | 
						||
| 
								 | 
							
								      isRevalidationRequired = false;
							 | 
						||
| 
								 | 
							
								      cancelledDeferredRoutes = [];
							 | 
						||
| 
								 | 
							
								      cancelledFetcherLoads = [];
							 | 
						||
| 
								 | 
							
								    } // Trigger a navigation event, which can either be a numerical POP or a PUSH
							 | 
						||
| 
								 | 
							
								    // replace with an optional submission
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function navigate(to, opts) {
							 | 
						||
| 
								 | 
							
								      if (typeof to === "number") {
							 | 
						||
| 
								 | 
							
								        init.history.go(to);
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        path,
							 | 
						||
| 
								 | 
							
								        submission,
							 | 
						||
| 
								 | 
							
								        error
							 | 
						||
| 
								 | 
							
								      } = normalizeNavigateOptions(to, opts);
							 | 
						||
| 
								 | 
							
								      let location = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
							 | 
						||
| 
								 | 
							
								      // URL from window.location, so we need to encode it here so the behavior
							 | 
						||
| 
								 | 
							
								      // remains the same as POP and non-data-router usages.  new URL() does all
							 | 
						||
| 
								 | 
							
								      // the same encoding we'd get from a history.pushState/window.location read
							 | 
						||
| 
								 | 
							
								      // without having to touch history
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      location = _extends({}, location, init.history.encodeLocation(location));
							 | 
						||
| 
								 | 
							
								      let userReplace = opts && opts.replace != null ? opts.replace : undefined;
							 | 
						||
| 
								 | 
							
								      let historyAction = exports.Action.Push;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (userReplace === true) {
							 | 
						||
| 
								 | 
							
								        historyAction = exports.Action.Replace;
							 | 
						||
| 
								 | 
							
								      } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {
							 | 
						||
| 
								 | 
							
								        // By default on submissions to the current location we REPLACE so that
							 | 
						||
| 
								 | 
							
								        // users don't have to double-click the back button to get to the prior
							 | 
						||
| 
								 | 
							
								        // location.  If the user redirects to a different location from the
							 | 
						||
| 
								 | 
							
								        // action/loader this will be ignored and the redirect will be a PUSH
							 | 
						||
| 
								 | 
							
								        historyAction = exports.Action.Replace;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
							 | 
						||
| 
								 | 
							
								      return await startNavigation(historyAction, location, {
							 | 
						||
| 
								 | 
							
								        submission,
							 | 
						||
| 
								 | 
							
								        // Send through the formData serialization error if we have one so we can
							 | 
						||
| 
								 | 
							
								        // render at the right error boundary after we match routes
							 | 
						||
| 
								 | 
							
								        pendingError: error,
							 | 
						||
| 
								 | 
							
								        preventScrollReset,
							 | 
						||
| 
								 | 
							
								        replace: opts && opts.replace
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    } // Revalidate all current loaders.  If a navigation is in progress or if this
							 | 
						||
| 
								 | 
							
								    // is interrupted by a navigation, allow this to "succeed" by calling all
							 | 
						||
| 
								 | 
							
								    // loaders during the next loader round
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function revalidate() {
							 | 
						||
| 
								 | 
							
								      interruptActiveLoads();
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        revalidation: "loading"
							 | 
						||
| 
								 | 
							
								      }); // If we're currently submitting an action, we don't need to start a new
							 | 
						||
| 
								 | 
							
								      // navigation, we'll just let the follow up loader execution call all loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (state.navigation.state === "submitting") {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // If we're currently in an idle state, start a new navigation for the current
							 | 
						||
| 
								 | 
							
								      // action/location and mark it as uninterrupted, which will skip the history
							 | 
						||
| 
								 | 
							
								      // update in completeNavigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (state.navigation.state === "idle") {
							 | 
						||
| 
								 | 
							
								        startNavigation(state.historyAction, state.location, {
							 | 
						||
| 
								 | 
							
								          startUninterruptedRevalidation: true
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Otherwise, if we're currently in a loading state, just start a new
							 | 
						||
| 
								 | 
							
								      // navigation to the navigation.location but do not trigger an uninterrupted
							 | 
						||
| 
								 | 
							
								      // revalidation so that history correctly updates once the navigation completes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      startNavigation(pendingAction || state.historyAction, state.navigation.location, {
							 | 
						||
| 
								 | 
							
								        overrideNavigation: state.navigation
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    } // Start a navigation to the given action/location.  Can optionally provide a
							 | 
						||
| 
								 | 
							
								    // overrideNavigation which will override the normalLoad in the case of a redirect
							 | 
						||
| 
								 | 
							
								    // navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function startNavigation(historyAction, location, opts) {
							 | 
						||
| 
								 | 
							
								      // Abort any in-progress navigations and start a new one. Unset any ongoing
							 | 
						||
| 
								 | 
							
								      // uninterrupted revalidations unless told otherwise, since we want this
							 | 
						||
| 
								 | 
							
								      // new navigation to update history normally
							 | 
						||
| 
								 | 
							
								      pendingNavigationController && pendingNavigationController.abort();
							 | 
						||
| 
								 | 
							
								      pendingNavigationController = null;
							 | 
						||
| 
								 | 
							
								      pendingAction = historyAction;
							 | 
						||
| 
								 | 
							
								      isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation,
							 | 
						||
| 
								 | 
							
								      // and track whether we should reset scroll on completion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      saveScrollPosition(state.location, state.matches);
							 | 
						||
| 
								 | 
							
								      pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
							 | 
						||
| 
								 | 
							
								      let loadingNavigation = opts && opts.overrideNavigation;
							 | 
						||
| 
								 | 
							
								      let matches = matchRoutes(dataRoutes, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!matches) {
							 | 
						||
| 
								 | 
							
								        let error = getInternalRouterError(404, {
							 | 
						||
| 
								 | 
							
								          pathname: location.pathname
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        let {
							 | 
						||
| 
								 | 
							
								          matches: notFoundMatches,
							 | 
						||
| 
								 | 
							
								          route
							 | 
						||
| 
								 | 
							
								        } = getShortCircuitMatches(dataRoutes); // Cancel all pending deferred on 404s since we don't keep any routes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        cancelActiveDeferreds();
							 | 
						||
| 
								 | 
							
								        completeNavigation(location, {
							 | 
						||
| 
								 | 
							
								          matches: notFoundMatches,
							 | 
						||
| 
								 | 
							
								          loaderData: {},
							 | 
						||
| 
								 | 
							
								          errors: {
							 | 
						||
| 
								 | 
							
								            [route.id]: error
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Short circuit if it's only a hash change
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isHashChangeOnly(state.location, location)) {
							 | 
						||
| 
								 | 
							
								        completeNavigation(location, {
							 | 
						||
| 
								 | 
							
								          matches
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Create a controller/Request for this navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      pendingNavigationController = new AbortController();
							 | 
						||
| 
								 | 
							
								      let request = createClientSideRequest(location, pendingNavigationController.signal, opts && opts.submission);
							 | 
						||
| 
								 | 
							
								      let pendingActionData;
							 | 
						||
| 
								 | 
							
								      let pendingError;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (opts && opts.pendingError) {
							 | 
						||
| 
								 | 
							
								        // If we have a pendingError, it means the user attempted a GET submission
							 | 
						||
| 
								 | 
							
								        // with binary FormData so assign here and skip to handleLoaders.  That
							 | 
						||
| 
								 | 
							
								        // way we handle calling loaders above the boundary etc.  It's not really
							 | 
						||
| 
								 | 
							
								        // different from an actionError in that sense.
							 | 
						||
| 
								 | 
							
								        pendingError = {
							 | 
						||
| 
								 | 
							
								          [findNearestBoundary(matches).route.id]: opts.pendingError
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
							 | 
						||
| 
								 | 
							
								        // Call action if we received an action submission
							 | 
						||
| 
								 | 
							
								        let actionOutput = await handleAction(request, location, opts.submission, matches, {
							 | 
						||
| 
								 | 
							
								          replace: opts.replace
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (actionOutput.shortCircuited) {
							 | 
						||
| 
								 | 
							
								          return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pendingActionData = actionOutput.pendingActionData;
							 | 
						||
| 
								 | 
							
								        pendingError = actionOutput.pendingActionError;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        let navigation = _extends({
							 | 
						||
| 
								 | 
							
								          state: "loading",
							 | 
						||
| 
								 | 
							
								          location
							 | 
						||
| 
								 | 
							
								        }, opts.submission);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        loadingNavigation = navigation; // Create a GET request for the loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        request = new Request(request.url, {
							 | 
						||
| 
								 | 
							
								          signal: request.signal
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } // Call loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        shortCircuited,
							 | 
						||
| 
								 | 
							
								        loaderData,
							 | 
						||
| 
								 | 
							
								        errors
							 | 
						||
| 
								 | 
							
								      } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.replace, pendingActionData, pendingError);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (shortCircuited) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Clean up now that the action/loaders have completed.  Don't clean up if
							 | 
						||
| 
								 | 
							
								      // we short circuited because pendingNavigationController will have already
							 | 
						||
| 
								 | 
							
								      // been assigned to a new controller for the next navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      pendingNavigationController = null;
							 | 
						||
| 
								 | 
							
								      completeNavigation(location, _extends({
							 | 
						||
| 
								 | 
							
								        matches
							 | 
						||
| 
								 | 
							
								      }, pendingActionData ? {
							 | 
						||
| 
								 | 
							
								        actionData: pendingActionData
							 | 
						||
| 
								 | 
							
								      } : {}, {
							 | 
						||
| 
								 | 
							
								        loaderData,
							 | 
						||
| 
								 | 
							
								        errors
							 | 
						||
| 
								 | 
							
								      }));
							 | 
						||
| 
								 | 
							
								    } // Call the action matched by the leaf route for this navigation and handle
							 | 
						||
| 
								 | 
							
								    // redirects/errors
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function handleAction(request, location, submission, matches, opts) {
							 | 
						||
| 
								 | 
							
								      interruptActiveLoads(); // Put us in a submitting state
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let navigation = _extends({
							 | 
						||
| 
								 | 
							
								        state: "submitting",
							 | 
						||
| 
								 | 
							
								        location
							 | 
						||
| 
								 | 
							
								      }, submission);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        navigation
							 | 
						||
| 
								 | 
							
								      }); // Call our action and get the result
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let result;
							 | 
						||
| 
								 | 
							
								      let actionMatch = getTargetMatch(matches, location);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!actionMatch.route.action) {
							 | 
						||
| 
								 | 
							
								        result = {
							 | 
						||
| 
								 | 
							
								          type: ResultType.error,
							 | 
						||
| 
								 | 
							
								          error: getInternalRouterError(405, {
							 | 
						||
| 
								 | 
							
								            method: request.method,
							 | 
						||
| 
								 | 
							
								            pathname: location.pathname,
							 | 
						||
| 
								 | 
							
								            routeId: actionMatch.route.id
							 | 
						||
| 
								 | 
							
								          })
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        result = await callLoaderOrAction("action", request, actionMatch, matches, router.basename);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (request.signal.aborted) {
							 | 
						||
| 
								 | 
							
								          return {
							 | 
						||
| 
								 | 
							
								            shortCircuited: true
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRedirectResult(result)) {
							 | 
						||
| 
								 | 
							
								        let replace;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (opts && opts.replace != null) {
							 | 
						||
| 
								 | 
							
								          replace = opts.replace;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          // If the user didn't explicity indicate replace behavior, replace if
							 | 
						||
| 
								 | 
							
								          // we redirected to the exact same location we're currently at to avoid
							 | 
						||
| 
								 | 
							
								          // double back-buttons
							 | 
						||
| 
								 | 
							
								          replace = result.location === state.location.pathname + state.location.search;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        await startRedirectNavigation(state, result, {
							 | 
						||
| 
								 | 
							
								          submission,
							 | 
						||
| 
								 | 
							
								          replace
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          shortCircuited: true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isErrorResult(result)) {
							 | 
						||
| 
								 | 
							
								        // Store off the pending error - we use it to determine which loaders
							 | 
						||
| 
								 | 
							
								        // to call and will commit it when we complete the navigation
							 | 
						||
| 
								 | 
							
								        let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the
							 | 
						||
| 
								 | 
							
								        // action threw an error that'll be rendered in an errorElement, we fall
							 | 
						||
| 
								 | 
							
								        // back to PUSH so that the user can use the back button to get back to
							 | 
						||
| 
								 | 
							
								        // the pre-submission form location to try again
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ((opts && opts.replace) !== true) {
							 | 
						||
| 
								 | 
							
								          pendingAction = exports.Action.Push;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          // Send back an empty object we can use to clear out any prior actionData
							 | 
						||
| 
								 | 
							
								          pendingActionData: {},
							 | 
						||
| 
								 | 
							
								          pendingActionError: {
							 | 
						||
| 
								 | 
							
								            [boundaryMatch.route.id]: result.error
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isDeferredResult(result)) {
							 | 
						||
| 
								 | 
							
								        throw new Error("defer() is not supported in actions");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        pendingActionData: {
							 | 
						||
| 
								 | 
							
								          [actionMatch.route.id]: result.data
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    } // Call all applicable loaders for the given matches, handling redirects,
							 | 
						||
| 
								 | 
							
								    // errors, etc.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function handleLoaders(request, location, matches, overrideNavigation, submission, replace, pendingActionData, pendingError) {
							 | 
						||
| 
								 | 
							
								      // Figure out the right navigation we want to use for data loading
							 | 
						||
| 
								 | 
							
								      let loadingNavigation = overrideNavigation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!loadingNavigation) {
							 | 
						||
| 
								 | 
							
								        let navigation = _extends({
							 | 
						||
| 
								 | 
							
								          state: "loading",
							 | 
						||
| 
								 | 
							
								          location,
							 | 
						||
| 
								 | 
							
								          formMethod: undefined,
							 | 
						||
| 
								 | 
							
								          formAction: undefined,
							 | 
						||
| 
								 | 
							
								          formEncType: undefined,
							 | 
						||
| 
								 | 
							
								          formData: undefined
							 | 
						||
| 
								 | 
							
								        }, submission);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        loadingNavigation = navigation;
							 | 
						||
| 
								 | 
							
								      } // If this was a redirect from an action we don't have a "submission" but
							 | 
						||
| 
								 | 
							
								      // we have it on the loading navigation so use that if available
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let activeSubmission = submission ? submission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? {
							 | 
						||
| 
								 | 
							
								        formMethod: loadingNavigation.formMethod,
							 | 
						||
| 
								 | 
							
								        formAction: loadingNavigation.formAction,
							 | 
						||
| 
								 | 
							
								        formData: loadingNavigation.formData,
							 | 
						||
| 
								 | 
							
								        formEncType: loadingNavigation.formEncType
							 | 
						||
| 
								 | 
							
								      } : undefined;
							 | 
						||
| 
								 | 
							
								      let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
							 | 
						||
| 
								 | 
							
								      // about to reload.  Note that if this is an action reload we would have
							 | 
						||
| 
								 | 
							
								      // already cancelled all pending deferreds so this would be a no-op
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
							 | 
						||
| 
								 | 
							
								        completeNavigation(location, _extends({
							 | 
						||
| 
								 | 
							
								          matches,
							 | 
						||
| 
								 | 
							
								          loaderData: {},
							 | 
						||
| 
								 | 
							
								          // Commit pending error if we're short circuiting
							 | 
						||
| 
								 | 
							
								          errors: pendingError || null
							 | 
						||
| 
								 | 
							
								        }, pendingActionData ? {
							 | 
						||
| 
								 | 
							
								          actionData: pendingActionData
							 | 
						||
| 
								 | 
							
								        } : {}));
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          shortCircuited: true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } // If this is an uninterrupted revalidation, we remain in our current idle
							 | 
						||
| 
								 | 
							
								      // state.  If not, we need to switch to our loading state and load data,
							 | 
						||
| 
								 | 
							
								      // preserving any new action data or existing action data (in the case of
							 | 
						||
| 
								 | 
							
								      // a revalidation interrupting an actionReload)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!isUninterruptedRevalidation) {
							 | 
						||
| 
								 | 
							
								        revalidatingFetchers.forEach(_ref2 => {
							 | 
						||
| 
								 | 
							
								          let [key] = _ref2;
							 | 
						||
| 
								 | 
							
								          let fetcher = state.fetchers.get(key);
							 | 
						||
| 
								 | 
							
								          let revalidatingFetcher = {
							 | 
						||
| 
								 | 
							
								            state: "loading",
							 | 
						||
| 
								 | 
							
								            data: fetcher && fetcher.data,
							 | 
						||
| 
								 | 
							
								            formMethod: undefined,
							 | 
						||
| 
								 | 
							
								            formAction: undefined,
							 | 
						||
| 
								 | 
							
								            formEncType: undefined,
							 | 
						||
| 
								 | 
							
								            formData: undefined,
							 | 
						||
| 
								 | 
							
								            " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								          state.fetchers.set(key, revalidatingFetcher);
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        let actionData = pendingActionData || state.actionData;
							 | 
						||
| 
								 | 
							
								        updateState(_extends({
							 | 
						||
| 
								 | 
							
								          navigation: loadingNavigation
							 | 
						||
| 
								 | 
							
								        }, actionData ? Object.keys(actionData).length === 0 ? {
							 | 
						||
| 
								 | 
							
								          actionData: null
							 | 
						||
| 
								 | 
							
								        } : {
							 | 
						||
| 
								 | 
							
								          actionData
							 | 
						||
| 
								 | 
							
								        } : {}, revalidatingFetchers.length > 0 ? {
							 | 
						||
| 
								 | 
							
								          fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								        } : {}));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      pendingNavigationLoadId = ++incrementingLoadId;
							 | 
						||
| 
								 | 
							
								      revalidatingFetchers.forEach(_ref3 => {
							 | 
						||
| 
								 | 
							
								        let [key] = _ref3;
							 | 
						||
| 
								 | 
							
								        return fetchControllers.set(key, pendingNavigationController);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        results,
							 | 
						||
| 
								 | 
							
								        loaderResults,
							 | 
						||
| 
								 | 
							
								        fetcherResults
							 | 
						||
| 
								 | 
							
								      } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (request.signal.aborted) {
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          shortCircuited: true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } // Clean up _after_ loaders have completed.  Don't clean up if we short
							 | 
						||
| 
								 | 
							
								      // circuited because fetchControllers would have been aborted and
							 | 
						||
| 
								 | 
							
								      // reassigned to new controllers for the next navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      revalidatingFetchers.forEach(_ref4 => {
							 | 
						||
| 
								 | 
							
								        let [key] = _ref4;
							 | 
						||
| 
								 | 
							
								        return fetchControllers.delete(key);
							 | 
						||
| 
								 | 
							
								      }); // If any loaders returned a redirect Response, start a new REPLACE navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let redirect = findRedirect(results);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (redirect) {
							 | 
						||
| 
								 | 
							
								        await startRedirectNavigation(state, redirect, {
							 | 
						||
| 
								 | 
							
								          replace
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          shortCircuited: true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } // Process and commit output from loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        loaderData,
							 | 
						||
| 
								 | 
							
								        errors
							 | 
						||
| 
								 | 
							
								      } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      activeDeferreds.forEach((deferredData, routeId) => {
							 | 
						||
| 
								 | 
							
								        deferredData.subscribe(aborted => {
							 | 
						||
| 
								 | 
							
								          // Note: No need to updateState here since the TrackedPromise on
							 | 
						||
| 
								 | 
							
								          // loaderData is stable across resolve/reject
							 | 
						||
| 
								 | 
							
								          // Remove this instance if we were aborted or if promises have settled
							 | 
						||
| 
								 | 
							
								          if (aborted || deferredData.done) {
							 | 
						||
| 
								 | 
							
								            activeDeferreds.delete(routeId);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      markFetchRedirectsDone();
							 | 
						||
| 
								 | 
							
								      let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
							 | 
						||
| 
								 | 
							
								      return _extends({
							 | 
						||
| 
								 | 
							
								        loaderData,
							 | 
						||
| 
								 | 
							
								        errors
							 | 
						||
| 
								 | 
							
								      }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? {
							 | 
						||
| 
								 | 
							
								        fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								      } : {});
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function getFetcher(key) {
							 | 
						||
| 
								 | 
							
								      return state.fetchers.get(key) || IDLE_FETCHER;
							 | 
						||
| 
								 | 
							
								    } // Trigger a fetcher load/submit for the given fetcher key
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function fetch(key, routeId, href, opts) {
							 | 
						||
| 
								 | 
							
								      if (isServer) {
							 | 
						||
| 
								 | 
							
								        throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (fetchControllers.has(key)) abortFetcher(key);
							 | 
						||
| 
								 | 
							
								      let matches = matchRoutes(dataRoutes, href, init.basename);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!matches) {
							 | 
						||
| 
								 | 
							
								        setFetcherError(key, routeId, getInternalRouterError(404, {
							 | 
						||
| 
								 | 
							
								          pathname: href
							 | 
						||
| 
								 | 
							
								        }));
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        path,
							 | 
						||
| 
								 | 
							
								        submission
							 | 
						||
| 
								 | 
							
								      } = normalizeNavigateOptions(href, opts, true);
							 | 
						||
| 
								 | 
							
								      let match = getTargetMatch(matches, path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (submission && isMutationMethod(submission.formMethod)) {
							 | 
						||
| 
								 | 
							
								        handleFetcherAction(key, routeId, path, match, matches, submission);
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Store off the match so we can call it's shouldRevalidate on subsequent
							 | 
						||
| 
								 | 
							
								      // revalidations
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      fetchLoadMatches.set(key, [path, match, matches]);
							 | 
						||
| 
								 | 
							
								      handleFetcherLoader(key, routeId, path, match, matches, submission);
							 | 
						||
| 
								 | 
							
								    } // Call the action for the matched fetcher.submit(), and then handle redirects,
							 | 
						||
| 
								 | 
							
								    // errors, and revalidation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {
							 | 
						||
| 
								 | 
							
								      interruptActiveLoads();
							 | 
						||
| 
								 | 
							
								      fetchLoadMatches.delete(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!match.route.action) {
							 | 
						||
| 
								 | 
							
								        let error = getInternalRouterError(405, {
							 | 
						||
| 
								 | 
							
								          method: submission.formMethod,
							 | 
						||
| 
								 | 
							
								          pathname: path,
							 | 
						||
| 
								 | 
							
								          routeId: routeId
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        setFetcherError(key, routeId, error);
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Put this fetcher into it's submitting state
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let existingFetcher = state.fetchers.get(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let fetcher = _extends({
							 | 
						||
| 
								 | 
							
								        state: "submitting"
							 | 
						||
| 
								 | 
							
								      }, submission, {
							 | 
						||
| 
								 | 
							
								        data: existingFetcher && existingFetcher.data,
							 | 
						||
| 
								 | 
							
								        " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      state.fetchers.set(key, fetcher);
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								      }); // Call the action for the fetcher
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let abortController = new AbortController();
							 | 
						||
| 
								 | 
							
								      let fetchRequest = createClientSideRequest(path, abortController.signal, submission);
							 | 
						||
| 
								 | 
							
								      fetchControllers.set(key, abortController);
							 | 
						||
| 
								 | 
							
								      let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (fetchRequest.signal.aborted) {
							 | 
						||
| 
								 | 
							
								        // We can delete this so long as we weren't aborted by ou our own fetcher
							 | 
						||
| 
								 | 
							
								        // re-submit which would have put _new_ controller is in fetchControllers
							 | 
						||
| 
								 | 
							
								        if (fetchControllers.get(key) === abortController) {
							 | 
						||
| 
								 | 
							
								          fetchControllers.delete(key);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRedirectResult(actionResult)) {
							 | 
						||
| 
								 | 
							
								        fetchControllers.delete(key);
							 | 
						||
| 
								 | 
							
								        fetchRedirectIds.add(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        let loadingFetcher = _extends({
							 | 
						||
| 
								 | 
							
								          state: "loading"
							 | 
						||
| 
								 | 
							
								        }, submission, {
							 | 
						||
| 
								 | 
							
								          data: undefined,
							 | 
						||
| 
								 | 
							
								          " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        state.fetchers.set(key, loadingFetcher);
							 | 
						||
| 
								 | 
							
								        updateState({
							 | 
						||
| 
								 | 
							
								          fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return startRedirectNavigation(state, actionResult, {
							 | 
						||
| 
								 | 
							
								          isFetchActionRedirect: true
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } // Process any non-redirect errors thrown
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isErrorResult(actionResult)) {
							 | 
						||
| 
								 | 
							
								        setFetcherError(key, routeId, actionResult.error);
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isDeferredResult(actionResult)) {
							 | 
						||
| 
								 | 
							
								        invariant(false, "defer() is not supported in actions");
							 | 
						||
| 
								 | 
							
								      } // Start the data load for current matches, or the next location if we're
							 | 
						||
| 
								 | 
							
								      // in the middle of a navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let nextLocation = state.navigation.location || state.location;
							 | 
						||
| 
								 | 
							
								      let revalidationRequest = createClientSideRequest(nextLocation, abortController.signal);
							 | 
						||
| 
								 | 
							
								      let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
							 | 
						||
| 
								 | 
							
								      invariant(matches, "Didn't find any matches after fetcher action");
							 | 
						||
| 
								 | 
							
								      let loadId = ++incrementingLoadId;
							 | 
						||
| 
								 | 
							
								      fetchReloadIds.set(key, loadId);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let loadFetcher = _extends({
							 | 
						||
| 
								 | 
							
								        state: "loading",
							 | 
						||
| 
								 | 
							
								        data: actionResult.data
							 | 
						||
| 
								 | 
							
								      }, submission, {
							 | 
						||
| 
								 | 
							
								        " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      state.fetchers.set(key, loadFetcher);
							 | 
						||
| 
								 | 
							
								      let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
							 | 
						||
| 
								 | 
							
								        [match.route.id]: actionResult.data
							 | 
						||
| 
								 | 
							
								      }, undefined, // No need to send through errors since we short circuit above
							 | 
						||
| 
								 | 
							
								      fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
							 | 
						||
| 
								 | 
							
								      // current fetcher which we want to keep in it's current loading state which
							 | 
						||
| 
								 | 
							
								      // contains it's action submission info + action data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      revalidatingFetchers.filter(_ref5 => {
							 | 
						||
| 
								 | 
							
								        let [staleKey] = _ref5;
							 | 
						||
| 
								 | 
							
								        return staleKey !== key;
							 | 
						||
| 
								 | 
							
								      }).forEach(_ref6 => {
							 | 
						||
| 
								 | 
							
								        let [staleKey] = _ref6;
							 | 
						||
| 
								 | 
							
								        let existingFetcher = state.fetchers.get(staleKey);
							 | 
						||
| 
								 | 
							
								        let revalidatingFetcher = {
							 | 
						||
| 
								 | 
							
								          state: "loading",
							 | 
						||
| 
								 | 
							
								          data: existingFetcher && existingFetcher.data,
							 | 
						||
| 
								 | 
							
								          formMethod: undefined,
							 | 
						||
| 
								 | 
							
								          formAction: undefined,
							 | 
						||
| 
								 | 
							
								          formEncType: undefined,
							 | 
						||
| 
								 | 
							
								          formData: undefined,
							 | 
						||
| 
								 | 
							
								          " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        state.fetchers.set(staleKey, revalidatingFetcher);
							 | 
						||
| 
								 | 
							
								        fetchControllers.set(staleKey, abortController);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        results,
							 | 
						||
| 
								 | 
							
								        loaderResults,
							 | 
						||
| 
								 | 
							
								        fetcherResults
							 | 
						||
| 
								 | 
							
								      } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (abortController.signal.aborted) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      fetchReloadIds.delete(key);
							 | 
						||
| 
								 | 
							
								      fetchControllers.delete(key);
							 | 
						||
| 
								 | 
							
								      revalidatingFetchers.forEach(_ref7 => {
							 | 
						||
| 
								 | 
							
								        let [staleKey] = _ref7;
							 | 
						||
| 
								 | 
							
								        return fetchControllers.delete(staleKey);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      let redirect = findRedirect(results);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (redirect) {
							 | 
						||
| 
								 | 
							
								        return startRedirectNavigation(state, redirect);
							 | 
						||
| 
								 | 
							
								      } // Process and commit output from loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        loaderData,
							 | 
						||
| 
								 | 
							
								        errors
							 | 
						||
| 
								 | 
							
								      } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
							 | 
						||
| 
								 | 
							
								      let doneFetcher = {
							 | 
						||
| 
								 | 
							
								        state: "idle",
							 | 
						||
| 
								 | 
							
								        data: actionResult.data,
							 | 
						||
| 
								 | 
							
								        formMethod: undefined,
							 | 
						||
| 
								 | 
							
								        formAction: undefined,
							 | 
						||
| 
								 | 
							
								        formEncType: undefined,
							 | 
						||
| 
								 | 
							
								        formData: undefined,
							 | 
						||
| 
								 | 
							
								        " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      state.fetchers.set(key, doneFetcher);
							 | 
						||
| 
								 | 
							
								      let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is
							 | 
						||
| 
								 | 
							
								      // more recent than the navigation, we want the newer data so abort the
							 | 
						||
| 
								 | 
							
								      // navigation and complete it with the fetcher data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
							 | 
						||
| 
								 | 
							
								        invariant(pendingAction, "Expected pending action");
							 | 
						||
| 
								 | 
							
								        pendingNavigationController && pendingNavigationController.abort();
							 | 
						||
| 
								 | 
							
								        completeNavigation(state.navigation.location, {
							 | 
						||
| 
								 | 
							
								          matches,
							 | 
						||
| 
								 | 
							
								          loaderData,
							 | 
						||
| 
								 | 
							
								          errors,
							 | 
						||
| 
								 | 
							
								          fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        // otherwise just update with the fetcher data, preserving any existing
							 | 
						||
| 
								 | 
							
								        // loaderData for loaders that did not need to reload.  We have to
							 | 
						||
| 
								 | 
							
								        // manually merge here since we aren't going through completeNavigation
							 | 
						||
| 
								 | 
							
								        updateState(_extends({
							 | 
						||
| 
								 | 
							
								          errors,
							 | 
						||
| 
								 | 
							
								          loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors)
							 | 
						||
| 
								 | 
							
								        }, didAbortFetchLoads ? {
							 | 
						||
| 
								 | 
							
								          fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								        } : {}));
							 | 
						||
| 
								 | 
							
								        isRevalidationRequired = false;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function handleFetcherLoader(key, routeId, path, match, matches, submission) {
							 | 
						||
| 
								 | 
							
								      let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let loadingFetcher = _extends({
							 | 
						||
| 
								 | 
							
								        state: "loading",
							 | 
						||
| 
								 | 
							
								        formMethod: undefined,
							 | 
						||
| 
								 | 
							
								        formAction: undefined,
							 | 
						||
| 
								 | 
							
								        formEncType: undefined,
							 | 
						||
| 
								 | 
							
								        formData: undefined
							 | 
						||
| 
								 | 
							
								      }, submission, {
							 | 
						||
| 
								 | 
							
								        data: existingFetcher && existingFetcher.data,
							 | 
						||
| 
								 | 
							
								        " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      state.fetchers.set(key, loadingFetcher);
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								      }); // Call the loader for this fetcher route match
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let abortController = new AbortController();
							 | 
						||
| 
								 | 
							
								      let fetchRequest = createClientSideRequest(path, abortController.signal);
							 | 
						||
| 
								 | 
							
								      fetchControllers.set(key, abortController);
							 | 
						||
| 
								 | 
							
								      let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported or fetcher loads, await everything and treat it
							 | 
						||
| 
								 | 
							
								      // as a normal load.  resolveDeferredData will return undefined if this
							 | 
						||
| 
								 | 
							
								      // fetcher gets aborted, so we just leave result untouched and short circuit
							 | 
						||
| 
								 | 
							
								      // below if that happens
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isDeferredResult(result)) {
							 | 
						||
| 
								 | 
							
								        result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result;
							 | 
						||
| 
								 | 
							
								      } // We can delete this so long as we weren't aborted by ou our own fetcher
							 | 
						||
| 
								 | 
							
								      // re-load which would have put _new_ controller is in fetchControllers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (fetchControllers.get(key) === abortController) {
							 | 
						||
| 
								 | 
							
								        fetchControllers.delete(key);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (fetchRequest.signal.aborted) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // If the loader threw a redirect Response, start a new REPLACE navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRedirectResult(result)) {
							 | 
						||
| 
								 | 
							
								        await startRedirectNavigation(state, result);
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      } // Process any non-redirect errors thrown
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isErrorResult(result)) {
							 | 
						||
| 
								 | 
							
								        let boundaryMatch = findNearestBoundary(state.matches, routeId);
							 | 
						||
| 
								 | 
							
								        state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -
							 | 
						||
| 
								 | 
							
								        // do we need to behave any differently with our non-redirect errors?
							 | 
						||
| 
								 | 
							
								        // What if it was a non-redirect Response?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        updateState({
							 | 
						||
| 
								 | 
							
								          fetchers: new Map(state.fetchers),
							 | 
						||
| 
								 | 
							
								          errors: {
							 | 
						||
| 
								 | 
							
								            [boundaryMatch.route.id]: result.error
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); // Put the fetcher back into an idle state
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let doneFetcher = {
							 | 
						||
| 
								 | 
							
								        state: "idle",
							 | 
						||
| 
								 | 
							
								        data: result.data,
							 | 
						||
| 
								 | 
							
								        formMethod: undefined,
							 | 
						||
| 
								 | 
							
								        formAction: undefined,
							 | 
						||
| 
								 | 
							
								        formEncType: undefined,
							 | 
						||
| 
								 | 
							
								        formData: undefined,
							 | 
						||
| 
								 | 
							
								        " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								      state.fetchers.set(key, doneFetcher);
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Utility function to handle redirects returned from an action or loader.
							 | 
						||
| 
								 | 
							
								     * Normally, a redirect "replaces" the navigation that triggered it.  So, for
							 | 
						||
| 
								 | 
							
								     * example:
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     *  - user is on /a
							 | 
						||
| 
								 | 
							
								     *  - user clicks a link to /b
							 | 
						||
| 
								 | 
							
								     *  - loader for /b redirects to /c
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * In a non-JS app the browser would track the in-flight navigation to /b and
							 | 
						||
| 
								 | 
							
								     * then replace it with /c when it encountered the redirect response.  In
							 | 
						||
| 
								 | 
							
								     * the end it would only ever update the URL bar with /c.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * In client-side routing using pushState/replaceState, we aim to emulate
							 | 
						||
| 
								 | 
							
								     * this behavior and we also do not update history until the end of the
							 | 
						||
| 
								 | 
							
								     * navigation (including processed redirects).  This means that we never
							 | 
						||
| 
								 | 
							
								     * actually touch history until we've processed redirects, so we just use
							 | 
						||
| 
								 | 
							
								     * the history action from the original navigation (PUSH or REPLACE).
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function startRedirectNavigation(state, redirect, _temp) {
							 | 
						||
| 
								 | 
							
								      var _window;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        submission,
							 | 
						||
| 
								 | 
							
								        replace,
							 | 
						||
| 
								 | 
							
								        isFetchActionRedirect
							 | 
						||
| 
								 | 
							
								      } = _temp === void 0 ? {} : _temp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (redirect.revalidate) {
							 | 
						||
| 
								 | 
							
								        isRevalidationRequired = true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let redirectLocation = createLocation(state.location, redirect.location, // TODO: This can be removed once we get rid of useTransition in Remix v2
							 | 
						||
| 
								 | 
							
								      _extends({
							 | 
						||
| 
								 | 
							
								        _isRedirect: true
							 | 
						||
| 
								 | 
							
								      }, isFetchActionRedirect ? {
							 | 
						||
| 
								 | 
							
								        _isFetchActionRedirect: true
							 | 
						||
| 
								 | 
							
								      } : {}));
							 | 
						||
| 
								 | 
							
								      invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an external redirect that goes to a new origin
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
							 | 
						||
| 
								 | 
							
								        let newOrigin = createClientSideURL(redirect.location).origin;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (window.location.origin !== newOrigin) {
							 | 
						||
| 
								 | 
							
								          if (replace) {
							 | 
						||
| 
								 | 
							
								            window.location.replace(redirect.location);
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            window.location.assign(redirect.location);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } // There's no need to abort on redirects, since we don't detect the
							 | 
						||
| 
								 | 
							
								      // redirect until the action/loaders have settled
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      pendingNavigationController = null;
							 | 
						||
| 
								 | 
							
								      let redirectHistoryAction = replace === true ? exports.Action.Replace : exports.Action.Push; // Use the incoming submission if provided, fallback on the active one in
							 | 
						||
| 
								 | 
							
								      // state.navigation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        formMethod,
							 | 
						||
| 
								 | 
							
								        formAction,
							 | 
						||
| 
								 | 
							
								        formEncType,
							 | 
						||
| 
								 | 
							
								        formData
							 | 
						||
| 
								 | 
							
								      } = state.navigation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!submission && formMethod && formAction && formData && formEncType) {
							 | 
						||
| 
								 | 
							
								        submission = {
							 | 
						||
| 
								 | 
							
								          formMethod,
							 | 
						||
| 
								 | 
							
								          formAction,
							 | 
						||
| 
								 | 
							
								          formEncType,
							 | 
						||
| 
								 | 
							
								          formData
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } // If this was a 307/308 submission we want to preserve the HTTP method and
							 | 
						||
| 
								 | 
							
								      // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the
							 | 
						||
| 
								 | 
							
								      // redirected location
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (redirectPreserveMethodStatusCodes.has(redirect.status) && submission && isMutationMethod(submission.formMethod)) {
							 | 
						||
| 
								 | 
							
								        await startNavigation(redirectHistoryAction, redirectLocation, {
							 | 
						||
| 
								 | 
							
								          submission: _extends({}, submission, {
							 | 
						||
| 
								 | 
							
								            formAction: redirect.location
							 | 
						||
| 
								 | 
							
								          })
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        // Otherwise, we kick off a new loading navigation, preserving the
							 | 
						||
| 
								 | 
							
								        // submission info for the duration of this navigation
							 | 
						||
| 
								 | 
							
								        await startNavigation(redirectHistoryAction, redirectLocation, {
							 | 
						||
| 
								 | 
							
								          overrideNavigation: {
							 | 
						||
| 
								 | 
							
								            state: "loading",
							 | 
						||
| 
								 | 
							
								            location: redirectLocation,
							 | 
						||
| 
								 | 
							
								            formMethod: submission ? submission.formMethod : undefined,
							 | 
						||
| 
								 | 
							
								            formAction: submission ? submission.formAction : undefined,
							 | 
						||
| 
								 | 
							
								            formEncType: submission ? submission.formEncType : undefined,
							 | 
						||
| 
								 | 
							
								            formData: submission ? submission.formData : undefined
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
							 | 
						||
| 
								 | 
							
								      // Call all navigation loaders and revalidating fetcher loaders in parallel,
							 | 
						||
| 
								 | 
							
								      // then slice off the results into separate arrays so we can handle them
							 | 
						||
| 
								 | 
							
								      // accordingly
							 | 
						||
| 
								 | 
							
								      let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {
							 | 
						||
| 
								 | 
							
								        let [, href, match, fetchMatches] = _ref8;
							 | 
						||
| 
								 | 
							
								        return callLoaderOrAction("loader", createClientSideRequest(href, request.signal), match, fetchMatches, router.basename);
							 | 
						||
| 
								 | 
							
								      })]);
							 | 
						||
| 
								 | 
							
								      let loaderResults = results.slice(0, matchesToLoad.length);
							 | 
						||
| 
								 | 
							
								      let fetcherResults = results.slice(matchesToLoad.length);
							 | 
						||
| 
								 | 
							
								      await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(_ref9 => {
							 | 
						||
| 
								 | 
							
								        let [,, match] = _ref9;
							 | 
						||
| 
								 | 
							
								        return match;
							 | 
						||
| 
								 | 
							
								      }), fetcherResults, request.signal, true)]);
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        results,
							 | 
						||
| 
								 | 
							
								        loaderResults,
							 | 
						||
| 
								 | 
							
								        fetcherResults
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function interruptActiveLoads() {
							 | 
						||
| 
								 | 
							
								      // Every interruption triggers a revalidation
							 | 
						||
| 
								 | 
							
								      isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for
							 | 
						||
| 
								 | 
							
								      // revalidation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      fetchLoadMatches.forEach((_, key) => {
							 | 
						||
| 
								 | 
							
								        if (fetchControllers.has(key)) {
							 | 
						||
| 
								 | 
							
								          cancelledFetcherLoads.push(key);
							 | 
						||
| 
								 | 
							
								          abortFetcher(key);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function setFetcherError(key, routeId, error) {
							 | 
						||
| 
								 | 
							
								      let boundaryMatch = findNearestBoundary(state.matches, routeId);
							 | 
						||
| 
								 | 
							
								      deleteFetcher(key);
							 | 
						||
| 
								 | 
							
								      updateState({
							 | 
						||
| 
								 | 
							
								        errors: {
							 | 
						||
| 
								 | 
							
								          [boundaryMatch.route.id]: error
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        fetchers: new Map(state.fetchers)
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function deleteFetcher(key) {
							 | 
						||
| 
								 | 
							
								      if (fetchControllers.has(key)) abortFetcher(key);
							 | 
						||
| 
								 | 
							
								      fetchLoadMatches.delete(key);
							 | 
						||
| 
								 | 
							
								      fetchReloadIds.delete(key);
							 | 
						||
| 
								 | 
							
								      fetchRedirectIds.delete(key);
							 | 
						||
| 
								 | 
							
								      state.fetchers.delete(key);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function abortFetcher(key) {
							 | 
						||
| 
								 | 
							
								      let controller = fetchControllers.get(key);
							 | 
						||
| 
								 | 
							
								      invariant(controller, "Expected fetch controller: " + key);
							 | 
						||
| 
								 | 
							
								      controller.abort();
							 | 
						||
| 
								 | 
							
								      fetchControllers.delete(key);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function markFetchersDone(keys) {
							 | 
						||
| 
								 | 
							
								      for (let key of keys) {
							 | 
						||
| 
								 | 
							
								        let fetcher = getFetcher(key);
							 | 
						||
| 
								 | 
							
								        let doneFetcher = {
							 | 
						||
| 
								 | 
							
								          state: "idle",
							 | 
						||
| 
								 | 
							
								          data: fetcher.data,
							 | 
						||
| 
								 | 
							
								          formMethod: undefined,
							 | 
						||
| 
								 | 
							
								          formAction: undefined,
							 | 
						||
| 
								 | 
							
								          formEncType: undefined,
							 | 
						||
| 
								 | 
							
								          formData: undefined,
							 | 
						||
| 
								 | 
							
								          " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        state.fetchers.set(key, doneFetcher);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function markFetchRedirectsDone() {
							 | 
						||
| 
								 | 
							
								      let doneKeys = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (let key of fetchRedirectIds) {
							 | 
						||
| 
								 | 
							
								        let fetcher = state.fetchers.get(key);
							 | 
						||
| 
								 | 
							
								        invariant(fetcher, "Expected fetcher: " + key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (fetcher.state === "loading") {
							 | 
						||
| 
								 | 
							
								          fetchRedirectIds.delete(key);
							 | 
						||
| 
								 | 
							
								          doneKeys.push(key);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      markFetchersDone(doneKeys);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function abortStaleFetchLoads(landedId) {
							 | 
						||
| 
								 | 
							
								      let yeetedKeys = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (let [key, id] of fetchReloadIds) {
							 | 
						||
| 
								 | 
							
								        if (id < landedId) {
							 | 
						||
| 
								 | 
							
								          let fetcher = state.fetchers.get(key);
							 | 
						||
| 
								 | 
							
								          invariant(fetcher, "Expected fetcher: " + key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (fetcher.state === "loading") {
							 | 
						||
| 
								 | 
							
								            abortFetcher(key);
							 | 
						||
| 
								 | 
							
								            fetchReloadIds.delete(key);
							 | 
						||
| 
								 | 
							
								            yeetedKeys.push(key);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      markFetchersDone(yeetedKeys);
							 | 
						||
| 
								 | 
							
								      return yeetedKeys.length > 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function cancelActiveDeferreds(predicate) {
							 | 
						||
| 
								 | 
							
								      let cancelledRouteIds = [];
							 | 
						||
| 
								 | 
							
								      activeDeferreds.forEach((dfd, routeId) => {
							 | 
						||
| 
								 | 
							
								        if (!predicate || predicate(routeId)) {
							 | 
						||
| 
								 | 
							
								          // Cancel the deferred - but do not remove from activeDeferreds here -
							 | 
						||
| 
								 | 
							
								          // we rely on the subscribers to do that so our tests can assert proper
							 | 
						||
| 
								 | 
							
								          // cleanup via _internalActiveDeferreds
							 | 
						||
| 
								 | 
							
								          dfd.cancel();
							 | 
						||
| 
								 | 
							
								          cancelledRouteIds.push(routeId);
							 | 
						||
| 
								 | 
							
								          activeDeferreds.delete(routeId);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      return cancelledRouteIds;
							 | 
						||
| 
								 | 
							
								    } // Opt in to capturing and reporting scroll positions during navigations,
							 | 
						||
| 
								 | 
							
								    // used by the <ScrollRestoration> component
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function enableScrollRestoration(positions, getPosition, getKey) {
							 | 
						||
| 
								 | 
							
								      savedScrollPositions = positions;
							 | 
						||
| 
								 | 
							
								      getScrollPosition = getPosition;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on
							 | 
						||
| 
								 | 
							
								      // the initial updateState() because we've not yet rendered <ScrollRestoration/>
							 | 
						||
| 
								 | 
							
								      // and therefore have no savedScrollPositions available
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {
							 | 
						||
| 
								 | 
							
								        initialScrollRestored = true;
							 | 
						||
| 
								 | 
							
								        let y = getSavedScrollPosition(state.location, state.matches);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (y != null) {
							 | 
						||
| 
								 | 
							
								          updateState({
							 | 
						||
| 
								 | 
							
								            restoreScrollPosition: y
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return () => {
							 | 
						||
| 
								 | 
							
								        savedScrollPositions = null;
							 | 
						||
| 
								 | 
							
								        getScrollPosition = null;
							 | 
						||
| 
								 | 
							
								        getScrollRestorationKey = null;
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function saveScrollPosition(location, matches) {
							 | 
						||
| 
								 | 
							
								      if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {
							 | 
						||
| 
								 | 
							
								        let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));
							 | 
						||
| 
								 | 
							
								        let key = getScrollRestorationKey(location, userMatches) || location.key;
							 | 
						||
| 
								 | 
							
								        savedScrollPositions[key] = getScrollPosition();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function getSavedScrollPosition(location, matches) {
							 | 
						||
| 
								 | 
							
								      if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {
							 | 
						||
| 
								 | 
							
								        let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));
							 | 
						||
| 
								 | 
							
								        let key = getScrollRestorationKey(location, userMatches) || location.key;
							 | 
						||
| 
								 | 
							
								        let y = savedScrollPositions[key];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (typeof y === "number") {
							 | 
						||
| 
								 | 
							
								          return y;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    router = {
							 | 
						||
| 
								 | 
							
								      get basename() {
							 | 
						||
| 
								 | 
							
								        return init.basename;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      get state() {
							 | 
						||
| 
								 | 
							
								        return state;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      get routes() {
							 | 
						||
| 
								 | 
							
								        return dataRoutes;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      initialize,
							 | 
						||
| 
								 | 
							
								      subscribe,
							 | 
						||
| 
								 | 
							
								      enableScrollRestoration,
							 | 
						||
| 
								 | 
							
								      navigate,
							 | 
						||
| 
								 | 
							
								      fetch,
							 | 
						||
| 
								 | 
							
								      revalidate,
							 | 
						||
| 
								 | 
							
								      // Passthrough to history-aware createHref used by useHref so we get proper
							 | 
						||
| 
								 | 
							
								      // hash-aware URLs in DOM paths
							 | 
						||
| 
								 | 
							
								      createHref: to => init.history.createHref(to),
							 | 
						||
| 
								 | 
							
								      encodeLocation: to => init.history.encodeLocation(to),
							 | 
						||
| 
								 | 
							
								      getFetcher,
							 | 
						||
| 
								 | 
							
								      deleteFetcher,
							 | 
						||
| 
								 | 
							
								      dispose,
							 | 
						||
| 
								 | 
							
								      _internalFetchControllers: fetchControllers,
							 | 
						||
| 
								 | 
							
								      _internalActiveDeferreds: activeDeferreds
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    return router;
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region createStaticHandler
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createStaticHandler(routes, opts) {
							 | 
						||
| 
								 | 
							
								    invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
							 | 
						||
| 
								 | 
							
								    let dataRoutes = convertRoutesToDataRoutes(routes);
							 | 
						||
| 
								 | 
							
								    let basename = (opts ? opts.basename : null) || "/";
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * The query() method is intended for document requests, in which we want to
							 | 
						||
| 
								 | 
							
								     * call an optional action and potentially multiple loaders for all nested
							 | 
						||
| 
								 | 
							
								     * routes.  It returns a StaticHandlerContext object, which is very similar
							 | 
						||
| 
								 | 
							
								     * to the router state (location, loaderData, actionData, errors, etc.) and
							 | 
						||
| 
								 | 
							
								     * also adds SSR-specific information such as the statusCode and headers
							 | 
						||
| 
								 | 
							
								     * from action/loaders Responses.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * It _should_ never throw and should report all errors through the
							 | 
						||
| 
								 | 
							
								     * returned context.errors object, properly associating errors to their error
							 | 
						||
| 
								 | 
							
								     * boundary.  Additionally, it tracks _deepestRenderedBoundaryId which can be
							 | 
						||
| 
								 | 
							
								     * used to emulate React error boundaries during SSr by performing a second
							 | 
						||
| 
								 | 
							
								     * pass only down to the boundaryId.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * The one exception where we do not return a StaticHandlerContext is when a
							 | 
						||
| 
								 | 
							
								     * redirect response is returned or thrown from any action/loader.  We
							 | 
						||
| 
								 | 
							
								     * propagate that out and return the raw Response so the HTTP server can
							 | 
						||
| 
								 | 
							
								     * return it directly.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function query(request, _temp2) {
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        requestContext
							 | 
						||
| 
								 | 
							
								      } = _temp2 === void 0 ? {} : _temp2;
							 | 
						||
| 
								 | 
							
								      let url = new URL(request.url);
							 | 
						||
| 
								 | 
							
								      let method = request.method.toLowerCase();
							 | 
						||
| 
								 | 
							
								      let location = createLocation("", createPath(url), null, "default");
							 | 
						||
| 
								 | 
							
								      let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!isValidMethod(method) && method !== "head") {
							 | 
						||
| 
								 | 
							
								        let error = getInternalRouterError(405, {
							 | 
						||
| 
								 | 
							
								          method
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        let {
							 | 
						||
| 
								 | 
							
								          matches: methodNotAllowedMatches,
							 | 
						||
| 
								 | 
							
								          route
							 | 
						||
| 
								 | 
							
								        } = getShortCircuitMatches(dataRoutes);
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          basename,
							 | 
						||
| 
								 | 
							
								          location,
							 | 
						||
| 
								 | 
							
								          matches: methodNotAllowedMatches,
							 | 
						||
| 
								 | 
							
								          loaderData: {},
							 | 
						||
| 
								 | 
							
								          actionData: null,
							 | 
						||
| 
								 | 
							
								          errors: {
							 | 
						||
| 
								 | 
							
								            [route.id]: error
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          statusCode: error.status,
							 | 
						||
| 
								 | 
							
								          loaderHeaders: {},
							 | 
						||
| 
								 | 
							
								          actionHeaders: {}
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } else if (!matches) {
							 | 
						||
| 
								 | 
							
								        let error = getInternalRouterError(404, {
							 | 
						||
| 
								 | 
							
								          pathname: location.pathname
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        let {
							 | 
						||
| 
								 | 
							
								          matches: notFoundMatches,
							 | 
						||
| 
								 | 
							
								          route
							 | 
						||
| 
								 | 
							
								        } = getShortCircuitMatches(dataRoutes);
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          basename,
							 | 
						||
| 
								 | 
							
								          location,
							 | 
						||
| 
								 | 
							
								          matches: notFoundMatches,
							 | 
						||
| 
								 | 
							
								          loaderData: {},
							 | 
						||
| 
								 | 
							
								          actionData: null,
							 | 
						||
| 
								 | 
							
								          errors: {
							 | 
						||
| 
								 | 
							
								            [route.id]: error
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          statusCode: error.status,
							 | 
						||
| 
								 | 
							
								          loaderHeaders: {},
							 | 
						||
| 
								 | 
							
								          actionHeaders: {}
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let result = await queryImpl(request, location, matches, requestContext);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isResponse(result)) {
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								      } // When returning StaticHandlerContext, we patch back in the location here
							 | 
						||
| 
								 | 
							
								      // since we need it for React Context.  But this helps keep our submit and
							 | 
						||
| 
								 | 
							
								      // loadRouteData operating on a Request instead of a Location
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return _extends({
							 | 
						||
| 
								 | 
							
								        location,
							 | 
						||
| 
								 | 
							
								        basename
							 | 
						||
| 
								 | 
							
								      }, result);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * The queryRoute() method is intended for targeted route requests, either
							 | 
						||
| 
								 | 
							
								     * for fetch ?_data requests or resource route requests.  In this case, we
							 | 
						||
| 
								 | 
							
								     * are only ever calling a single action or loader, and we are returning the
							 | 
						||
| 
								 | 
							
								     * returned value directly.  In most cases, this will be a Response returned
							 | 
						||
| 
								 | 
							
								     * from the action/loader, but it may be a primitive or other value as well -
							 | 
						||
| 
								 | 
							
								     * and in such cases the calling context should handle that accordingly.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * We do respect the throw/return differentiation, so if an action/loader
							 | 
						||
| 
								 | 
							
								     * throws, then this method will throw the value.  This is important so we
							 | 
						||
| 
								 | 
							
								     * can do proper boundary identification in Remix where a thrown Response
							 | 
						||
| 
								 | 
							
								     * must go to the Catch Boundary but a returned Response is happy-path.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * One thing to note is that any Router-initiated Errors that make sense
							 | 
						||
| 
								 | 
							
								     * to associate with a status code will be thrown as an ErrorResponse
							 | 
						||
| 
								 | 
							
								     * instance which include the raw Error, such that the calling context can
							 | 
						||
| 
								 | 
							
								     * serialize the error as they see fit while including the proper response
							 | 
						||
| 
								 | 
							
								     * code.  Examples here are 404 and 405 errors that occur prior to reaching
							 | 
						||
| 
								 | 
							
								     * any user-defined loaders.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function queryRoute(request, _temp3) {
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        routeId,
							 | 
						||
| 
								 | 
							
								        requestContext
							 | 
						||
| 
								 | 
							
								      } = _temp3 === void 0 ? {} : _temp3;
							 | 
						||
| 
								 | 
							
								      let url = new URL(request.url);
							 | 
						||
| 
								 | 
							
								      let method = request.method.toLowerCase();
							 | 
						||
| 
								 | 
							
								      let location = createLocation("", createPath(url), null, "default");
							 | 
						||
| 
								 | 
							
								      let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!isValidMethod(method) && method !== "head") {
							 | 
						||
| 
								 | 
							
								        throw getInternalRouterError(405, {
							 | 
						||
| 
								 | 
							
								          method
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } else if (!matches) {
							 | 
						||
| 
								 | 
							
								        throw getInternalRouterError(404, {
							 | 
						||
| 
								 | 
							
								          pathname: location.pathname
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (routeId && !match) {
							 | 
						||
| 
								 | 
							
								        throw getInternalRouterError(403, {
							 | 
						||
| 
								 | 
							
								          pathname: location.pathname,
							 | 
						||
| 
								 | 
							
								          routeId
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } else if (!match) {
							 | 
						||
| 
								 | 
							
								        // This should never hit I don't think?
							 | 
						||
| 
								 | 
							
								        throw getInternalRouterError(404, {
							 | 
						||
| 
								 | 
							
								          pathname: location.pathname
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let result = await queryImpl(request, location, matches, requestContext, match);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isResponse(result)) {
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let error = result.errors ? Object.values(result.errors)[0] : undefined;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (error !== undefined) {
							 | 
						||
| 
								 | 
							
								        // If we got back result.errors, that means the loader/action threw
							 | 
						||
| 
								 | 
							
								        // _something_ that wasn't a Response, but it's not guaranteed/required
							 | 
						||
| 
								 | 
							
								        // to be an `instanceof Error` either, so we have to use throw here to
							 | 
						||
| 
								 | 
							
								        // preserve the "error" state outside of queryImpl.
							 | 
						||
| 
								 | 
							
								        throw error;
							 | 
						||
| 
								 | 
							
								      } // Pick off the right state value to return
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let routeData = [result.actionData, result.loaderData].find(v => v);
							 | 
						||
| 
								 | 
							
								      return Object.values(routeData || {})[0];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function queryImpl(request, location, matches, requestContext, routeMatch) {
							 | 
						||
| 
								 | 
							
								      invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        if (isMutationMethod(request.method.toLowerCase())) {
							 | 
						||
| 
								 | 
							
								          let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null);
							 | 
						||
| 
								 | 
							
								          return result;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        let result = await loadRouteData(request, matches, requestContext, routeMatch);
							 | 
						||
| 
								 | 
							
								        return isResponse(result) ? result : _extends({}, result, {
							 | 
						||
| 
								 | 
							
								          actionData: null,
							 | 
						||
| 
								 | 
							
								          actionHeaders: {}
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } catch (e) {
							 | 
						||
| 
								 | 
							
								        // If the user threw/returned a Response in callLoaderOrAction, we throw
							 | 
						||
| 
								 | 
							
								        // it to bail out and then return or throw here based on whether the user
							 | 
						||
| 
								 | 
							
								        // returned or threw
							 | 
						||
| 
								 | 
							
								        if (isQueryRouteResponse(e)) {
							 | 
						||
| 
								 | 
							
								          if (e.type === ResultType.error && !isRedirectResponse(e.response)) {
							 | 
						||
| 
								 | 
							
								            throw e.response;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return e.response;
							 | 
						||
| 
								 | 
							
								        } // Redirects are always returned since they don't propagate to catch
							 | 
						||
| 
								 | 
							
								        // boundaries
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isRedirectResponse(e)) {
							 | 
						||
| 
								 | 
							
								          return e;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        throw e;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function submit(request, matches, actionMatch, requestContext, isRouteRequest) {
							 | 
						||
| 
								 | 
							
								      let result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!actionMatch.route.action) {
							 | 
						||
| 
								 | 
							
								        let error = getInternalRouterError(405, {
							 | 
						||
| 
								 | 
							
								          method: request.method,
							 | 
						||
| 
								 | 
							
								          pathname: new URL(request.url).pathname,
							 | 
						||
| 
								 | 
							
								          routeId: actionMatch.route.id
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isRouteRequest) {
							 | 
						||
| 
								 | 
							
								          throw error;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        result = {
							 | 
						||
| 
								 | 
							
								          type: ResultType.error,
							 | 
						||
| 
								 | 
							
								          error
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        result = await callLoaderOrAction("action", request, actionMatch, matches, basename, true, isRouteRequest, requestContext);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (request.signal.aborted) {
							 | 
						||
| 
								 | 
							
								          let method = isRouteRequest ? "queryRoute" : "query";
							 | 
						||
| 
								 | 
							
								          throw new Error(method + "() call aborted");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRedirectResult(result)) {
							 | 
						||
| 
								 | 
							
								        // Uhhhh - this should never happen, we should always throw these from
							 | 
						||
| 
								 | 
							
								        // callLoaderOrAction, but the type narrowing here keeps TS happy and we
							 | 
						||
| 
								 | 
							
								        // can get back on the "throw all redirect responses" train here should
							 | 
						||
| 
								 | 
							
								        // this ever happen :/
							 | 
						||
| 
								 | 
							
								        throw new Response(null, {
							 | 
						||
| 
								 | 
							
								          status: result.status,
							 | 
						||
| 
								 | 
							
								          headers: {
							 | 
						||
| 
								 | 
							
								            Location: result.location
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isDeferredResult(result)) {
							 | 
						||
| 
								 | 
							
								        throw new Error("defer() is not supported in actions");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRouteRequest) {
							 | 
						||
| 
								 | 
							
								        // Note: This should only be non-Response values if we get here, since
							 | 
						||
| 
								 | 
							
								        // isRouteRequest should throw any Response received in callLoaderOrAction
							 | 
						||
| 
								 | 
							
								        if (isErrorResult(result)) {
							 | 
						||
| 
								 | 
							
								          throw result.error;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          matches: [actionMatch],
							 | 
						||
| 
								 | 
							
								          loaderData: {},
							 | 
						||
| 
								 | 
							
								          actionData: {
							 | 
						||
| 
								 | 
							
								            [actionMatch.route.id]: result.data
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          errors: null,
							 | 
						||
| 
								 | 
							
								          // Note: statusCode + headers are unused here since queryRoute will
							 | 
						||
| 
								 | 
							
								          // return the raw Response or value
							 | 
						||
| 
								 | 
							
								          statusCode: 200,
							 | 
						||
| 
								 | 
							
								          loaderHeaders: {},
							 | 
						||
| 
								 | 
							
								          actionHeaders: {}
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isErrorResult(result)) {
							 | 
						||
| 
								 | 
							
								        // Store off the pending error - we use it to determine which loaders
							 | 
						||
| 
								 | 
							
								        // to call and will commit it when we complete the navigation
							 | 
						||
| 
								 | 
							
								        let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
							 | 
						||
| 
								 | 
							
								        let context = await loadRouteData(request, matches, requestContext, undefined, {
							 | 
						||
| 
								 | 
							
								          [boundaryMatch.route.id]: result.error
							 | 
						||
| 
								 | 
							
								        }); // action status codes take precedence over loader status codes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return _extends({}, context, {
							 | 
						||
| 
								 | 
							
								          statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500,
							 | 
						||
| 
								 | 
							
								          actionData: null,
							 | 
						||
| 
								 | 
							
								          actionHeaders: _extends({}, result.headers ? {
							 | 
						||
| 
								 | 
							
								            [actionMatch.route.id]: result.headers
							 | 
						||
| 
								 | 
							
								          } : {})
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      } // Create a GET request for the loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let loaderRequest = new Request(request.url, {
							 | 
						||
| 
								 | 
							
								        headers: request.headers,
							 | 
						||
| 
								 | 
							
								        redirect: request.redirect,
							 | 
						||
| 
								 | 
							
								        signal: request.signal
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      let context = await loadRouteData(loaderRequest, matches, requestContext);
							 | 
						||
| 
								 | 
							
								      return _extends({}, context, result.statusCode ? {
							 | 
						||
| 
								 | 
							
								        statusCode: result.statusCode
							 | 
						||
| 
								 | 
							
								      } : {}, {
							 | 
						||
| 
								 | 
							
								        actionData: {
							 | 
						||
| 
								 | 
							
								          [actionMatch.route.id]: result.data
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        actionHeaders: _extends({}, result.headers ? {
							 | 
						||
| 
								 | 
							
								          [actionMatch.route.id]: result.headers
							 | 
						||
| 
								 | 
							
								        } : {})
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) {
							 | 
						||
| 
								 | 
							
								      let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader)) {
							 | 
						||
| 
								 | 
							
								        throw getInternalRouterError(400, {
							 | 
						||
| 
								 | 
							
								          method: request.method,
							 | 
						||
| 
								 | 
							
								          pathname: new URL(request.url).pathname,
							 | 
						||
| 
								 | 
							
								          routeId: routeMatch == null ? void 0 : routeMatch.route.id
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]);
							 | 
						||
| 
								 | 
							
								      let matchesToLoad = requestMatches.filter(m => m.route.loader); // Short circuit if we have no loaders to run (query())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (matchesToLoad.length === 0) {
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          matches,
							 | 
						||
| 
								 | 
							
								          // Add a null for all matched routes for proper revalidation on the client
							 | 
						||
| 
								 | 
							
								          loaderData: matches.reduce((acc, m) => Object.assign(acc, {
							 | 
						||
| 
								 | 
							
								            [m.route.id]: null
							 | 
						||
| 
								 | 
							
								          }), {}),
							 | 
						||
| 
								 | 
							
								          errors: pendingActionError || null,
							 | 
						||
| 
								 | 
							
								          statusCode: 200,
							 | 
						||
| 
								 | 
							
								          loaderHeaders: {}
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, basename, true, isRouteRequest, requestContext))]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (request.signal.aborted) {
							 | 
						||
| 
								 | 
							
								        let method = isRouteRequest ? "queryRoute" : "query";
							 | 
						||
| 
								 | 
							
								        throw new Error(method + "() call aborted");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let executedLoaders = new Set();
							 | 
						||
| 
								 | 
							
								      results.forEach((result, i) => {
							 | 
						||
| 
								 | 
							
								        executedLoaders.add(matchesToLoad[i].route.id); // Can't do anything with these without the Remix side of things, so just
							 | 
						||
| 
								 | 
							
								        // cancel them for now
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isDeferredResult(result)) {
							 | 
						||
| 
								 | 
							
								          result.deferredData.cancel();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }); // Process and commit output from loaders
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError); // Add a null for any non-loader matches for proper revalidation on the client
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      matches.forEach(match => {
							 | 
						||
| 
								 | 
							
								        if (!executedLoaders.has(match.route.id)) {
							 | 
						||
| 
								 | 
							
								          context.loaderData[match.route.id] = null;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      return _extends({}, context, {
							 | 
						||
| 
								 | 
							
								        matches
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      dataRoutes,
							 | 
						||
| 
								 | 
							
								      query,
							 | 
						||
| 
								 | 
							
								      queryRoute
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								  //#region Helpers
							 | 
						||
| 
								 | 
							
								  ////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Given an existing StaticHandlerContext and an error thrown at render time,
							 | 
						||
| 
								 | 
							
								   * provide an updated StaticHandlerContext suitable for a second SSR render
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getStaticContextFromError(routes, context, error) {
							 | 
						||
| 
								 | 
							
								    let newContext = _extends({}, context, {
							 | 
						||
| 
								 | 
							
								      statusCode: 500,
							 | 
						||
| 
								 | 
							
								      errors: {
							 | 
						||
| 
								 | 
							
								        [context._deepestRenderedBoundaryId || routes[0].id]: error
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return newContext;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isSubmissionNavigation(opts) {
							 | 
						||
| 
								 | 
							
								    return opts != null && "formData" in opts;
							 | 
						||
| 
								 | 
							
								  } // Normalize navigation options by converting formMethod=GET formData objects to
							 | 
						||
| 
								 | 
							
								  // URLSearchParams so they behave identically to links with query params
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function normalizeNavigateOptions(to, opts, isFetcher) {
							 | 
						||
| 
								 | 
							
								    if (isFetcher === void 0) {
							 | 
						||
| 
								 | 
							
								      isFetcher = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let path = typeof to === "string" ? to : createPath(to); // Return location verbatim on non-submission navigations
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!opts || !isSubmissionNavigation(opts)) {
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        path
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (opts.formMethod && !isValidMethod(opts.formMethod)) {
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        path,
							 | 
						||
| 
								 | 
							
								        error: getInternalRouterError(405, {
							 | 
						||
| 
								 | 
							
								          method: opts.formMethod
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    } // Create a Submission on non-GET navigations
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let submission;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (opts.formData) {
							 | 
						||
| 
								 | 
							
								      submission = {
							 | 
						||
| 
								 | 
							
								        formMethod: opts.formMethod || "get",
							 | 
						||
| 
								 | 
							
								        formAction: stripHashFromPath(path),
							 | 
						||
| 
								 | 
							
								        formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
							 | 
						||
| 
								 | 
							
								        formData: opts.formData
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isMutationMethod(submission.formMethod)) {
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          path,
							 | 
						||
| 
								 | 
							
								          submission
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } // Flatten submission onto URLSearchParams for GET submissions
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let parsedPath = parsePath(path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to
							 | 
						||
| 
								 | 
							
								      // navigation GET submissions which run all loaders), we need to preserve
							 | 
						||
| 
								 | 
							
								      // any incoming ?index params
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
							 | 
						||
| 
								 | 
							
								        searchParams.append("index", "");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      parsedPath.search = "?" + searchParams;
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        path,
							 | 
						||
| 
								 | 
							
								        error: getInternalRouterError(400)
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      path: createPath(parsedPath),
							 | 
						||
| 
								 | 
							
								      submission
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  } // Filter out all routes below any caught error as they aren't going to
							 | 
						||
| 
								 | 
							
								  // render so we don't need to load them
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getLoaderMatchesUntilBoundary(matches, boundaryId) {
							 | 
						||
| 
								 | 
							
								    let boundaryMatches = matches;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (boundaryId) {
							 | 
						||
| 
								 | 
							
								      let index = matches.findIndex(m => m.route.id === boundaryId);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (index >= 0) {
							 | 
						||
| 
								 | 
							
								        boundaryMatches = matches.slice(0, index);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return boundaryMatches;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
							 | 
						||
| 
								 | 
							
								    let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; // Pick navigation matches that are net-new or qualify for revalidation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
							 | 
						||
| 
								 | 
							
								    let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
							 | 
						||
| 
								 | 
							
								    let navigationMatches = boundaryMatches.filter((match, index) => match.route.loader != null && (isNewLoader(state.loaderData, state.matches[index], match) || // If this route had a pending deferred cancelled it must be revalidated
							 | 
						||
| 
								 | 
							
								    cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let revalidatingFetchers = [];
							 | 
						||
| 
								 | 
							
								    fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
							 | 
						||
| 
								 | 
							
								      let [href, match, fetchMatches] = _ref10;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // This fetcher was cancelled from a prior action submission - force reload
							 | 
						||
| 
								 | 
							
								      if (cancelledFetcherLoads.includes(key)) {
							 | 
						||
| 
								 | 
							
								        revalidatingFetchers.push([key, href, match, fetchMatches]);
							 | 
						||
| 
								 | 
							
								      } else if (isRevalidationRequired) {
							 | 
						||
| 
								 | 
							
								        let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (shouldRevalidate) {
							 | 
						||
| 
								 | 
							
								          revalidatingFetchers.push([key, href, match, fetchMatches]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    return [navigationMatches, revalidatingFetchers];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isNewLoader(currentLoaderData, currentMatch, match) {
							 | 
						||
| 
								 | 
							
								    let isNew = // [a] -> [a, b]
							 | 
						||
| 
								 | 
							
								    !currentMatch || // [a, b] -> [a, c]
							 | 
						||
| 
								 | 
							
								    match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially
							 | 
						||
| 
								 | 
							
								    // from a prior error or from a cancelled pending deferred
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return isNew || isMissingData;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isNewRouteInstance(currentMatch, match) {
							 | 
						||
| 
								 | 
							
								    let currentPath = currentMatch.route.path;
							 | 
						||
| 
								 | 
							
								    return (// param change for this match, /users/123 -> /users/456
							 | 
						||
| 
								 | 
							
								      currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
							 | 
						||
| 
								 | 
							
								      // e.g. /files/images/avatar.jpg -> files/finances.xls
							 | 
						||
| 
								 | 
							
								      currentPath && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function shouldRevalidateLoader(currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
							 | 
						||
| 
								 | 
							
								    let currentUrl = createClientSideURL(currentLocation);
							 | 
						||
| 
								 | 
							
								    let currentParams = currentMatch.params;
							 | 
						||
| 
								 | 
							
								    let nextUrl = createClientSideURL(location);
							 | 
						||
| 
								 | 
							
								    let nextParams = match.params; // This is the default implementation as to when we revalidate.  If the route
							 | 
						||
| 
								 | 
							
								    // provides it's own implementation, then we give them full control but
							 | 
						||
| 
								 | 
							
								    // provide this value so they can leverage it if needed after they check
							 | 
						||
| 
								 | 
							
								    // their own specific use cases
							 | 
						||
| 
								 | 
							
								    // Note that fetchers always provide the same current/next locations so the
							 | 
						||
| 
								 | 
							
								    // URL-based checks here don't apply to fetcher shouldRevalidate calls
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let defaultShouldRevalidate = isNewRouteInstance(currentMatch, match) || // Clicked the same link, resubmitted a GET form
							 | 
						||
| 
								 | 
							
								    currentUrl.toString() === nextUrl.toString() || // Search params affect all loaders
							 | 
						||
| 
								 | 
							
								    currentUrl.search !== nextUrl.search || // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate
							 | 
						||
| 
								 | 
							
								    isRevalidationRequired;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (match.route.shouldRevalidate) {
							 | 
						||
| 
								 | 
							
								      let routeChoice = match.route.shouldRevalidate(_extends({
							 | 
						||
| 
								 | 
							
								        currentUrl,
							 | 
						||
| 
								 | 
							
								        currentParams,
							 | 
						||
| 
								 | 
							
								        nextUrl,
							 | 
						||
| 
								 | 
							
								        nextParams
							 | 
						||
| 
								 | 
							
								      }, submission, {
							 | 
						||
| 
								 | 
							
								        actionResult,
							 | 
						||
| 
								 | 
							
								        defaultShouldRevalidate
							 | 
						||
| 
								 | 
							
								      }));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (typeof routeChoice === "boolean") {
							 | 
						||
| 
								 | 
							
								        return routeChoice;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return defaultShouldRevalidate;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  async function callLoaderOrAction(type, request, match, matches, basename, isStaticRequest, isRouteRequest, requestContext) {
							 | 
						||
| 
								 | 
							
								    if (basename === void 0) {
							 | 
						||
| 
								 | 
							
								      basename = "/";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (isStaticRequest === void 0) {
							 | 
						||
| 
								 | 
							
								      isStaticRequest = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (isRouteRequest === void 0) {
							 | 
						||
| 
								 | 
							
								      isRouteRequest = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let resultType;
							 | 
						||
| 
								 | 
							
								    let result; // Setup a promise we can race against so that abort signals short circuit
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let reject;
							 | 
						||
| 
								 | 
							
								    let abortPromise = new Promise((_, r) => reject = r);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let onReject = () => reject();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    request.signal.addEventListener("abort", onReject);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      let handler = match.route[type];
							 | 
						||
| 
								 | 
							
								      invariant(handler, "Could not find the " + type + " to run on the \"" + match.route.id + "\" route");
							 | 
						||
| 
								 | 
							
								      result = await Promise.race([handler({
							 | 
						||
| 
								 | 
							
								        request,
							 | 
						||
| 
								 | 
							
								        params: match.params,
							 | 
						||
| 
								 | 
							
								        context: requestContext
							 | 
						||
| 
								 | 
							
								      }), abortPromise]);
							 | 
						||
| 
								 | 
							
								      invariant(result !== undefined, "You defined " + (type === "action" ? "an action" : "a loader") + " for route " + ("\"" + match.route.id + "\" but didn't return anything from your `" + type + "` ") + "function. Please return a value or `null`.");
							 | 
						||
| 
								 | 
							
								    } catch (e) {
							 | 
						||
| 
								 | 
							
								      resultType = ResultType.error;
							 | 
						||
| 
								 | 
							
								      result = e;
							 | 
						||
| 
								 | 
							
								    } finally {
							 | 
						||
| 
								 | 
							
								      request.signal.removeEventListener("abort", onReject);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (isResponse(result)) {
							 | 
						||
| 
								 | 
							
								      let status = result.status; // Process redirects
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (redirectStatusCodes.has(status)) {
							 | 
						||
| 
								 | 
							
								        let location = result.headers.get("Location");
							 | 
						||
| 
								 | 
							
								        invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
							 | 
						||
| 
								 | 
							
								        let isAbsolute = /^[a-z+]+:\/\//i.test(location) || location.startsWith("//"); // Support relative routing in internal redirects
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!isAbsolute) {
							 | 
						||
| 
								 | 
							
								          let activeMatches = matches.slice(0, matches.indexOf(match) + 1);
							 | 
						||
| 
								 | 
							
								          let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase);
							 | 
						||
| 
								 | 
							
								          let resolvedLocation = resolveTo(location, routePathnames, new URL(request.url).pathname);
							 | 
						||
| 
								 | 
							
								          invariant(createPath(resolvedLocation), "Unable to resolve redirect location: " + location); // Prepend the basename to the redirect location if we have one
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (basename) {
							 | 
						||
| 
								 | 
							
								            let path = resolvedLocation.pathname;
							 | 
						||
| 
								 | 
							
								            resolvedLocation.pathname = path === "/" ? basename : joinPaths([basename, path]);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          location = createPath(resolvedLocation);
							 | 
						||
| 
								 | 
							
								        } // Don't process redirects in the router during static requests requests.
							 | 
						||
| 
								 | 
							
								        // Instead, throw the Response and let the server handle it with an HTTP
							 | 
						||
| 
								 | 
							
								        // redirect.  We also update the Location header in place in this flow so
							 | 
						||
| 
								 | 
							
								        // basename and relative routing is taken into account
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isStaticRequest) {
							 | 
						||
| 
								 | 
							
								          result.headers.set("Location", location);
							 | 
						||
| 
								 | 
							
								          throw result;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          type: ResultType.redirect,
							 | 
						||
| 
								 | 
							
								          status,
							 | 
						||
| 
								 | 
							
								          location,
							 | 
						||
| 
								 | 
							
								          revalidate: result.headers.get("X-Remix-Revalidate") !== null
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } // For SSR single-route requests, we want to hand Responses back directly
							 | 
						||
| 
								 | 
							
								      // without unwrapping.  We do this with the QueryRouteResponse wrapper
							 | 
						||
| 
								 | 
							
								      // interface so we can know whether it was returned or thrown
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRouteRequest) {
							 | 
						||
| 
								 | 
							
								        // eslint-disable-next-line no-throw-literal
							 | 
						||
| 
								 | 
							
								        throw {
							 | 
						||
| 
								 | 
							
								          type: resultType || ResultType.data,
							 | 
						||
| 
								 | 
							
								          response: result
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let data;
							 | 
						||
| 
								 | 
							
								      let contentType = result.headers.get("Content-Type"); // Check between word boundaries instead of startsWith() due to the last
							 | 
						||
| 
								 | 
							
								      // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (contentType && /\bapplication\/json\b/.test(contentType)) {
							 | 
						||
| 
								 | 
							
								        data = await result.json();
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        data = await result.text();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (resultType === ResultType.error) {
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          type: resultType,
							 | 
						||
| 
								 | 
							
								          error: new ErrorResponse(status, result.statusText, data),
							 | 
						||
| 
								 | 
							
								          headers: result.headers
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        type: ResultType.data,
							 | 
						||
| 
								 | 
							
								        data,
							 | 
						||
| 
								 | 
							
								        statusCode: result.status,
							 | 
						||
| 
								 | 
							
								        headers: result.headers
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (resultType === ResultType.error) {
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        type: resultType,
							 | 
						||
| 
								 | 
							
								        error: result
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (result instanceof DeferredData) {
							 | 
						||
| 
								 | 
							
								      return {
							 | 
						||
| 
								 | 
							
								        type: ResultType.deferred,
							 | 
						||
| 
								 | 
							
								        deferredData: result
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      type: ResultType.data,
							 | 
						||
| 
								 | 
							
								      data: result
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  } // Utility method for creating the Request instances for loaders/actions during
							 | 
						||
| 
								 | 
							
								  // client-side navigations and fetches.  During SSR we will always have a
							 | 
						||
| 
								 | 
							
								  // Request instance from the static handler (query/queryRoute)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createClientSideRequest(location, signal, submission) {
							 | 
						||
| 
								 | 
							
								    let url = createClientSideURL(stripHashFromPath(location)).toString();
							 | 
						||
| 
								 | 
							
								    let init = {
							 | 
						||
| 
								 | 
							
								      signal
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (submission && isMutationMethod(submission.formMethod)) {
							 | 
						||
| 
								 | 
							
								      let {
							 | 
						||
| 
								 | 
							
								        formMethod,
							 | 
						||
| 
								 | 
							
								        formEncType,
							 | 
						||
| 
								 | 
							
								        formData
							 | 
						||
| 
								 | 
							
								      } = submission;
							 | 
						||
| 
								 | 
							
								      init.method = formMethod.toUpperCase();
							 | 
						||
| 
								 | 
							
								      init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData;
							 | 
						||
| 
								 | 
							
								    } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return new Request(url, init);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function convertFormDataToSearchParams(formData) {
							 | 
						||
| 
								 | 
							
								    let searchParams = new URLSearchParams();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let [key, value] of formData.entries()) {
							 | 
						||
| 
								 | 
							
								      invariant(typeof value === "string", 'File inputs are not supported with encType "application/x-www-form-urlencoded", ' + 'please use "multipart/form-data" instead.');
							 | 
						||
| 
								 | 
							
								      searchParams.append(key, value);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return searchParams;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) {
							 | 
						||
| 
								 | 
							
								    // Fill in loaderData/errors from our loaders
							 | 
						||
| 
								 | 
							
								    let loaderData = {};
							 | 
						||
| 
								 | 
							
								    let errors = null;
							 | 
						||
| 
								 | 
							
								    let statusCode;
							 | 
						||
| 
								 | 
							
								    let foundError = false;
							 | 
						||
| 
								 | 
							
								    let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    results.forEach((result, index) => {
							 | 
						||
| 
								 | 
							
								      let id = matchesToLoad[index].route.id;
							 | 
						||
| 
								 | 
							
								      invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isErrorResult(result)) {
							 | 
						||
| 
								 | 
							
								        // Look upwards from the matched route for the closest ancestor
							 | 
						||
| 
								 | 
							
								        // error boundary, defaulting to the root match
							 | 
						||
| 
								 | 
							
								        let boundaryMatch = findNearestBoundary(matches, id);
							 | 
						||
| 
								 | 
							
								        let error = result.error; // If we have a pending action error, we report it at the highest-route
							 | 
						||
| 
								 | 
							
								        // that throws a loader error, and then clear it out to indicate that
							 | 
						||
| 
								 | 
							
								        // it was consumed
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (pendingError) {
							 | 
						||
| 
								 | 
							
								          error = Object.values(pendingError)[0];
							 | 
						||
| 
								 | 
							
								          pendingError = undefined;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (errors[boundaryMatch.route.id] == null) {
							 | 
						||
| 
								 | 
							
								          errors[boundaryMatch.route.id] = error;
							 | 
						||
| 
								 | 
							
								        } // Clear our any prior loaderData for the throwing route
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        loaderData[id] = undefined; // Once we find our first (highest) error, we set the status code and
							 | 
						||
| 
								 | 
							
								        // prevent deeper status codes from overriding
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!foundError) {
							 | 
						||
| 
								 | 
							
								          foundError = true;
							 | 
						||
| 
								 | 
							
								          statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (result.headers) {
							 | 
						||
| 
								 | 
							
								          loaderHeaders[id] = result.headers;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (isDeferredResult(result)) {
							 | 
						||
| 
								 | 
							
								        activeDeferreds && activeDeferreds.set(id, result.deferredData);
							 | 
						||
| 
								 | 
							
								        loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        loaderData[id] = result.data; // Error status codes always override success status codes, but if all
							 | 
						||
| 
								 | 
							
								        // loaders are successful we take the deepest status code.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
							 | 
						||
| 
								 | 
							
								          statusCode = result.statusCode;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (result.headers) {
							 | 
						||
| 
								 | 
							
								          loaderHeaders[id] = result.headers;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }); // If we didn't consume the pending action error (i.e., all loaders
							 | 
						||
| 
								 | 
							
								    // resolved), then consume it here.  Also clear out any loaderData for the
							 | 
						||
| 
								 | 
							
								    // throwing route
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (pendingError) {
							 | 
						||
| 
								 | 
							
								      errors = pendingError;
							 | 
						||
| 
								 | 
							
								      loaderData[Object.keys(pendingError)[0]] = undefined;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      loaderData,
							 | 
						||
| 
								 | 
							
								      errors,
							 | 
						||
| 
								 | 
							
								      statusCode: statusCode || 200,
							 | 
						||
| 
								 | 
							
								      loaderHeaders
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) {
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      loaderData,
							 | 
						||
| 
								 | 
							
								      errors
							 | 
						||
| 
								 | 
							
								    } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let index = 0; index < revalidatingFetchers.length; index++) {
							 | 
						||
| 
								 | 
							
								      let [key,, match] = revalidatingFetchers[index];
							 | 
						||
| 
								 | 
							
								      invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result");
							 | 
						||
| 
								 | 
							
								      let result = fetcherResults[index]; // Process fetcher non-redirect errors
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isErrorResult(result)) {
							 | 
						||
| 
								 | 
							
								        let boundaryMatch = findNearestBoundary(state.matches, match.route.id);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!(errors && errors[boundaryMatch.route.id])) {
							 | 
						||
| 
								 | 
							
								          errors = _extends({}, errors, {
							 | 
						||
| 
								 | 
							
								            [boundaryMatch.route.id]: result.error
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        state.fetchers.delete(key);
							 | 
						||
| 
								 | 
							
								      } else if (isRedirectResult(result)) {
							 | 
						||
| 
								 | 
							
								        // Should never get here, redirects should get processed above, but we
							 | 
						||
| 
								 | 
							
								        // keep this to type narrow to a success result in the else
							 | 
						||
| 
								 | 
							
								        throw new Error("Unhandled fetcher revalidation redirect");
							 | 
						||
| 
								 | 
							
								      } else if (isDeferredResult(result)) {
							 | 
						||
| 
								 | 
							
								        // Should never get here, deferred data should be awaited for fetchers
							 | 
						||
| 
								 | 
							
								        // in resolveDeferredResults
							 | 
						||
| 
								 | 
							
								        throw new Error("Unhandled fetcher deferred data");
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        let doneFetcher = {
							 | 
						||
| 
								 | 
							
								          state: "idle",
							 | 
						||
| 
								 | 
							
								          data: result.data,
							 | 
						||
| 
								 | 
							
								          formMethod: undefined,
							 | 
						||
| 
								 | 
							
								          formAction: undefined,
							 | 
						||
| 
								 | 
							
								          formEncType: undefined,
							 | 
						||
| 
								 | 
							
								          formData: undefined,
							 | 
						||
| 
								 | 
							
								          " _hasFetcherDoneAnything ": true
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        state.fetchers.set(key, doneFetcher);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      loaderData,
							 | 
						||
| 
								 | 
							
								      errors
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
							 | 
						||
| 
								 | 
							
								    let mergedLoaderData = _extends({}, newLoaderData);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let match of matches) {
							 | 
						||
| 
								 | 
							
								      let id = match.route.id;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (newLoaderData.hasOwnProperty(id)) {
							 | 
						||
| 
								 | 
							
								        if (newLoaderData[id] !== undefined) {
							 | 
						||
| 
								 | 
							
								          mergedLoaderData[id] = newLoaderData[id];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (loaderData[id] !== undefined) {
							 | 
						||
| 
								 | 
							
								        mergedLoaderData[id] = loaderData[id];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (errors && errors.hasOwnProperty(id)) {
							 | 
						||
| 
								 | 
							
								        // Don't keep any loader data below the boundary
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return mergedLoaderData;
							 | 
						||
| 
								 | 
							
								  } // Find the nearest error boundary, looking upwards from the leaf route (or the
							 | 
						||
| 
								 | 
							
								  // route specified by routeId) for the closest ancestor error boundary,
							 | 
						||
| 
								 | 
							
								  // defaulting to the root match
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function findNearestBoundary(matches, routeId) {
							 | 
						||
| 
								 | 
							
								    let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches];
							 | 
						||
| 
								 | 
							
								    return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getShortCircuitMatches(routes) {
							 | 
						||
| 
								 | 
							
								    // Prefer a root layout route if present, otherwise shim in a route object
							 | 
						||
| 
								 | 
							
								    let route = routes.find(r => r.index || !r.path || r.path === "/") || {
							 | 
						||
| 
								 | 
							
								      id: "__shim-error-route__"
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      matches: [{
							 | 
						||
| 
								 | 
							
								        params: {},
							 | 
						||
| 
								 | 
							
								        pathname: "",
							 | 
						||
| 
								 | 
							
								        pathnameBase: "",
							 | 
						||
| 
								 | 
							
								        route
							 | 
						||
| 
								 | 
							
								      }],
							 | 
						||
| 
								 | 
							
								      route
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getInternalRouterError(status, _temp4) {
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      pathname,
							 | 
						||
| 
								 | 
							
								      routeId,
							 | 
						||
| 
								 | 
							
								      method
							 | 
						||
| 
								 | 
							
								    } = _temp4 === void 0 ? {} : _temp4;
							 | 
						||
| 
								 | 
							
								    let statusText = "Unknown Server Error";
							 | 
						||
| 
								 | 
							
								    let errorMessage = "Unknown @remix-run/router error";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (status === 400) {
							 | 
						||
| 
								 | 
							
								      statusText = "Bad Request";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (method && pathname && routeId) {
							 | 
						||
| 
								 | 
							
								        errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        errorMessage = "Cannot submit binary form data using GET";
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else if (status === 403) {
							 | 
						||
| 
								 | 
							
								      statusText = "Forbidden";
							 | 
						||
| 
								 | 
							
								      errorMessage = "Route \"" + routeId + "\" does not match URL \"" + pathname + "\"";
							 | 
						||
| 
								 | 
							
								    } else if (status === 404) {
							 | 
						||
| 
								 | 
							
								      statusText = "Not Found";
							 | 
						||
| 
								 | 
							
								      errorMessage = "No route matches URL \"" + pathname + "\"";
							 | 
						||
| 
								 | 
							
								    } else if (status === 405) {
							 | 
						||
| 
								 | 
							
								      statusText = "Method Not Allowed";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (method && pathname && routeId) {
							 | 
						||
| 
								 | 
							
								        errorMessage = "You made a " + method.toUpperCase() + " request to \"" + pathname + "\" but " + ("did not provide an `action` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
							 | 
						||
| 
								 | 
							
								      } else if (method) {
							 | 
						||
| 
								 | 
							
								        errorMessage = "Invalid request method \"" + method.toUpperCase() + "\"";
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true);
							 | 
						||
| 
								 | 
							
								  } // Find any returned redirect errors, starting from the lowest match
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function findRedirect(results) {
							 | 
						||
| 
								 | 
							
								    for (let i = results.length - 1; i >= 0; i--) {
							 | 
						||
| 
								 | 
							
								      let result = results[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isRedirectResult(result)) {
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function stripHashFromPath(path) {
							 | 
						||
| 
								 | 
							
								    let parsedPath = typeof path === "string" ? parsePath(path) : path;
							 | 
						||
| 
								 | 
							
								    return createPath(_extends({}, parsedPath, {
							 | 
						||
| 
								 | 
							
								      hash: ""
							 | 
						||
| 
								 | 
							
								    }));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isHashChangeOnly(a, b) {
							 | 
						||
| 
								 | 
							
								    return a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isDeferredResult(result) {
							 | 
						||
| 
								 | 
							
								    return result.type === ResultType.deferred;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isErrorResult(result) {
							 | 
						||
| 
								 | 
							
								    return result.type === ResultType.error;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isRedirectResult(result) {
							 | 
						||
| 
								 | 
							
								    return (result && result.type) === ResultType.redirect;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isResponse(value) {
							 | 
						||
| 
								 | 
							
								    return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isRedirectResponse(result) {
							 | 
						||
| 
								 | 
							
								    if (!isResponse(result)) {
							 | 
						||
| 
								 | 
							
								      return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let status = result.status;
							 | 
						||
| 
								 | 
							
								    let location = result.headers.get("Location");
							 | 
						||
| 
								 | 
							
								    return status >= 300 && status <= 399 && location != null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isQueryRouteResponse(obj) {
							 | 
						||
| 
								 | 
							
								    return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isValidMethod(method) {
							 | 
						||
| 
								 | 
							
								    return validRequestMethods.has(method);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function isMutationMethod(method) {
							 | 
						||
| 
								 | 
							
								    return validMutationMethods.has(method);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
							 | 
						||
| 
								 | 
							
								    for (let index = 0; index < results.length; index++) {
							 | 
						||
| 
								 | 
							
								      let result = results[index];
							 | 
						||
| 
								 | 
							
								      let match = matchesToLoad[index];
							 | 
						||
| 
								 | 
							
								      let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
							 | 
						||
| 
								 | 
							
								      let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {
							 | 
						||
| 
								 | 
							
								        // Note: we do not have to touch activeDeferreds here since we race them
							 | 
						||
| 
								 | 
							
								        // against the signal in resolveDeferredData and they'll get aborted
							 | 
						||
| 
								 | 
							
								        // there if needed
							 | 
						||
| 
								 | 
							
								        await resolveDeferredData(result, signal, isFetcher).then(result => {
							 | 
						||
| 
								 | 
							
								          if (result) {
							 | 
						||
| 
								 | 
							
								            results[index] = result || results[index];
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  async function resolveDeferredData(result, signal, unwrap) {
							 | 
						||
| 
								 | 
							
								    if (unwrap === void 0) {
							 | 
						||
| 
								 | 
							
								      unwrap = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let aborted = await result.deferredData.resolveData(signal);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (aborted) {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (unwrap) {
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          type: ResultType.data,
							 | 
						||
| 
								 | 
							
								          data: result.deferredData.unwrappedData
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      } catch (e) {
							 | 
						||
| 
								 | 
							
								        // Handle any TrackedPromise._error values encountered while unwrapping
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								          type: ResultType.error,
							 | 
						||
| 
								 | 
							
								          error: e
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      type: ResultType.data,
							 | 
						||
| 
								 | 
							
								      data: result.deferredData.data
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function hasNakedIndexQuery(search) {
							 | 
						||
| 
								 | 
							
								    return new URLSearchParams(search).getAll("index").some(v => v === "");
							 | 
						||
| 
								 | 
							
								  } // Note: This should match the format exported by useMatches, so if you change
							 | 
						||
| 
								 | 
							
								  // this please also change that :)  Eventually we'll DRY this up
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function createUseMatchesMatch(match, loaderData) {
							 | 
						||
| 
								 | 
							
								    let {
							 | 
						||
| 
								 | 
							
								      route,
							 | 
						||
| 
								 | 
							
								      pathname,
							 | 
						||
| 
								 | 
							
								      params
							 | 
						||
| 
								 | 
							
								    } = match;
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      id: route.id,
							 | 
						||
| 
								 | 
							
								      pathname,
							 | 
						||
| 
								 | 
							
								      params,
							 | 
						||
| 
								 | 
							
								      data: loaderData[route.id],
							 | 
						||
| 
								 | 
							
								      handle: route.handle
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function getTargetMatch(matches, location) {
							 | 
						||
| 
								 | 
							
								    let search = typeof location === "string" ? parsePath(location).search : location.search;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
							 | 
						||
| 
								 | 
							
								      // Return the leaf index route when index is present
							 | 
						||
| 
								 | 
							
								      return matches[matches.length - 1];
							 | 
						||
| 
								 | 
							
								    } // Otherwise grab the deepest "path contributing" match (ignoring index and
							 | 
						||
| 
								 | 
							
								    // pathless layout routes)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let pathMatches = getPathContributingMatches(matches);
							 | 
						||
| 
								 | 
							
								    return pathMatches[pathMatches.length - 1];
							 | 
						||
| 
								 | 
							
								  } //#endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  exports.AbortedDeferredError = AbortedDeferredError;
							 | 
						||
| 
								 | 
							
								  exports.ErrorResponse = ErrorResponse;
							 | 
						||
| 
								 | 
							
								  exports.IDLE_FETCHER = IDLE_FETCHER;
							 | 
						||
| 
								 | 
							
								  exports.IDLE_NAVIGATION = IDLE_NAVIGATION;
							 | 
						||
| 
								 | 
							
								  exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
							 | 
						||
| 
								 | 
							
								  exports.UNSAFE_getPathContributingMatches = getPathContributingMatches;
							 | 
						||
| 
								 | 
							
								  exports.createBrowserHistory = createBrowserHistory;
							 | 
						||
| 
								 | 
							
								  exports.createHashHistory = createHashHistory;
							 | 
						||
| 
								 | 
							
								  exports.createMemoryHistory = createMemoryHistory;
							 | 
						||
| 
								 | 
							
								  exports.createPath = createPath;
							 | 
						||
| 
								 | 
							
								  exports.createRouter = createRouter;
							 | 
						||
| 
								 | 
							
								  exports.createStaticHandler = createStaticHandler;
							 | 
						||
| 
								 | 
							
								  exports.defer = defer;
							 | 
						||
| 
								 | 
							
								  exports.generatePath = generatePath;
							 | 
						||
| 
								 | 
							
								  exports.getStaticContextFromError = getStaticContextFromError;
							 | 
						||
| 
								 | 
							
								  exports.getToPathname = getToPathname;
							 | 
						||
| 
								 | 
							
								  exports.invariant = invariant;
							 | 
						||
| 
								 | 
							
								  exports.isRouteErrorResponse = isRouteErrorResponse;
							 | 
						||
| 
								 | 
							
								  exports.joinPaths = joinPaths;
							 | 
						||
| 
								 | 
							
								  exports.json = json;
							 | 
						||
| 
								 | 
							
								  exports.matchPath = matchPath;
							 | 
						||
| 
								 | 
							
								  exports.matchRoutes = matchRoutes;
							 | 
						||
| 
								 | 
							
								  exports.normalizePathname = normalizePathname;
							 | 
						||
| 
								 | 
							
								  exports.parsePath = parsePath;
							 | 
						||
| 
								 | 
							
								  exports.redirect = redirect;
							 | 
						||
| 
								 | 
							
								  exports.resolvePath = resolvePath;
							 | 
						||
| 
								 | 
							
								  exports.resolveTo = resolveTo;
							 | 
						||
| 
								 | 
							
								  exports.stripBasename = stripBasename;
							 | 
						||
| 
								 | 
							
								  exports.warning = warning;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Object.defineProperty(exports, '__esModule', { value: true });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}));
							 | 
						||
| 
								 | 
							
								//# sourceMappingURL=router.umd.js.map
							 |