File: /home/zeusxp5/lrliberia.com/wp-content/themes/lifttruck/inc/panel/build/index.js
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/@remix-run/router/dist/router.js":
/*!*******************************************************!*\
!*** ./node_modules/@remix-run/router/dist/router.js ***!
\*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ AbortedDeferredError: () => (/* binding */ AbortedDeferredError),
/* harmony export */ Action: () => (/* binding */ Action),
/* harmony export */ IDLE_BLOCKER: () => (/* binding */ IDLE_BLOCKER),
/* harmony export */ IDLE_FETCHER: () => (/* binding */ IDLE_FETCHER),
/* harmony export */ IDLE_NAVIGATION: () => (/* binding */ IDLE_NAVIGATION),
/* harmony export */ UNSAFE_DEFERRED_SYMBOL: () => (/* binding */ UNSAFE_DEFERRED_SYMBOL),
/* harmony export */ UNSAFE_DeferredData: () => (/* binding */ DeferredData),
/* harmony export */ UNSAFE_ErrorResponseImpl: () => (/* binding */ ErrorResponseImpl),
/* harmony export */ UNSAFE_convertRouteMatchToUiMatch: () => (/* binding */ convertRouteMatchToUiMatch),
/* harmony export */ UNSAFE_convertRoutesToDataRoutes: () => (/* binding */ convertRoutesToDataRoutes),
/* harmony export */ UNSAFE_getResolveToMatches: () => (/* binding */ getResolveToMatches),
/* harmony export */ UNSAFE_invariant: () => (/* binding */ invariant),
/* harmony export */ UNSAFE_warning: () => (/* binding */ warning),
/* harmony export */ createBrowserHistory: () => (/* binding */ createBrowserHistory),
/* harmony export */ createHashHistory: () => (/* binding */ createHashHistory),
/* harmony export */ createMemoryHistory: () => (/* binding */ createMemoryHistory),
/* harmony export */ createPath: () => (/* binding */ createPath),
/* harmony export */ createRouter: () => (/* binding */ createRouter),
/* harmony export */ createStaticHandler: () => (/* binding */ createStaticHandler),
/* harmony export */ defer: () => (/* binding */ defer),
/* harmony export */ generatePath: () => (/* binding */ generatePath),
/* harmony export */ getStaticContextFromError: () => (/* binding */ getStaticContextFromError),
/* harmony export */ getToPathname: () => (/* binding */ getToPathname),
/* harmony export */ isDeferredData: () => (/* binding */ isDeferredData),
/* harmony export */ isRouteErrorResponse: () => (/* binding */ isRouteErrorResponse),
/* harmony export */ joinPaths: () => (/* binding */ joinPaths),
/* harmony export */ json: () => (/* binding */ json),
/* harmony export */ matchPath: () => (/* binding */ matchPath),
/* harmony export */ matchRoutes: () => (/* binding */ matchRoutes),
/* harmony export */ normalizePathname: () => (/* binding */ normalizePathname),
/* harmony export */ parsePath: () => (/* binding */ parsePath),
/* harmony export */ redirect: () => (/* binding */ redirect),
/* harmony export */ redirectDocument: () => (/* binding */ redirectDocument),
/* harmony export */ resolvePath: () => (/* binding */ resolvePath),
/* harmony export */ resolveTo: () => (/* binding */ resolveTo),
/* harmony export */ stripBasename: () => (/* binding */ stripBasename)
/* harmony export */ });
/**
* @remix-run/router v1.14.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 _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.
*/
var Action;
(function (Action) {
/**
* A POP indicates a change to an arbitrary index in the history stack, such
* as a back or forward navigation. It does not describe the direction of the
* navigation, only that the current index changed.
*
* Note: This is the default action for newly created history objects.
*/
Action["Pop"] = "POP";
/**
* A PUSH indicates a new entry being added to the history stack, such as when
* a link is clicked and a new page loads. When this happens, all subsequent
* entries in the stack are lost.
*/
Action["Push"] = "PUSH";
/**
* A REPLACE indicates the entry at the current index in the history stack
* being replaced by a new one.
*/
Action["Replace"] = "REPLACE";
})(Action || (Action = {}));
const PopStateEventType = "popstate";
/**
* 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 = 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(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to));
return location;
}
function createHref(to) {
return typeof to === "string" ? to : createPath(to);
}
let history = {
get index() {
return index;
},
get action() {
return action;
},
get location() {
return getCurrentLocation();
},
createHref,
createURL(to) {
return new URL(createHref(to), "http://localhost");
},
encodeLocation(to) {
let path = typeof to === "string" ? parsePath(to) : to;
return {
pathname: path.pathname || "",
search: path.search || "",
hash: path.hash || ""
};
},
push(to, state) {
action = Action.Push;
let nextLocation = createMemoryLocation(to, state);
index += 1;
entries.splice(index, entries.length, nextLocation);
if (v5Compat && listener) {
listener({
action,
location: nextLocation,
delta: 1
});
}
},
replace(to, state) {
action = Action.Replace;
let nextLocation = createMemoryLocation(to, state);
entries[index] = nextLocation;
if (v5Compat && listener) {
listener({
action,
location: nextLocation,
delta: 0
});
}
},
go(delta) {
action = Action.Pop;
let nextIndex = clampIndex(index + delta);
let nextLocation = entries[nextIndex];
index = nextIndex;
if (listener) {
listener({
action,
location: nextLocation,
delta
});
}
},
listen(fn) {
listener = fn;
return () => {
listener = null;
};
}
};
return history;
}
/**
* 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);
}
/**
* 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));
// Hash URL should always have a leading / just like window.location.pathname
// does, so if an app ends up at a route like /#something then we add a
// leading slash so all of our path-matching behaves the same as if it would
// in a browser router. This is particularly important when there exists a
// root splat route (<Route path="*">) since that matches internally against
// "/*" and we'd expect /#something to 404 in a hash router app.
if (!pathname.startsWith("/") && !pathname.startsWith(".")) {
pathname = "/" + pathname;
}
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(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")");
}
return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options);
}
function invariant(value, message) {
if (value === false || value === null || typeof value === "undefined") {
throw new Error(message);
}
}
function warning(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, index) {
return {
usr: location.state,
key: location.key,
idx: index
};
}
/**
* 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 getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
if (options === void 0) {
options = {};
}
let {
window = document.defaultView,
v5Compat = false
} = options;
let globalHistory = window.history;
let action = Action.Pop;
let listener = null;
let index = getIndex();
// Index should only be null when we initialize. If not, it's because the
// user called history.pushState or history.replaceState directly, in which
// case we should log a warning as it will result in bugs.
if (index == null) {
index = 0;
globalHistory.replaceState(_extends({}, globalHistory.state, {
idx: index
}), "");
}
function getIndex() {
let state = globalHistory.state || {
idx: null
};
return state.idx;
}
function handlePop() {
action = Action.Pop;
let nextIndex = getIndex();
let delta = nextIndex == null ? null : nextIndex - index;
index = nextIndex;
if (listener) {
listener({
action,
location: history.location,
delta
});
}
}
function push(to, state) {
action = Action.Push;
let location = createLocation(history.location, to, state);
if (validateLocation) validateLocation(location, to);
index = getIndex() + 1;
let historyState = getHistoryState(location, index);
let url = history.createHref(location);
// try...catch because iOS limits us to 100 pushState calls :/
try {
globalHistory.pushState(historyState, "", url);
} catch (error) {
// If the exception is because `state` can't be serialized, let that throw
// outwards just like a replace call would so the dev knows the cause
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#shared-history-push/replace-state-steps
// https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal
if (error instanceof DOMException && error.name === "DataCloneError") {
throw 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,
delta: 1
});
}
}
function replace(to, state) {
action = Action.Replace;
let location = createLocation(history.location, to, state);
if (validateLocation) validateLocation(location, to);
index = getIndex();
let historyState = getHistoryState(location, index);
let url = history.createHref(location);
globalHistory.replaceState(historyState, "", url);
if (v5Compat && listener) {
listener({
action,
location: history.location,
delta: 0
});
}
}
function createURL(to) {
// 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 = window.location.origin !== "null" ? window.location.origin : window.location.href;
let href = typeof to === "string" ? to : createPath(to);
invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
return new URL(href, base);
}
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);
},
createURL,
encodeLocation(to) {
// Encode a Location the same way window.location would
let url = createURL(to);
return {
pathname: url.pathname,
search: url.search,
hash: url.hash
};
},
push,
replace,
go(n) {
return globalHistory.go(n);
}
};
return history;
}
//#endregion
var ResultType;
(function (ResultType) {
ResultType["data"] = "data";
ResultType["deferred"] = "deferred";
ResultType["redirect"] = "redirect";
ResultType["error"] = "error";
})(ResultType || (ResultType = {}));
const immutableRouteKeys = new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]);
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, mapRouteProperties, parentPath, manifest) {
if (parentPath === void 0) {
parentPath = [];
}
if (manifest === void 0) {
manifest = {};
}
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(!manifest[id], "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages");
if (isIndexRoute(route)) {
let indexRoute = _extends({}, route, mapRouteProperties(route), {
id
});
manifest[id] = indexRoute;
return indexRoute;
} else {
let pathOrLayoutRoute = _extends({}, route, mapRouteProperties(route), {
id,
children: undefined
});
manifest[id] = pathOrLayoutRoute;
if (route.children) {
pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, mapRouteProperties, treePath, manifest);
}
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 convertRouteMatchToUiMatch(match, loaderData) {
let {
route,
pathname,
params
} = match;
return {
id: route.id,
pathname,
params,
data: loaderData[route.id],
handle: route.handle
};
}
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 explode _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(/\*$/, "/*");
}
// ensure `/` is added at the beginning if the path is absolute
const prefix = path.startsWith("/") ? "/" : "";
const stringify = p => p == null ? "" : typeof p === "string" ? p : String(p);
const segments = path.split(/\/+/).map((segment, index, array) => {
const isLastSegment = index === array.length - 1;
// only apply the splat if it's the last segment
if (isLastSegment && segment === "*") {
const star = "*";
// Apply the splat
return stringify(params[star]);
}
const keyMatch = segment.match(/^:(\w+)(\??)$/);
if (keyMatch) {
const [, key, optional] = keyMatch;
let param = params[key];
invariant(optional === "?" || param != null, "Missing \":" + key + "\" param");
return stringify(param);
}
// Remove any optional markers from optional static segments
return segment.replace(/\?$/g, "");
})
// Remove empty segments
.filter(segment => !!segment);
return prefix + segments.join("/");
}
/**
* 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, compiledParams] = 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 = compiledParams.reduce((memo, _ref, index) => {
let {
paramName,
isOptional
} = _ref;
// 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");
}
const value = captureGroups[index];
if (isOptional && !value) {
memo[paramName] = undefined;
} else {
memo[paramName] = safelyDecodeURIComponent(value || "", 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 params = [];
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, isOptional) => {
params.push({
paramName,
isOptional: isOptional != null
});
return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
});
if (path.endsWith("*")) {
params.push({
paramName: "*"
});
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, params];
}
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) || "/";
}
/**
* 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);
}
// Return the array of pathnames for the current route matches - used to
// generate the routePathnames input for resolveTo()
function getResolveToMatches(matches, v7_relativeSplatPath) {
let pathMatches = getPathContributingMatches(matches);
// When v7_relativeSplatPath is enabled, use the full pathname for the leaf
// match so we include splat values for "." links. See:
// https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329
if (v7_relativeSplatPath) {
return pathMatches.map((match, idx) => idx === matches.length - 1 ? match.pathname : match.pathnameBase);
}
return pathMatches.map(match => match.pathnameBase);
}
/**
* @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 (toPathname == null) {
from = locationPathname;
} else {
let routePathnameIndex = routePathnames.length - 1;
// With relative="route" (the default), 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".
if (!isPathRelative && toPathname.startsWith("..")) {
let toSegments = toPathname.split("/");
while (toSegments[0] === "..") {
toSegments.shift();
routePathnameIndex -= 1;
}
to.pathname = toSegments.join("/");
}
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, responseInit) {
this.pendingKeysSet = new Set();
this.subscribers = new Set();
this.deferredKeys = [];
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, _ref2) => {
let [key, value] = _ref2;
return Object.assign(acc, {
[key]: this.trackPromise(key, value)
});
}, {});
if (this.done) {
// All incoming values were resolved
this.unlistenAbortSignal();
}
this.init = responseInit;
}
trackPromise(key, value) {
if (!(value instanceof Promise)) {
return value;
}
this.deferredKeys.push(key);
this.pendingKeysSet.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, undefined, 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.pendingKeysSet.delete(key);
if (this.done) {
// Nothing left to abort!
this.unlistenAbortSignal();
}
// If the promise was resolved/rejected with undefined, we'll throw an error as you
// should always resolve with a value or null
if (error === undefined && data === undefined) {
let undefinedError = new Error("Deferred data for key \"" + key + "\" resolved/rejected with `undefined`, " + "you must resolve/reject with a value or `null`.");
Object.defineProperty(promise, "_error", {
get: () => undefinedError
});
this.emit(false, key);
return Promise.reject(undefinedError);
}
if (data === undefined) {
Object.defineProperty(promise, "_error", {
get: () => error
});
this.emit(false, key);
return Promise.reject(error);
}
Object.defineProperty(promise, "_data", {
get: () => data
});
this.emit(false, key);
return data;
}
emit(aborted, settledKey) {
this.subscribers.forEach(subscriber => subscriber(aborted, settledKey));
}
subscribe(fn) {
this.subscribers.add(fn);
return () => this.subscribers.delete(fn);
}
cancel() {
this.controller.abort();
this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));
this.emit(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.pendingKeysSet.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, _ref3) => {
let [key, value] = _ref3;
return Object.assign(acc, {
[key]: unwrapTrackedPromise(value)
});
}, {});
}
get pendingKeys() {
return Array.from(this.pendingKeysSet);
}
}
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;
}
const defer = function defer(data, init) {
if (init === void 0) {
init = {};
}
let responseInit = typeof init === "number" ? {
status: init
} : init;
return new DeferredData(data, responseInit);
};
/**
* 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
}));
};
/**
* A redirect response that will force a document reload to the new location.
* Sets the status code and the `Location` header.
* Defaults to "302 Found".
*/
const redirectDocument = (url, init) => {
let response = redirect(url, init);
response.headers.set("X-Remix-Reload-Document", "true");
return response;
};
/**
* @private
* Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
*
* We don't export the class for public use since it's an implementation
* detail, but we export the interface above so folks can build their own
* abstractions around instances via isRouteErrorResponse()
*/
class ErrorResponseImpl {
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 thrown from an action/loader
*/
function isRouteErrorResponse(error) {
return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
}
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,
json: undefined,
text: undefined
};
const IDLE_FETCHER = {
state: "idle",
data: undefined,
formMethod: undefined,
formAction: undefined,
formEncType: undefined,
formData: undefined,
json: undefined,
text: undefined
};
const IDLE_BLOCKER = {
state: "unblocked",
proceed: undefined,
reset: undefined,
location: undefined
};
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
const defaultMapRouteProperties = route => ({
hasErrorBoundary: Boolean(route.hasErrorBoundary)
});
const TRANSITIONS_STORAGE_KEY = "remix-router-transitions";
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region createRouter
////////////////////////////////////////////////////////////////////////////////
/**
* Create a router and listen to history POP navigations
*/
function createRouter(init) {
const routerWindow = init.window ? init.window : typeof window !== "undefined" ? window : undefined;
const isBrowser = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined";
const isServer = !isBrowser;
invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
let mapRouteProperties;
if (init.mapRouteProperties) {
mapRouteProperties = init.mapRouteProperties;
} else if (init.detectErrorBoundary) {
// If they are still using the deprecated version, wrap it with the new API
let detectErrorBoundary = init.detectErrorBoundary;
mapRouteProperties = route => ({
hasErrorBoundary: detectErrorBoundary(route)
});
} else {
mapRouteProperties = defaultMapRouteProperties;
}
// Routes keyed by ID
let manifest = {};
// Routes in tree format for matching
let dataRoutes = convertRoutesToDataRoutes(init.routes, mapRouteProperties, undefined, manifest);
let inFlightDataRoutes;
let basename = init.basename || "/";
// Config driven behavior flags
let future = _extends({
v7_fetcherPersist: false,
v7_normalizeFormMethod: false,
v7_partialHydration: false,
v7_prependBasename: false,
v7_relativeSplatPath: false
}, init.future);
// 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, 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;
let hasLazyRoutes = initialMatches.some(m => m.route.lazy);
let hasLoaders = initialMatches.some(m => m.route.loader);
if (hasLazyRoutes) {
// All initialMatches need to be loaded before we're ready. If we have lazy
// functions around still then we'll need to run them in initialize()
initialized = false;
} else if (!hasLoaders) {
// If we've got no loaders to run, then we're good to go
initialized = true;
} else if (future.v7_partialHydration) {
// If partial hydration is enabled, we're initialized so long as we were
// provided with hydrationData for every route with a loader, and no loaders
// were marked for explicit hydration
let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
let errors = init.hydrationData ? init.hydrationData.errors : null;
initialized = initialMatches.every(m => m.route.loader && m.route.loader.hydrate !== true && (loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined));
} else {
// Without partial hydration - we're initialized if we were provided any
// hydrationData - which is expected to be complete
initialized = 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(),
blockers: new Map()
};
// -- Stateful internal variables to manage navigations --
// Current navigation in progress (to be committed in completeNavigation)
let pendingAction = 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;
// Should the current navigation enable document.startViewTransition?
let pendingViewTransitionEnabled = false;
// Store applied view transitions so we can apply them on POP
let appliedViewTransitions = new Map();
// Cleanup function for persisting applied transitions to sessionStorage
let removePageHideEventListener = null;
// 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)
// - useRevalidator()
// - 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
let fetchRedirectIds = new Set();
// Most recent href/match for fetcher.load calls for fetchers
let fetchLoadMatches = new Map();
// Ref-count mounted fetchers so we know when it's ok to clean them up
let activeFetchers = new Map();
// Fetchers that have requested a delete when using v7_fetcherPersist,
// they'll be officially removed after they return to idle
let deletedFetchers = new Set();
// 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();
// Store blocker functions in a separate Map outside of router state since
// we don't need to update UI state if they change
let blockerFunctions = new Map();
// Flag to ignore the next history update, so we can revert the URL change on
// a POP navigation that was blocked by the user without touching router state
let ignoreNextHistoryUpdate = false;
// 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,
delta
} = _ref;
// Ignore this event if it was just us resetting the URL from a
// blocked POP navigation
if (ignoreNextHistoryUpdate) {
ignoreNextHistoryUpdate = false;
return;
}
warning(blockerFunctions.size === 0 || delta != null, "You are trying to use a blocker on a POP navigation to a location " + "that was not created by @remix-run/router. This will fail silently in " + "production. This can happen if you are navigating outside the router " + "via `window.history.pushState`/`window.location.hash` instead of using " + "router navigation APIs. This can also happen if you are using " + "createHashRouter and the user manually changes the URL.");
let blockerKey = shouldBlockNavigation({
currentLocation: state.location,
nextLocation: location,
historyAction
});
if (blockerKey && delta != null) {
// Restore the URL to match the current UI, but don't update router state
ignoreNextHistoryUpdate = true;
init.history.go(delta * -1);
// Put the blocker into a blocked state
updateBlocker(blockerKey, {
state: "blocked",
location,
proceed() {
updateBlocker(blockerKey, {
state: "proceeding",
proceed: undefined,
reset: undefined,
location
});
// Re-do the same POP navigation we just blocked
init.history.go(delta);
},
reset() {
let blockers = new Map(state.blockers);
blockers.set(blockerKey, IDLE_BLOCKER);
updateState({
blockers
});
}
});
return;
}
return startNavigation(historyAction, location);
});
if (isBrowser) {
// FIXME: This feels gross. How can we cleanup the lines between
// scrollRestoration/appliedTransitions persistance?
restoreAppliedTransitions(routerWindow, appliedViewTransitions);
let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions);
routerWindow.addEventListener("pagehide", _saveAppliedTransitions);
removePageHideEventListener = () => routerWindow.removeEventListener("pagehide", _saveAppliedTransitions);
}
// Kick off initial data load if needed. Use Pop to avoid modifying history
// Note we don't do any handling of lazy here. For SPA's it'll get handled
// in the normal navigation flow. For SSR it's expected that lazy modules are
// resolved prior to router creation since we can't go into a fallbackElement
// UI for SSR'd apps
if (!state.initialized) {
startNavigation(Action.Pop, state.location, {
initialHydration: true
});
}
return router;
}
// Clean up a router and it's side effects
function dispose() {
if (unlistenHistory) {
unlistenHistory();
}
if (removePageHideEventListener) {
removePageHideEventListener();
}
subscribers.clear();
pendingNavigationController && pendingNavigationController.abort();
state.fetchers.forEach((_, key) => deleteFetcher(key));
state.blockers.forEach((_, key) => deleteBlocker(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, opts) {
if (opts === void 0) {
opts = {};
}
state = _extends({}, state, newState);
// Prep fetcher cleanup so we can tell the UI which fetcher data entries
// can be removed
let completedFetchers = [];
let deletedFetchersKeys = [];
if (future.v7_fetcherPersist) {
state.fetchers.forEach((fetcher, key) => {
if (fetcher.state === "idle") {
if (deletedFetchers.has(key)) {
// Unmounted from the UI and can be totally removed
deletedFetchersKeys.push(key);
} else {
// Returned to idle but still mounted in the UI, so semi-remains for
// revalidations and such
completedFetchers.push(key);
}
}
});
}
// Iterate over a local copy so that if flushSync is used and we end up
// removing and adding a new subscriber due to the useCallback dependencies,
// we don't get ourselves into a loop calling the new subscriber immediately
[...subscribers].forEach(subscriber => subscriber(state, {
deletedFetchers: deletedFetchersKeys,
unstable_viewTransitionOpts: opts.viewTransitionOpts,
unstable_flushSync: opts.flushSync === true
}));
// Remove idle fetchers from state since we only care about in-flight fetchers.
if (future.v7_fetcherPersist) {
completedFetchers.forEach(key => state.fetchers.delete(key));
deletedFetchersKeys.forEach(key => deleteFetcher(key));
}
}
// 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, _temp) {
var _location$state, _location$state2;
let {
flushSync
} = _temp === void 0 ? {} : _temp;
// 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;
// On a successful navigation we can assume we got through all blockers
// so we can start fresh
let blockers = state.blockers;
if (blockers.size > 0) {
blockers = new Map(blockers);
blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));
}
// Always respect the user flag. Otherwise don't reset on mutation
// submission navigations unless they redirect
let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
if (inFlightDataRoutes) {
dataRoutes = inFlightDataRoutes;
inFlightDataRoutes = undefined;
}
if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) {
init.history.push(location, location.state);
} else if (pendingAction === Action.Replace) {
init.history.replace(location, location.state);
}
let viewTransitionOpts;
// On POP, enable transitions if they were enabled on the original navigation
if (pendingAction === Action.Pop) {
// Forward takes precedence so they behave like the original navigation
let priorPaths = appliedViewTransitions.get(state.location.pathname);
if (priorPaths && priorPaths.has(location.pathname)) {
viewTransitionOpts = {
currentLocation: state.location,
nextLocation: location
};
} else if (appliedViewTransitions.has(location.pathname)) {
// If we don't have a previous forward nav, assume we're popping back to
// the new location and enable if that location previously enabled
viewTransitionOpts = {
currentLocation: location,
nextLocation: state.location
};
}
} else if (pendingViewTransitionEnabled) {
// Store the applied transition on PUSH/REPLACE
let toPaths = appliedViewTransitions.get(state.location.pathname);
if (toPaths) {
toPaths.add(location.pathname);
} else {
toPaths = new Set([location.pathname]);
appliedViewTransitions.set(state.location.pathname, toPaths);
}
viewTransitionOpts = {
currentLocation: state.location,
nextLocation: location
};
}
updateState(_extends({}, newState, {
actionData,
loaderData,
historyAction: pendingAction,
location,
initialized: true,
navigation: IDLE_NAVIGATION,
revalidation: "idle",
restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),
preventScrollReset,
blockers
}), {
viewTransitionOpts,
flushSync: flushSync === true
});
// Reset stateful navigation vars
pendingAction = Action.Pop;
pendingPreventScrollReset = false;
pendingViewTransitionEnabled = 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 normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, future.v7_relativeSplatPath, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);
let {
path,
submission,
error
} = normalizeNavigateOptions(future.v7_normalizeFormMethod, false, normalizedPath, opts);
let currentLocation = state.location;
let nextLocation = 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
nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation));
let userReplace = opts && opts.replace != null ? opts.replace : undefined;
let historyAction = Action.Push;
if (userReplace === true) {
historyAction = 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 = Action.Replace;
}
let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
let flushSync = (opts && opts.unstable_flushSync) === true;
let blockerKey = shouldBlockNavigation({
currentLocation,
nextLocation,
historyAction
});
if (blockerKey) {
// Put the blocker into a blocked state
updateBlocker(blockerKey, {
state: "blocked",
location: nextLocation,
proceed() {
updateBlocker(blockerKey, {
state: "proceeding",
proceed: undefined,
reset: undefined,
location: nextLocation
});
// Send the same navigation through
navigate(to, opts);
},
reset() {
let blockers = new Map(state.blockers);
blockers.set(blockerKey, IDLE_BLOCKER);
updateState({
blockers
});
}
});
return;
}
return await startNavigation(historyAction, nextLocation, {
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,
enableViewTransition: opts && opts.unstable_viewTransition,
flushSync
});
}
// 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;
pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;
let routesToUse = inFlightDataRoutes || dataRoutes;
let loadingNavigation = opts && opts.overrideNavigation;
let matches = matchRoutes(routesToUse, location, basename);
let flushSync = (opts && opts.flushSync) === true;
// 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(routesToUse);
// Cancel all pending deferred on 404s since we don't keep any routes
cancelActiveDeferreds();
completeNavigation(location, {
matches: notFoundMatches,
loaderData: {},
errors: {
[route.id]: error
}
}, {
flushSync
});
return;
}
// Short circuit if it's only a hash change and not a revalidation or
// mutation submission.
//
// Ignore on initial page loads because since the initial load will always
// be "same hash". For example, on /page#hash and submit a <Form method="post">
// which will default to a navigation to /page
if (state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
completeNavigation(location, {
matches
}, {
flushSync
});
return;
}
// Create a controller/Request for this navigation
pendingNavigationController = new AbortController();
let request = createClientSideRequest(init.history, 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,
flushSync
});
if (actionOutput.shortCircuited) {
return;
}
pendingActionData = actionOutput.pendingActionData;
pendingError = actionOutput.pendingActionError;
loadingNavigation = getLoadingNavigation(location, opts.submission);
flushSync = false;
// 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.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, 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) {
if (opts === void 0) {
opts = {};
}
interruptActiveLoads();
// Put us in a submitting state
let navigation = getSubmittingNavigation(location, submission);
updateState({
navigation
}, {
flushSync: opts.flushSync === true
});
// Call our action and get the result
let result;
let actionMatch = getTargetMatch(matches, location);
if (!actionMatch.route.action && !actionMatch.route.lazy) {
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, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
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 = 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 getInternalRouterError(400, {
type: "defer-action"
});
}
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, fetcherSubmission, replace, initialHydration, flushSync, pendingActionData, pendingError) {
// Figure out the right navigation we want to use for data loading
let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
// 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 || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
let routesToUse = inFlightDataRoutes || dataRoutes;
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, future.v7_partialHydration && initialHydration === true, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError);
// 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));
pendingNavigationLoadId = ++incrementingLoadId;
// Short circuit if we have no loaders to run
if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
let updatedFetchers = markFetchRedirectsDone();
completeNavigation(location, _extends({
matches,
loaderData: {},
// Commit pending error if we're short circuiting
errors: pendingError || null
}, pendingActionData ? {
actionData: pendingActionData
} : {}, updatedFetchers ? {
fetchers: new Map(state.fetchers)
} : {}), {
flushSync
});
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 we have partialHydration enabled, then don't update the state for the
// initial data load since iot's not a "navigation"
if (!isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration)) {
revalidatingFetchers.forEach(rf => {
let fetcher = state.fetchers.get(rf.key);
let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);
state.fetchers.set(rf.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)
} : {}), {
flushSync
});
}
revalidatingFetchers.forEach(rf => {
if (fetchControllers.has(rf.key)) {
abortFetcher(rf.key);
}
if (rf.controller) {
// Fetchers use an independent AbortController so that aborting a fetcher
// (via deleteFetcher) does not abort the triggering navigation that
// triggered the revalidation
fetchControllers.set(rf.key, rf.controller);
}
});
// Proxy navigation abort through to revalidation fetchers
let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(f => abortFetcher(f.key));
if (pendingNavigationController) {
pendingNavigationController.signal.addEventListener("abort", abortPendingFetchRevalidations);
}
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
if (pendingNavigationController) {
pendingNavigationController.signal.removeEventListener("abort", abortPendingFetchRevalidations);
}
revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key));
// If any loaders returned a redirect Response, start a new REPLACE navigation
let redirect = findRedirect(results);
if (redirect) {
if (redirect.idx >= matchesToLoad.length) {
// If this redirect came from a fetcher make sure we mark it in
// fetchRedirectIds so it doesn't get revalidated on the next set of
// loader executions
let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
fetchRedirectIds.add(fetcherKey);
}
await startRedirectNavigation(state, redirect.result, {
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);
}
});
});
let updatedFetchers = markFetchRedirectsDone();
let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
return _extends({
loaderData,
errors
}, shouldUpdateFetchers ? {
fetchers: new Map(state.fetchers)
} : {});
}
// 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 flushSync = (opts && opts.unstable_flushSync) === true;
let routesToUse = inFlightDataRoutes || dataRoutes;
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
let matches = matchRoutes(routesToUse, normalizedPath, basename);
if (!matches) {
setFetcherError(key, routeId, getInternalRouterError(404, {
pathname: normalizedPath
}), {
flushSync
});
return;
}
let {
path,
submission,
error
} = normalizeNavigateOptions(future.v7_normalizeFormMethod, true, normalizedPath, opts);
if (error) {
setFetcherError(key, routeId, error, {
flushSync
});
return;
}
let match = getTargetMatch(matches, path);
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
if (submission && isMutationMethod(submission.formMethod)) {
handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
return;
}
// Store off the match so we can call it's shouldRevalidate on subsequent
// revalidations
fetchLoadMatches.set(key, {
routeId,
path
});
handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
}
// Call the action for the matched fetcher.submit(), and then handle redirects,
// errors, and revalidation
async function handleFetcherAction(key, routeId, path, match, requestMatches, flushSync, submission) {
interruptActiveLoads();
fetchLoadMatches.delete(key);
if (!match.route.action && !match.route.lazy) {
let error = getInternalRouterError(405, {
method: submission.formMethod,
pathname: path,
routeId: routeId
});
setFetcherError(key, routeId, error, {
flushSync
});
return;
}
// Put this fetcher into it's submitting state
let existingFetcher = state.fetchers.get(key);
updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
flushSync
});
// Call the action for the fetcher
let abortController = new AbortController();
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
fetchControllers.set(key, abortController);
let originatingLoadId = incrementingLoadId;
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
if (fetchRequest.signal.aborted) {
// We can delete this so long as we weren't aborted by our own fetcher
// re-submit which would have put _new_ controller is in fetchControllers
if (fetchControllers.get(key) === abortController) {
fetchControllers.delete(key);
}
return;
}
// When using v7_fetcherPersist, we don't want errors bubbling up to the UI
// or redirects processed for unmounted fetchers so we just revert them to
// idle
if (future.v7_fetcherPersist && deletedFetchers.has(key)) {
if (isRedirectResult(actionResult) || isErrorResult(actionResult)) {
updateFetcherState(key, getDoneFetcher(undefined));
return;
}
// Let SuccessResult's fall through for revalidation
} else {
if (isRedirectResult(actionResult)) {
fetchControllers.delete(key);
if (pendingNavigationLoadId > originatingLoadId) {
// A new navigation was kicked off after our action started, so that
// should take precedence over this redirect navigation. We already
// set isRevalidationRequired so all loaders for the new route should
// fire unless opted out via shouldRevalidate
updateFetcherState(key, getDoneFetcher(undefined));
return;
} else {
fetchRedirectIds.add(key);
updateFetcherState(key, getLoadingFetcher(submission));
return startRedirectNavigation(state, actionResult, {
fetcherSubmission: submission
});
}
}
// Process any non-redirect errors thrown
if (isErrorResult(actionResult)) {
setFetcherError(key, routeId, actionResult.error);
return;
}
}
if (isDeferredResult(actionResult)) {
throw getInternalRouterError(400, {
type: "defer-action"
});
}
// 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(init.history, nextLocation, abortController.signal);
let routesToUse = inFlightDataRoutes || dataRoutes;
let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches;
invariant(matches, "Didn't find any matches after fetcher action");
let loadId = ++incrementingLoadId;
fetchReloadIds.set(key, loadId);
let loadFetcher = getLoadingFetcher(submission, actionResult.data);
state.fetchers.set(key, loadFetcher);
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, false, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, {
[match.route.id]: actionResult.data
}, undefined // No need to send through errors since we short circuit above
);
// 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(rf => rf.key !== key).forEach(rf => {
let staleKey = rf.key;
let existingFetcher = state.fetchers.get(staleKey);
let revalidatingFetcher = getLoadingFetcher(undefined, existingFetcher ? existingFetcher.data : undefined);
state.fetchers.set(staleKey, revalidatingFetcher);
if (fetchControllers.has(staleKey)) {
abortFetcher(staleKey);
}
if (rf.controller) {
fetchControllers.set(staleKey, rf.controller);
}
});
updateState({
fetchers: new Map(state.fetchers)
});
let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(rf => abortFetcher(rf.key));
abortController.signal.addEventListener("abort", abortPendingFetchRevalidations);
let {
results,
loaderResults,
fetcherResults
} = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
if (abortController.signal.aborted) {
return;
}
abortController.signal.removeEventListener("abort", abortPendingFetchRevalidations);
fetchReloadIds.delete(key);
fetchControllers.delete(key);
revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));
let redirect = findRedirect(results);
if (redirect) {
if (redirect.idx >= matchesToLoad.length) {
// If this redirect came from a fetcher make sure we mark it in
// fetchRedirectIds so it doesn't get revalidated on the next set of
// loader executions
let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
fetchRedirectIds.add(fetcherKey);
}
return startRedirectNavigation(state, redirect.result);
}
// Process and commit output from loaders
let {
loaderData,
errors
} = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
// Since we let revalidations complete even if the submitting fetcher was
// deleted, only put it back to idle if it hasn't been deleted
if (state.fetchers.has(key)) {
let doneFetcher = getDoneFetcher(actionResult.data);
state.fetchers.set(key, doneFetcher);
}
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({
errors,
loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors),
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, flushSync, submission) {
let existingFetcher = state.fetchers.get(key);
updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {
flushSync
});
// Call the loader for this fetcher route match
let abortController = new AbortController();
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
fetchControllers.set(key, abortController);
let originatingLoadId = incrementingLoadId;
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
// Deferred isn't supported for 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 our 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;
}
// We don't want errors bubbling up or redirects followed for unmounted
// fetchers, so short circuit here if it was removed from the UI
if (deletedFetchers.has(key)) {
updateFetcherState(key, getDoneFetcher(undefined));
return;
}
// If the loader threw a redirect Response, start a new REPLACE navigation
if (isRedirectResult(result)) {
if (pendingNavigationLoadId > originatingLoadId) {
// A new navigation was kicked off after our loader started, so that
// should take precedence over this redirect navigation
updateFetcherState(key, getDoneFetcher(undefined));
return;
} else {
fetchRedirectIds.add(key);
await startRedirectNavigation(state, result);
return;
}
}
// Process any non-redirect errors thrown
if (isErrorResult(result)) {
setFetcherError(key, routeId, result.error);
return;
}
invariant(!isDeferredResult(result), "Unhandled fetcher deferred data");
// Put the fetcher back into an idle state
updateFetcherState(key, getDoneFetcher(result.data));
}
/**
* 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, _temp2) {
let {
submission,
fetcherSubmission,
replace
} = _temp2 === void 0 ? {} : _temp2;
if (redirect.revalidate) {
isRevalidationRequired = true;
}
let redirectLocation = createLocation(state.location, redirect.location, {
_isRedirect: true
});
invariant(redirectLocation, "Expected a location on the redirect navigation");
if (isBrowser) {
let isDocumentReload = false;
if (redirect.reloadDocument) {
// Hard reload if the response contained X-Remix-Reload-Document
isDocumentReload = true;
} else if (ABSOLUTE_URL_REGEX.test(redirect.location)) {
const url = init.history.createURL(redirect.location);
isDocumentReload =
// Hard reload if it's an absolute URL to a new origin
url.origin !== routerWindow.location.origin ||
// Hard reload if it's an absolute URL that does not match our basename
stripBasename(url.pathname, basename) == null;
}
if (isDocumentReload) {
if (replace) {
routerWindow.location.replace(redirect.location);
} else {
routerWindow.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 ? Action.Replace : Action.Push;
// Use the incoming submission if provided, fallback on the active one in
// state.navigation
let {
formMethod,
formAction,
formEncType
} = state.navigation;
if (!submission && !fetcherSubmission && formMethod && formAction && formEncType) {
submission = getSubmissionFromNavigation(state.navigation);
}
// 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
let activeSubmission = submission || fetcherSubmission;
if (redirectPreserveMethodStatusCodes.has(redirect.status) && activeSubmission && isMutationMethod(activeSubmission.formMethod)) {
await startNavigation(redirectHistoryAction, redirectLocation, {
submission: _extends({}, activeSubmission, {
formAction: redirect.location
}),
// Preserve this flag across redirects
preventScrollReset: pendingPreventScrollReset
});
} else {
// If we have a navigation submission, we will preserve it through the
// redirect navigation
let overrideNavigation = getLoadingNavigation(redirectLocation, submission);
await startNavigation(redirectHistoryAction, redirectLocation, {
overrideNavigation,
// Send fetcher submissions through for shouldRevalidate
fetcherSubmission,
// Preserve this flag across redirects
preventScrollReset: pendingPreventScrollReset
});
}
}
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, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath)), ...fetchersToLoad.map(f => {
if (f.matches && f.match && f.controller) {
return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, f.controller.signal), f.match, f.matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath);
} else {
let error = {
type: ResultType.error,
error: getInternalRouterError(404, {
pathname: f.path
})
};
return error;
}
})]);
let loaderResults = results.slice(0, matchesToLoad.length);
let fetcherResults = results.slice(matchesToLoad.length);
await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, loaderResults.map(() => request.signal), false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, fetchersToLoad.map(f => f.controller ? f.controller.signal : null), 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 updateFetcherState(key, fetcher, opts) {
if (opts === void 0) {
opts = {};
}
state.fetchers.set(key, fetcher);
updateState({
fetchers: new Map(state.fetchers)
}, {
flushSync: (opts && opts.flushSync) === true
});
}
function setFetcherError(key, routeId, error, opts) {
if (opts === void 0) {
opts = {};
}
let boundaryMatch = findNearestBoundary(state.matches, routeId);
deleteFetcher(key);
updateState({
errors: {
[boundaryMatch.route.id]: error
},
fetchers: new Map(state.fetchers)
}, {
flushSync: (opts && opts.flushSync) === true
});
}
function getFetcher(key) {
if (future.v7_fetcherPersist) {
activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
// If this fetcher was previously marked for deletion, unmark it since we
// have a new instance
if (deletedFetchers.has(key)) {
deletedFetchers.delete(key);
}
}
return state.fetchers.get(key) || IDLE_FETCHER;
}
function deleteFetcher(key) {
let fetcher = state.fetchers.get(key);
// Don't abort the controller if this is a deletion of a fetcher.submit()
// in it's loading phase since - we don't want to abort the corresponding
// revalidation and want them to complete and land
if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) {
abortFetcher(key);
}
fetchLoadMatches.delete(key);
fetchReloadIds.delete(key);
fetchRedirectIds.delete(key);
deletedFetchers.delete(key);
state.fetchers.delete(key);
}
function deleteFetcherAndUpdateState(key) {
if (future.v7_fetcherPersist) {
let count = (activeFetchers.get(key) || 0) - 1;
if (count <= 0) {
activeFetchers.delete(key);
deletedFetchers.add(key);
} else {
activeFetchers.set(key, count);
}
} else {
deleteFetcher(key);
}
updateState({
fetchers: new Map(state.fetchers)
});
}
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 = getDoneFetcher(fetcher.data);
state.fetchers.set(key, doneFetcher);
}
}
function markFetchRedirectsDone() {
let doneKeys = [];
let updatedFetchers = false;
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);
updatedFetchers = true;
}
}
markFetchersDone(doneKeys);
return updatedFetchers;
}
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 getBlocker(key, fn) {
let blocker = state.blockers.get(key) || IDLE_BLOCKER;
if (blockerFunctions.get(key) !== fn) {
blockerFunctions.set(key, fn);
}
return blocker;
}
function deleteBlocker(key) {
state.blockers.delete(key);
blockerFunctions.delete(key);
}
// Utility function to update blockers, ensuring valid state transitions
function updateBlocker(key, newBlocker) {
let blocker = state.blockers.get(key) || IDLE_BLOCKER;
// Poor mans state machine :)
// https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM
invariant(blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", "Invalid blocker state transition: " + blocker.state + " -> " + newBlocker.state);
let blockers = new Map(state.blockers);
blockers.set(key, newBlocker);
updateState({
blockers
});
}
function shouldBlockNavigation(_ref2) {
let {
currentLocation,
nextLocation,
historyAction
} = _ref2;
if (blockerFunctions.size === 0) {
return;
}
// We ony support a single active blocker at the moment since we don't have
// any compelling use cases for multi-blocker yet
if (blockerFunctions.size > 1) {
warning(false, "A router only supports one blocker at a time");
}
let entries = Array.from(blockerFunctions.entries());
let [blockerKey, blockerFunction] = entries[entries.length - 1];
let blocker = state.blockers.get(blockerKey);
if (blocker && blocker.state === "proceeding") {
// If the blocker is currently proceeding, we don't need to re-check
// it and can let this navigation continue
return;
}
// At this point, we know we're unblocked/blocked so we need to check the
// user-provided blocker function
if (blockerFunction({
currentLocation,
nextLocation,
historyAction
})) {
return blockerKey;
}
}
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 || null;
// 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 getScrollKey(location, matches) {
if (getScrollRestorationKey) {
let key = getScrollRestorationKey(location, matches.map(m => convertRouteMatchToUiMatch(m, state.loaderData)));
return key || location.key;
}
return location.key;
}
function saveScrollPosition(location, matches) {
if (savedScrollPositions && getScrollPosition) {
let key = getScrollKey(location, matches);
savedScrollPositions[key] = getScrollPosition();
}
}
function getSavedScrollPosition(location, matches) {
if (savedScrollPositions) {
let key = getScrollKey(location, matches);
let y = savedScrollPositions[key];
if (typeof y === "number") {
return y;
}
}
return null;
}
function _internalSetRoutes(newRoutes) {
manifest = {};
inFlightDataRoutes = convertRoutesToDataRoutes(newRoutes, mapRouteProperties, undefined, manifest);
}
router = {
get basename() {
return basename;
},
get future() {
return future;
},
get state() {
return state;
},
get routes() {
return dataRoutes;
},
get window() {
return routerWindow;
},
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: deleteFetcherAndUpdateState,
dispose,
getBlocker,
deleteBlocker,
_internalFetchControllers: fetchControllers,
_internalActiveDeferreds: activeDeferreds,
// TODO: Remove setRoutes, it's temporary to avoid dealing with
// updating the tree while validating the update algorithm.
_internalSetRoutes
};
return router;
}
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region createStaticHandler
////////////////////////////////////////////////////////////////////////////////
const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
function createStaticHandler(routes, opts) {
invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
let manifest = {};
let basename = (opts ? opts.basename : null) || "/";
let mapRouteProperties;
if (opts != null && opts.mapRouteProperties) {
mapRouteProperties = opts.mapRouteProperties;
} else if (opts != null && opts.detectErrorBoundary) {
// If they are still using the deprecated version, wrap it with the new API
let detectErrorBoundary = opts.detectErrorBoundary;
mapRouteProperties = route => ({
hasErrorBoundary: detectErrorBoundary(route)
});
} else {
mapRouteProperties = defaultMapRouteProperties;
}
// Config driven behavior flags
let future = _extends({
v7_relativeSplatPath: false
}, opts ? opts.future : null);
let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);
/**
* 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, _temp3) {
let {
requestContext
} = _temp3 === void 0 ? {} : _temp3;
let url = new URL(request.url);
let method = request.method;
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: {},
activeDeferreds: null
};
} 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: {},
activeDeferreds: null
};
}
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, _temp4) {
let {
routeId,
requestContext
} = _temp4 === void 0 ? {} : _temp4;
let url = new URL(request.url);
let method = request.method;
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" && method !== "OPTIONS") {
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
if (result.actionData) {
return Object.values(result.actionData)[0];
}
if (result.loaderData) {
var _result$activeDeferre;
let data = Object.values(result.loaderData)[0];
if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) {
data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];
}
return data;
}
return undefined;
}
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) {
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 && !actionMatch.route.lazy) {
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, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
isStaticRequest: true,
isRouteRequest,
requestContext
});
if (request.signal.aborted) {
let method = isRouteRequest ? "queryRoute" : "query";
throw new Error(method + "() call aborted: " + request.method + " " + request.url);
}
}
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)) {
let error = getInternalRouterError(400, {
type: "defer-action"
});
if (isRouteRequest) {
throw error;
}
result = {
type: ResultType.error,
error
};
}
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: {},
activeDeferreds: null
};
}
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) && !(routeMatch != null && routeMatch.route.lazy)) {
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 || m.route.lazy);
// 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: {},
activeDeferreds: null
};
}
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, future.v7_relativeSplatPath, {
isStaticRequest: true,
isRouteRequest,
requestContext
}))]);
if (request.signal.aborted) {
let method = isRouteRequest ? "queryRoute" : "query";
throw new Error(method + "() call aborted: " + request.method + " " + request.url);
}
// Process and commit output from loaders
let activeDeferreds = new Map();
let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds);
// Add a null for any non-loader matches for proper revalidation on the client
let executedLoaders = new Set(matchesToLoad.map(match => match.route.id));
matches.forEach(match => {
if (!executedLoaders.has(match.route.id)) {
context.loaderData[match.route.id] = null;
}
});
return _extends({}, context, {
matches,
activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null
});
}
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 && opts.formData != null || "body" in opts && opts.body !== undefined);
}
function normalizeTo(location, matches, basename, prependBasename, to, v7_relativeSplatPath, fromRouteId, relative) {
let contextualMatches;
let activeRouteMatch;
if (fromRouteId) {
// Grab matches up to the calling route so our route-relative logic is
// relative to the correct source route
contextualMatches = [];
for (let match of matches) {
contextualMatches.push(match);
if (match.route.id === fromRouteId) {
activeRouteMatch = match;
break;
}
}
} else {
contextualMatches = matches;
activeRouteMatch = matches[matches.length - 1];
}
// Resolve the relative path
let path = resolveTo(to ? to : ".", getResolveToMatches(contextualMatches, v7_relativeSplatPath), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
// When `to` is not specified we inherit search/hash from the current
// location, unlike when to="." and we just inherit the path.
// See https://github.com/remix-run/remix/issues/927
if (to == null) {
path.search = location.search;
path.hash = location.hash;
}
// Add an ?index param for matched index routes if we don't already have one
if ((to == null || to === "" || to === ".") && activeRouteMatch && activeRouteMatch.route.index && !hasNakedIndexQuery(path.search)) {
path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
}
// If we're operating within a basename, prepend it to the pathname. If
// this is a root navigation, then just use the raw basename which allows
// the basename to have full control over the presence of a trailing slash
// on root actions
if (prependBasename && basename !== "/") {
path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
}
return createPath(path);
}
// Normalize navigation options by converting formMethod=GET formData objects to
// URLSearchParams so they behave identically to links with query params
function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
// 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
})
};
}
let getInvalidBodyError = () => ({
path,
error: getInternalRouterError(400, {
type: "invalid-body"
})
});
// Create a Submission on non-GET navigations
let rawFormMethod = opts.formMethod || "get";
let formMethod = normalizeFormMethod ? rawFormMethod.toUpperCase() : rawFormMethod.toLowerCase();
let formAction = stripHashFromPath(path);
if (opts.body !== undefined) {
if (opts.formEncType === "text/plain") {
// text only support POST/PUT/PATCH/DELETE submissions
if (!isMutationMethod(formMethod)) {
return getInvalidBodyError();
}
let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ?
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
Array.from(opts.body.entries()).reduce((acc, _ref3) => {
let [name, value] = _ref3;
return "" + acc + name + "=" + value + "\n";
}, "") : String(opts.body);
return {
path,
submission: {
formMethod,
formAction,
formEncType: opts.formEncType,
formData: undefined,
json: undefined,
text
}
};
} else if (opts.formEncType === "application/json") {
// json only supports POST/PUT/PATCH/DELETE submissions
if (!isMutationMethod(formMethod)) {
return getInvalidBodyError();
}
try {
let json = typeof opts.body === "string" ? JSON.parse(opts.body) : opts.body;
return {
path,
submission: {
formMethod,
formAction,
formEncType: opts.formEncType,
formData: undefined,
json,
text: undefined
}
};
} catch (e) {
return getInvalidBodyError();
}
}
}
invariant(typeof FormData === "function", "FormData is not available in this environment");
let searchParams;
let formData;
if (opts.formData) {
searchParams = convertFormDataToSearchParams(opts.formData);
formData = opts.formData;
} else if (opts.body instanceof FormData) {
searchParams = convertFormDataToSearchParams(opts.body);
formData = opts.body;
} else if (opts.body instanceof URLSearchParams) {
searchParams = opts.body;
formData = convertSearchParamsToFormData(searchParams);
} else if (opts.body == null) {
searchParams = new URLSearchParams();
formData = new FormData();
} else {
try {
searchParams = new URLSearchParams(opts.body);
formData = convertSearchParamsToFormData(searchParams);
} catch (e) {
return getInvalidBodyError();
}
}
let submission = {
formMethod,
formAction,
formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
formData,
json: undefined,
text: undefined
};
if (isMutationMethod(submission.formMethod)) {
return {
path,
submission
};
}
// Flatten submission onto URLSearchParams for GET submissions
let parsedPath = parsePath(path);
// On GET navigation submissions we can drop the ?index param from the
// resulting location since all loaders will run. But fetcher GET submissions
// only run a single loader so we need to preserve any incoming ?index params
if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
searchParams.append("index", "");
}
parsedPath.search = "?" + searchParams;
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(history, state, matches, submission, location, isInitialLoad, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionData, pendingError) {
let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
let currentUrl = history.createURL(state.location);
let nextUrl = history.createURL(location);
// 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) => {
let {
route
} = match;
if (route.lazy) {
// We haven't loaded this route yet so we don't know if it's got a loader!
return true;
}
if (route.loader == null) {
return false;
}
if (isInitialLoad) {
if (route.loader.hydrate) {
return true;
}
return state.loaderData[route.id] === undefined && (
// Don't re-run if the loader ran and threw an error
!state.errors || state.errors[route.id] === undefined);
}
// Always call the loader on new route instances and pending defer cancellations
if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) {
return true;
}
// This is the default implementation for 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
let currentRouteMatch = state.matches[index];
let nextRouteMatch = match;
return shouldRevalidateLoader(match, _extends({
currentUrl,
currentParams: currentRouteMatch.params,
nextUrl,
nextParams: nextRouteMatch.params
}, submission, {
actionResult,
defaultShouldRevalidate:
// Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
isRevalidationRequired ||
// Clicked the same link, resubmitted a GET form
currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search ||
// Search params affect all loaders
currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch)
}));
});
// Pick fetcher.loads that need to be revalidated
let revalidatingFetchers = [];
fetchLoadMatches.forEach((f, key) => {
// Don't revalidate:
// - on initial load (shouldn't be any fetchers then anyway)
// - if fetcher won't be present in the subsequent render
// - no longer matches the URL (v7_fetcherPersist=false)
// - was unmounted but persisted due to v7_fetcherPersist=true
if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
return;
}
let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
// If the fetcher path no longer matches, push it in with null matches so
// we can trigger a 404 in callLoadersAndMaybeResolveData. Note this is
// currently only a use-case for Remix HMR where the route tree can change
// at runtime and remove a route previously loaded via a fetcher
if (!fetcherMatches) {
revalidatingFetchers.push({
key,
routeId: f.routeId,
path: f.path,
matches: null,
match: null,
controller: null
});
return;
}
// Revalidating fetchers are decoupled from the route matches since they
// load from a static href. They revalidate based on explicit revalidation
// (submission, useRevalidator, or X-Remix-Revalidate)
let fetcher = state.fetchers.get(key);
let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
let shouldRevalidate = false;
if (fetchRedirectIds.has(key)) {
// Never trigger a revalidation of an actively redirecting fetcher
shouldRevalidate = false;
} else if (cancelledFetcherLoads.includes(key)) {
// Always revalidate if the fetcher was cancelled
shouldRevalidate = true;
} else if (fetcher && fetcher.state !== "idle" && fetcher.data === undefined) {
// If the fetcher hasn't ever completed loading yet, then this isn't a
// revalidation, it would just be a brand new load if an explicit
// revalidation is required
shouldRevalidate = isRevalidationRequired;
} else {
// Otherwise fall back on any user-defined shouldRevalidate, defaulting
// to explicit revalidations only
shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({
currentUrl,
currentParams: state.matches[state.matches.length - 1].params,
nextUrl,
nextParams: matches[matches.length - 1].params
}, submission, {
actionResult,
defaultShouldRevalidate: isRevalidationRequired
}));
}
if (shouldRevalidate) {
revalidatingFetchers.push({
key,
routeId: f.routeId,
path: f.path,
matches: fetcherMatches,
match: fetcherMatch,
controller: new AbortController()
});
}
});
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 != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
);
}
function shouldRevalidateLoader(loaderMatch, arg) {
if (loaderMatch.route.shouldRevalidate) {
let routeChoice = loaderMatch.route.shouldRevalidate(arg);
if (typeof routeChoice === "boolean") {
return routeChoice;
}
}
return arg.defaultShouldRevalidate;
}
/**
* Execute route.lazy() methods to lazily load route modules (loader, action,
* shouldRevalidate) and update the routeManifest in place which shares objects
* with dataRoutes so those get updated as well.
*/
async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
if (!route.lazy) {
return;
}
let lazyRoute = await route.lazy();
// If the lazy route function was executed and removed by another parallel
// call then we can return - first lazy() to finish wins because the return
// value of lazy is expected to be static
if (!route.lazy) {
return;
}
let routeToUpdate = manifest[route.id];
invariant(routeToUpdate, "No route found in manifest");
// Update the route in place. This should be safe because there's no way
// we could yet be sitting on this route as we can't get there without
// resolving lazy() first.
//
// This is different than the HMR "update" use-case where we may actively be
// on the route being updated. The main concern boils down to "does this
// mutation affect any ongoing navigations or any current state.matches
// values?". If not, it should be safe to update in place.
let routeUpdates = {};
for (let lazyRouteProperty in lazyRoute) {
let staticRouteValue = routeToUpdate[lazyRouteProperty];
let isPropertyStaticallyDefined = staticRouteValue !== undefined &&
// This property isn't static since it should always be updated based
// on the route updates
lazyRouteProperty !== "hasErrorBoundary";
warning(!isPropertyStaticallyDefined, "Route \"" + routeToUpdate.id + "\" has a static property \"" + lazyRouteProperty + "\" " + "defined but its lazy function is also returning a value for this property. " + ("The lazy route property \"" + lazyRouteProperty + "\" will be ignored."));
if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) {
routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty];
}
}
// Mutate the route with the provided updates. Do this first so we pass
// the updated version to mapRouteProperties
Object.assign(routeToUpdate, routeUpdates);
// Mutate the `hasErrorBoundary` property on the route based on the route
// updates and remove the `lazy` function so we don't resolve the lazy
// route again.
Object.assign(routeToUpdate, _extends({}, mapRouteProperties(routeToUpdate), {
lazy: undefined
}));
}
async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, v7_relativeSplatPath, opts) {
if (opts === void 0) {
opts = {};
}
let resultType;
let result;
let onReject;
let runHandler = handler => {
// Setup a promise we can race against so that abort signals short circuit
let reject;
let abortPromise = new Promise((_, r) => reject = r);
onReject = () => reject();
request.signal.addEventListener("abort", onReject);
return Promise.race([handler({
request,
params: match.params,
context: opts.requestContext
}), abortPromise]);
};
try {
let handler = match.route[type];
if (match.route.lazy) {
if (handler) {
// Run statically defined handler in parallel with lazy()
let handlerError;
let values = await Promise.all([
// If the handler throws, don't let it immediately bubble out,
// since we need to let the lazy() execution finish so we know if this
// route has a boundary that can handle the error
runHandler(handler).catch(e => {
handlerError = e;
}), loadLazyRouteModule(match.route, mapRouteProperties, manifest)]);
if (handlerError) {
throw handlerError;
}
result = values[0];
} else {
// Load lazy route module, then run any returned handler
await loadLazyRouteModule(match.route, mapRouteProperties, manifest);
handler = match.route[type];
if (handler) {
// Handler still run even if we got interrupted to maintain consistency
// with un-abortable behavior of handler execution on non-lazy or
// previously-lazy-loaded routes
result = await runHandler(handler);
} else if (type === "action") {
let url = new URL(request.url);
let pathname = url.pathname + url.search;
throw getInternalRouterError(405, {
method: request.method,
pathname,
routeId: match.route.id
});
} else {
// lazy() route has no loader to run. Short circuit here so we don't
// hit the invariant below that errors on returning undefined.
return {
type: ResultType.data,
data: undefined
};
}
}
} else if (!handler) {
let url = new URL(request.url);
let pathname = url.pathname + url.search;
throw getInternalRouterError(404, {
pathname
});
} else {
result = await runHandler(handler);
}
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 {
if (onReject) {
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");
// Support relative routing in internal redirects
if (!ABSOLUTE_URL_REGEX.test(location)) {
location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location, v7_relativeSplatPath);
} else if (!opts.isStaticRequest) {
// Strip off the protocol+origin for same-origin + same-basename absolute
// redirects. If this is a static request, we can let it go back to the
// browser as-is
let currentUrl = new URL(request.url);
let url = location.startsWith("//") ? new URL(currentUrl.protocol + location) : new URL(location);
let isSameBasename = stripBasename(url.pathname, basename) != null;
if (url.origin === currentUrl.origin && isSameBasename) {
location = url.pathname + url.search + url.hash;
}
}
// 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 (opts.isStaticRequest) {
result.headers.set("Location", location);
throw result;
}
return {
type: ResultType.redirect,
status,
location,
revalidate: result.headers.get("X-Remix-Revalidate") !== null,
reloadDocument: result.headers.get("X-Remix-Reload-Document") !== 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 (opts.isRouteRequest) {
let queryRouteResponse = {
type: resultType === ResultType.error ? ResultType.error : ResultType.data,
response: result
};
throw queryRouteResponse;
}
let data;
try {
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();
}
} catch (e) {
return {
type: ResultType.error,
error: e
};
}
if (resultType === ResultType.error) {
return {
type: resultType,
error: new ErrorResponseImpl(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 (isDeferredData(result)) {
var _result$init, _result$init2;
return {
type: ResultType.deferred,
deferredData: result,
statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status,
headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers)
};
}
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(history, location, signal, submission) {
let url = history.createURL(stripHashFromPath(location)).toString();
let init = {
signal
};
if (submission && isMutationMethod(submission.formMethod)) {
let {
formMethod,
formEncType
} = submission;
// Didn't think we needed this but it turns out unlike other methods, patch
// won't be properly normalized to uppercase and results in a 405 error.
// See: https://fetch.spec.whatwg.org/#concept-method
init.method = formMethod.toUpperCase();
if (formEncType === "application/json") {
init.headers = new Headers({
"Content-Type": formEncType
});
init.body = JSON.stringify(submission.json);
} else if (formEncType === "text/plain") {
// Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
init.body = submission.text;
} else if (formEncType === "application/x-www-form-urlencoded" && submission.formData) {
// Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
init.body = convertFormDataToSearchParams(submission.formData);
} else {
// Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
init.body = submission.formData;
}
}
return new Request(url, init);
}
function convertFormDataToSearchParams(formData) {
let searchParams = new URLSearchParams();
for (let [key, value] of formData.entries()) {
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs
searchParams.append(key, typeof value === "string" ? value : value.name);
}
return searchParams;
}
function convertSearchParamsToFormData(searchParams) {
let formData = new FormData();
for (let [key, value] of searchParams.entries()) {
formData.append(key, value);
}
return formData;
}
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.set(id, result.deferredData);
loaderData[id] = result.deferredData.data;
} 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,
controller
} = revalidatingFetchers[index];
invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result");
let result = fetcherResults[index];
// Process fetcher non-redirect errors
if (controller && controller.signal.aborted) {
// Nothing to do for aborted fetchers
continue;
} else if (isErrorResult(result)) {
let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : 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
invariant(false, "Unhandled fetcher revalidation redirect");
} else if (isDeferredResult(result)) {
// Should never get here, deferred data should be awaited for fetchers
// in resolveDeferredResults
invariant(false, "Unhandled fetcher deferred data");
} else {
let doneFetcher = getDoneFetcher(result.data);
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 && match.route.loader) {
// Preserve existing keys not included in newLoaderData and where a loader
// wasn't removed by HMR
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.length === 1 ? routes[0] : routes.find(r => r.index || !r.path || r.path === "/") || {
id: "__shim-error-route__"
};
return {
matches: [{
params: {},
pathname: "",
pathnameBase: "",
route
}],
route
};
}
function getInternalRouterError(status, _temp5) {
let {
pathname,
routeId,
method,
type
} = _temp5 === void 0 ? {} : _temp5;
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 if (type === "defer-action") {
errorMessage = "defer() is not supported in actions";
} else if (type === "invalid-body") {
errorMessage = "Unable to encode submission body";
}
} 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 ErrorResponseImpl(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,
idx: i
};
}
}
}
function stripHashFromPath(path) {
let parsedPath = typeof path === "string" ? parsePath(path) : path;
return createPath(_extends({}, parsedPath, {
hash: ""
}));
}
function isHashChangeOnly(a, b) {
if (a.pathname !== b.pathname || a.search !== b.search) {
return false;
}
if (a.hash === "") {
// /page -> /page#hash
return b.hash !== "";
} else if (a.hash === b.hash) {
// /page#hash -> /page#hash
return true;
} else if (b.hash !== "") {
// /page#hash -> /page#other
return true;
}
// If the hash is removed the browser will re-perform a request to the server
// /page#hash -> /page
return false;
}
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 isDeferredData(value) {
let deferred = value;
return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function";
}
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 || obj.type === ResultType.error);
}
function isValidMethod(method) {
return validRequestMethods.has(method.toLowerCase());
}
function isMutationMethod(method) {
return validMutationMethods.has(method.toLowerCase());
}
async function resolveDeferredResults(currentMatches, matchesToLoad, results, signals, isFetcher, currentLoaderData) {
for (let index = 0; index < results.length; index++) {
let result = results[index];
let match = matchesToLoad[index];
// If we don't have a match, then we can have a deferred result to do
// anything with. This is for revalidating fetchers where the route was
// removed during HMR
if (!match) {
continue;
}
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
let signal = signals[index];
invariant(signal, "Expected an AbortSignal for revalidating fetcher deferred result");
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 === "");
}
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];
}
function getSubmissionFromNavigation(navigation) {
let {
formMethod,
formAction,
formEncType,
text,
formData,
json
} = navigation;
if (!formMethod || !formAction || !formEncType) {
return;
}
if (text != null) {
return {
formMethod,
formAction,
formEncType,
formData: undefined,
json: undefined,
text
};
} else if (formData != null) {
return {
formMethod,
formAction,
formEncType,
formData,
json: undefined,
text: undefined
};
} else if (json !== undefined) {
return {
formMethod,
formAction,
formEncType,
formData: undefined,
json,
text: undefined
};
}
}
function getLoadingNavigation(location, submission) {
if (submission) {
let navigation = {
state: "loading",
location,
formMethod: submission.formMethod,
formAction: submission.formAction,
formEncType: submission.formEncType,
formData: submission.formData,
json: submission.json,
text: submission.text
};
return navigation;
} else {
let navigation = {
state: "loading",
location,
formMethod: undefined,
formAction: undefined,
formEncType: undefined,
formData: undefined,
json: undefined,
text: undefined
};
return navigation;
}
}
function getSubmittingNavigation(location, submission) {
let navigation = {
state: "submitting",
location,
formMethod: submission.formMethod,
formAction: submission.formAction,
formEncType: submission.formEncType,
formData: submission.formData,
json: submission.json,
text: submission.text
};
return navigation;
}
function getLoadingFetcher(submission, data) {
if (submission) {
let fetcher = {
state: "loading",
formMethod: submission.formMethod,
formAction: submission.formAction,
formEncType: submission.formEncType,
formData: submission.formData,
json: submission.json,
text: submission.text,
data
};
return fetcher;
} else {
let fetcher = {
state: "loading",
formMethod: undefined,
formAction: undefined,
formEncType: undefined,
formData: undefined,
json: undefined,
text: undefined,
data
};
return fetcher;
}
}
function getSubmittingFetcher(submission, existingFetcher) {
let fetcher = {
state: "submitting",
formMethod: submission.formMethod,
formAction: submission.formAction,
formEncType: submission.formEncType,
formData: submission.formData,
json: submission.json,
text: submission.text,
data: existingFetcher ? existingFetcher.data : undefined
};
return fetcher;
}
function getDoneFetcher(data) {
let fetcher = {
state: "idle",
formMethod: undefined,
formAction: undefined,
formEncType: undefined,
formData: undefined,
json: undefined,
text: undefined,
data
};
return fetcher;
}
function restoreAppliedTransitions(_window, transitions) {
try {
let sessionPositions = _window.sessionStorage.getItem(TRANSITIONS_STORAGE_KEY);
if (sessionPositions) {
let json = JSON.parse(sessionPositions);
for (let [k, v] of Object.entries(json || {})) {
if (v && Array.isArray(v)) {
transitions.set(k, new Set(v || []));
}
}
}
} catch (e) {
// no-op, use default empty object
}
}
function persistAppliedTransitions(_window, transitions) {
if (transitions.size > 0) {
let json = {};
for (let [k, v] of transitions) {
json[k] = [...v];
}
try {
_window.sessionStorage.setItem(TRANSITIONS_STORAGE_KEY, JSON.stringify(json));
} catch (error) {
warning(false, "Failed to save applied view transitions in sessionStorage (" + error + ").");
}
}
}
//#endregion
//# sourceMappingURL=router.js.map
/***/ }),
/***/ "./node_modules/@wordpress/icons/build-module/icon/index.js":
/*!******************************************************************!*\
!*** ./node_modules/@wordpress/icons/build-module/icon/index.js ***!
\******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);
/**
* WordPress dependencies
*/
/** @typedef {{icon: JSX.Element, size?: number} & import('@wordpress/primitives').SVGProps} IconProps */
/**
* Return an SVG icon.
*
* @param {IconProps} props icon is the SVG component to render
* size is a number specifiying the icon size in pixels
* Other props will be passed to wrapped SVG component
* @param {import('react').ForwardedRef<HTMLElement>} ref The forwarded ref to the SVG element.
*
* @return {JSX.Element} Icon component
*/
function Icon({
icon,
size = 24,
...props
}, ref) {
return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.cloneElement)(icon, {
width: size,
height: size,
...props,
ref
});
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(Icon));
//# sourceMappingURL=index.js.map
/***/ }),
/***/ "./node_modules/@wordpress/icons/build-module/library/close.js":
/*!*********************************************************************!*\
!*** ./node_modules/@wordpress/icons/build-module/library/close.js ***!
\*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/primitives */ "@wordpress/primitives");
/* harmony import */ var _wordpress_primitives__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__);
/**
* WordPress dependencies
*/
const close = (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__.SVG, {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__.Path, {
d: "M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"
}));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (close);
//# sourceMappingURL=close.js.map
/***/ }),
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _panel_scss_style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./panel/scss/style.scss */ "./src/panel/scss/style.scss");
/* harmony import */ var _panel_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./panel/panel */ "./src/panel/panel.js");
/* harmony import */ var _modal_DeviaModal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modal/DeviaModal */ "./src/modal/DeviaModal.js");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_4__);
const rootElement = document.getElementById('devia-welcome');
if (rootElement) {
(0,_wordpress_element__WEBPACK_IMPORTED_MODULE_4__.createRoot)(rootElement).render((0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_panel_panel__WEBPACK_IMPORTED_MODULE_2__["default"], null));
}
if (devia_options.screen == 'modal') {
let modal = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_4__.createRoot)(document.getElementById('devia-modal'));
modal.render((0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_modal_DeviaModal__WEBPACK_IMPORTED_MODULE_3__["default"], null));
}
/***/ }),
/***/ "./src/modal/DeviaModal.js":
/*!*********************************!*\
!*** ./src/modal/DeviaModal.js ***!
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _OnboardingModal__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OnboardingModal */ "./src/modal/OnboardingModal.jsx");
function DeviaModal() {
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_OnboardingModal__WEBPACK_IMPORTED_MODULE_1__["default"], null);
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DeviaModal);
/***/ }),
/***/ "./src/modal/OnboardingModal.jsx":
/*!***************************************!*\
!*** ./src/modal/OnboardingModal.jsx ***!
\***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/api-fetch */ "@wordpress/api-fetch");
/* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _wordpress_icons__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/icons */ "./node_modules/@wordpress/icons/build-module/icon/index.js");
/* harmony import */ var _wordpress_icons__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @wordpress/icons */ "./node_modules/@wordpress/icons/build-module/library/close.js");
const {
__
} = wp.i18n;
function OnboardingModal() {
const [skipOnboarding, setSkipOnboarding] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_3__.useState)(false);
const canSkipOnboarding = skip => {
_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({
path: '/devia/v1/skip-onboarding',
method: 'POST'
}).then(response => {
setSkipOnboarding(true);
if (!skip) {
window.location.href = devia_options.dashboard_link;
setSkipOnboarding(true);
}
});
};
(0,_wordpress_element__WEBPACK_IMPORTED_MODULE_3__.useEffect)(() => {
if (devia_options.theme_options.skip_onboarding) {
setSkipOnboarding(true);
}
const handleEsc = event => {
if (event.key === 'Escape') {
canSkipOnboarding(true);
}
};
window.addEventListener('keydown', handleEsc);
return () => {
window.removeEventListener('keydown', handleEsc);
};
}, []);
if (skipOnboarding) {
return null;
}
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "devia-modal-background"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "devia-modal-content"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Button, {
onClick: () => canSkipOnboarding(true),
className: "devia-modal-close"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_icons__WEBPACK_IMPORTED_MODULE_4__["default"], {
icon: _wordpress_icons__WEBPACK_IMPORTED_MODULE_5__["default"]
})), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("h2", null, __(`Welcome to ${devia_options.name}!`, devia_options.text_domain)), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("p", null, __(`Visit the ${devia_options.name} Dashboard and Theme Setup Wizard (Admin Dashboard → ${devia_options.name} Theme) to get your site set up with just a few clicks. Head over there to get started!`, devia_options.text_domain)), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Flex, {
className: "devia-modal-inner",
justify: "center",
align: "center",
direction: "column",
gap: "3"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("iframe", {
width: "600",
height: "305",
src: devia_options.theme_params.video_tutorial,
title: "YouTube video player",
frameborder: "0",
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
referrerpolicy: "strict-origin-when-cross-origin",
allowfullscreen: ""
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Button, {
variant: "primary",
onClick: () => canSkipOnboarding(false)
}, __(`View ${devia_options.name} Dashboard →`, devia_options.text_domain)))));
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OnboardingModal);
/***/ }),
/***/ "./src/panel/components/Loading.jsx":
/*!******************************************!*\
!*** ./src/panel/components/Loading.jsx ***!
\******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
const Loading = () => {
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "panel-loading"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 200 200"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("radialGradient", {
id: "a11",
cx: ".66",
fx: ".66",
cy: ".3125",
fy: ".3125",
gradientTransform: "scale(1.5)"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("stop", {
offset: "0",
"stop-color": "#2145e6"
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("stop", {
offset: ".3",
"stop-color": "#2145e6",
"stop-opacity": ".9"
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("stop", {
offset: ".6",
"stop-color": "#2145e6",
"stop-opacity": ".6"
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("stop", {
offset: ".8",
"stop-color": "#2145e6",
"stop-opacity": ".3"
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("stop", {
offset: "1",
"stop-color": "#2145e6",
"stop-opacity": "0"
})), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("circle", {
"transform-origin": "center",
fill: "none",
stroke: "url(#a11)",
"stroke-width": "15",
"stroke-linecap": "round",
"stroke-dasharray": "200 1000",
"stroke-dashoffset": "0",
cx: "100",
cy: "100",
r: "70"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("animateTransform", {
type: "rotate",
attributeName: "transform",
calcMode: "spline",
dur: "2",
values: "360;0",
keyTimes: "0;1",
keySplines: "0 0 1 1",
repeatCount: "indefinite"
})), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("circle", {
"transform-origin": "center",
fill: "none",
opacity: ".2",
stroke: "#2145e6",
"stroke-width": "15",
"stroke-linecap": "round",
cx: "100",
cy: "100",
r: "70"
})));
};
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Loading);
/***/ }),
/***/ "./src/panel/components/main/PanelPage.jsx":
/*!*************************************************!*\
!*** ./src/panel/components/main/PanelPage.jsx ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _Loading__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Loading */ "./src/panel/components/Loading.jsx");
/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-router-dom */ "./node_modules/react-router/dist/index.js");
/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ "./node_modules/react-router-dom/dist/index.js");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_2__);
const Welcome = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_welcome_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/welcome */ "./src/panel/pages/welcome.jsx")));
const Documentation = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_documentation_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/documentation */ "./src/panel/pages/documentation.jsx")));
const ThemeOptions = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => Promise.all(/*! import() */[__webpack_require__.e("vendors-node_modules_axios_lib_axios_js"), __webpack_require__.e("src_panel_pages_theme-options_jsx")]).then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/theme-options */ "./src/panel/pages/theme-options.jsx")));
const ThemeActivation = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_theme-activation_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/theme-activation */ "./src/panel/pages/theme-activation.jsx")));
const DemoImport = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => Promise.all(/*! import() */[__webpack_require__.e("vendors-node_modules_reactjs-popup_dist_reactjs-popup_esm_js"), __webpack_require__.e("src_panel_pages_demo-import_jsx")]).then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/demo-import */ "./src/panel/pages/demo-import.jsx")));
const NotFound = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_not-found_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/not-found */ "./src/panel/pages/not-found.jsx")));
const General = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_options_general_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/options/general */ "./src/panel/pages/options/general.jsx")));
const Colors = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_options_colors_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/options/colors */ "./src/panel/pages/options/colors.jsx")));
const Fonts = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_options_fonts_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/options/fonts */ "./src/panel/pages/options/fonts.jsx")));
const Blog = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_options_blog_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/options/blog */ "./src/panel/pages/options/blog.jsx")));
const Shop = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_options_shop_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/options/shop */ "./src/panel/pages/options/shop.jsx")));
const Footer = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_pages_options_footer_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../pages/options/footer */ "./src/panel/pages/options/footer.jsx")));
const Navigation = (0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(() => __webpack_require__.e(/*! import() */ "src_panel_components_Navigation_jsx").then(__webpack_require__.bind(__webpack_require__, /*! ../../components/Navigation */ "./src/panel/components/Navigation.jsx")));
const {
__
} = wp.i18n;
function PanelPage() {
let pages = [{
title: __('Welcome Page', devia_options.text_domain),
slug: 'welcome-page',
icon: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24" height="24" aria-hidden="true" focusable="false" style="fill: currentcolor;"><path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 14.5c-3.6 0-6.5-2.9-6.5-6.5S8.4 5.5 12 5.5s6.5 2.9 6.5 6.5-2.9 6.5-6.5 6.5zM9 16l4.5-3L15 8.4l-4.5 3L9 16z"></path></svg>'
}, {
title: __('Theme Activation'),
slug: 'theme-activation',
icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false" style="fill: currentcolor;"><path d="M7 5.5h10a.5.5 0 01.5.5v12a.5.5 0 01-.5.5H7a.5.5 0 01-.5-.5V6a.5.5 0 01.5-.5zM17 4H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V6a2 2 0 00-2-2zm-1 3.75H8v1.5h8v-1.5zM8 11h8v1.5H8V11zm6 3.25H8v1.5h6v-1.5z"></path></svg>'
}, {
title: __('Documentation'),
slug: 'documentation',
icon: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24" height="24" aria-hidden="true" focusable="false" style="fill: currentcolor;"><path d="M12 4c-4.4 0-8 3.6-8 8v.1c0 4.1 3.2 7.5 7.2 7.9h.8c4.4 0 8-3.6 8-8s-3.6-8-8-8zm0 15V5c3.9 0 7 3.1 7 7s-3.1 7-7 7z"></path></svg>'
}];
const [isPurchase, setIsPurchase] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useState)(devia_options.is_theme_active.data);
const [menuOptions, setMenuOptions] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useState)([]);
const location = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_3__.useLocation)();
const navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_3__.useNavigate)();
const currentRouteIndex = menuOptions.findIndex(route => `/${route?.slug}` === location.pathname);
const currentPath = location.pathname;
const currentDepth = currentPath.split('/').filter(Boolean).length;
const panel_fields = JSON.parse(devia_options.theme_options.fields) ? JSON.parse(devia_options.theme_options.fields) : [];
(0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useEffect)(async () => {
if (location.pathname == '/') {
navigate(`/welcome-page`);
}
setMenuOptions(pages);
await checkIsPurchase();
}, []);
(0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useEffect)(() => {
if (!isPurchase.active && menuOptions.length > 4) {
setMenuOptions(pages);
}
if (isPurchase.active) {
pages.splice(2, 0, {
title: __('Demo Import'),
slug: 'demo-import',
icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false" style="fill: currentcolor;"><path d="M18 5.5H6a.5.5 0 00-.5.5v3h13V6a.5.5 0 00-.5-.5zm.5 5H10v8h8a.5.5 0 00.5-.5v-7.5zm-10 0h-3V18a.5.5 0 00.5.5h2.5v-8zM6 4h12a2 2 0 012 2v12a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z"></path></svg>'
}, {
title: __('Theme Options'),
slug: 'theme-options',
icon: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24" height="24" aria-hidden="true" focusable="false" style="fill: currentcolor;"><path d="M12 4c-4.4 0-8 3.6-8 8v.1c0 4.1 3.2 7.5 7.2 7.9h.8c4.4 0 8-3.6 8-8s-3.6-8-8-8zm0 15V5c3.9 0 7 3.1 7 7s-3.1 7-7 7z"></path></svg>'
});
setMenuOptions(pages);
}
}, [isPurchase]);
(0,_wordpress_element__WEBPACK_IMPORTED_MODULE_2__.useEffect)(() => {
localStorage.setItem('isPurchase', JSON.stringify(isPurchase));
}, [isPurchase]);
const checkIsPurchase = async () => {
const rest_url = `${devia_options.rest_url}wd/v2/check-purchase-code`;
const response = await fetch(rest_url, {
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': devia_options.nonce
}
});
if (response.ok) {
const _isPurchase = await response.json();
if (_isPurchase != isPurchase) {
setIsPurchase(_isPurchase);
}
}
};
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
class: "devia_dashboard"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
class: "navigable-region",
"data-depth": currentDepth
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
class: "devia-back_to_dash"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("a", {
href: devia_options.admin_dash_link
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("span", {
class: "dashicon dashicons dashicons-wordpress"
}), __('Back to Dashboard', devia_options.text_domain))), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("nav", {
class: "devia-nav"
}, menuOptions.map(option => (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_4__.NavLink, {
to: `/${option.slug}`,
className: state => `${state.isActive ? 'current' : ''} components-item edit-site-sidebar-navigation-item components-navigator-button`
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "components-flex components-h-stack"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: `devia-nav-item__icon`,
dangerouslySetInnerHTML: {
__html: option.icon
}
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "devia-nav-item"
}, option.title), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
width: "24",
height: "24",
class: "edit-site-sidebar-navigation-item__drilldown-indicator",
"aria-hidden": "true",
focusable: "false"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("path", {
d: "M10.8622 8.04053L14.2805 12.0286L10.8622 16.0167L9.72327 15.0405L12.3049 12.0286L9.72327 9.01672L10.8622 8.04053Z"
}))))))), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "create_more"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("a", {
href: "https://webdevia.com/downloads/website-maintenance-1-year/?utm_source=panel&utm_medium=click&utm_campaign=peaceofmind",
target: "_blank"
}, "Have peace of mind"))), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
class: "content-region"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react__WEBPACK_IMPORTED_MODULE_0__.Suspense, {
fallback: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_Loading__WEBPACK_IMPORTED_MODULE_1__["default"], null)
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Routes, null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
index: true,
path: '/welcome-page',
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Welcome, null)
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: '/documentation',
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Documentation, null)
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "/theme-options",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(ThemeOptions, null)
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
index: true,
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(General, {
fields: panel_fields.find(field => field.group === 'general').fields
})
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "colors",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Colors, {
fields: panel_fields.find(field => field.group === 'colors').fields
})
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "fonts",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Fonts, {
fields: panel_fields.find(field => field.group === 'fonts').fields
})
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "blog",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Blog, {
fields: panel_fields.find(field => field.group === 'blog').fields
})
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "shop",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Shop, {
fields: panel_fields.find(field => field.group === 'shop').fields
})
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "footer",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Footer, {
fields: panel_fields.find(field => field.group === 'footer').fields
})
})), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "/theme-activation",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(ThemeActivation, {
isPurchase: isPurchase,
setIsPurchase: setIsPurchase
})
}), isPurchase.active && (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "/demo-import",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(DemoImport, null)
}), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.Route, {
path: "*",
element: (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(NotFound, null)
}))), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(Navigation, {
index: currentRouteIndex,
routes: menuOptions,
isPurchase: isPurchase
}))));
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PanelPage);
/***/ }),
/***/ "./src/panel/context/PanelContext.jsx":
/*!********************************************!*\
!*** ./src/panel/context/PanelContext.jsx ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ PanelContext: () => (/* binding */ PanelContext),
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/api-fetch */ "@wordpress/api-fetch");
/* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2__);
const PanelContext = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createContext)();
function PanelContextProvider(props) {
const defaultSettings = {
//homepage_display: devia_options.homepage_display,
//home_id: devia_options.home_id,
site_icon: '',
brand_color: '#4D34FA',
style: 'blue'
};
const [settingsSaved, setSettingsSaved] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useState)(false);
const [settings, setSettings] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useState)(defaultSettings);
const [activeItem, setActiveItem] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useState)({
activeItem: "/"
});
const [currentStep, setCurrentStep] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useState)(0);
const [selectedPages, setSelectedPages] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useState)([]);
const pageStart = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);
const getSettings = () => {
_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({
path: '/devia/v1/settings'
}).then(options => {
setSettings(options);
});
};
const saveSettings = () => {
_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({
path: '/devia/v1/settings',
method: 'POST',
data: settings
});
};
const resetSettings = () => {
setSettings(defaultSettings);
_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({
path: '/devia/v1/settings',
method: 'POST',
data: defaultSettings
});
};
const importSettings = newSettings => {
setSettings(newSettings);
_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_2___default()({
path: '/devia/v1/settings',
method: 'POST',
data: newSettings
});
};
const updateSetting = (key, value) => {
setSettings({
...settings,
[key]: value
});
};
(0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {
getSettings();
}, []);
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(PanelContext.Provider, {
value: {
settings,
settingsSaved,
setSettingsSaved,
updateSetting,
setSettings,
saveSettings,
resetSettings,
importSettings,
activeItem,
setActiveItem,
currentStep,
setCurrentStep,
selectedPages,
setSelectedPages,
pageStart
}
}, props.children);
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PanelContextProvider);
/***/ }),
/***/ "./src/panel/panel.js":
/*!****************************!*\
!*** ./src/panel/panel.js ***!
\****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _context_PanelContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./context/PanelContext */ "./src/panel/context/PanelContext.jsx");
/* harmony import */ var _components_main_PanelPage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/main/PanelPage */ "./src/panel/components/main/PanelPage.jsx");
/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-router-dom */ "./node_modules/react-router-dom/dist/index.js");
function Panel() {
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_context_PanelContext__WEBPACK_IMPORTED_MODULE_1__["default"], null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react_router_dom__WEBPACK_IMPORTED_MODULE_3__.HashRouter, null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_components_main_PanelPage__WEBPACK_IMPORTED_MODULE_2__["default"], null)));
}
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Panel);
/***/ }),
/***/ "./src/panel/scss/style.scss":
/*!***********************************!*\
!*** ./src/panel/scss/style.scss ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "./node_modules/react-router-dom/dist/index.js":
/*!*****************************************************!*\
!*** ./node_modules/react-router-dom/dist/index.js ***!
\*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ AbortedDeferredError: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.AbortedDeferredError),
/* harmony export */ Await: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.Await),
/* harmony export */ BrowserRouter: () => (/* binding */ BrowserRouter),
/* harmony export */ Form: () => (/* binding */ Form),
/* harmony export */ HashRouter: () => (/* binding */ HashRouter),
/* harmony export */ Link: () => (/* binding */ Link),
/* harmony export */ MemoryRouter: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.MemoryRouter),
/* harmony export */ NavLink: () => (/* binding */ NavLink),
/* harmony export */ Navigate: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.Navigate),
/* harmony export */ NavigationType: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.Action),
/* harmony export */ Outlet: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.Outlet),
/* harmony export */ Route: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.Route),
/* harmony export */ Router: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.Router),
/* harmony export */ RouterProvider: () => (/* binding */ RouterProvider),
/* harmony export */ Routes: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.Routes),
/* harmony export */ ScrollRestoration: () => (/* binding */ ScrollRestoration),
/* harmony export */ UNSAFE_DataRouterContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterContext),
/* harmony export */ UNSAFE_DataRouterStateContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterStateContext),
/* harmony export */ UNSAFE_FetchersContext: () => (/* binding */ FetchersContext),
/* harmony export */ UNSAFE_LocationContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_LocationContext),
/* harmony export */ UNSAFE_NavigationContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_NavigationContext),
/* harmony export */ UNSAFE_RouteContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_RouteContext),
/* harmony export */ UNSAFE_ViewTransitionContext: () => (/* binding */ ViewTransitionContext),
/* harmony export */ UNSAFE_useRouteId: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_useRouteId),
/* harmony export */ UNSAFE_useScrollRestoration: () => (/* binding */ useScrollRestoration),
/* harmony export */ createBrowserRouter: () => (/* binding */ createBrowserRouter),
/* harmony export */ createHashRouter: () => (/* binding */ createHashRouter),
/* harmony export */ createMemoryRouter: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.createMemoryRouter),
/* harmony export */ createPath: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.createPath),
/* harmony export */ createRoutesFromChildren: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.createRoutesFromChildren),
/* harmony export */ createRoutesFromElements: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.createRoutesFromElements),
/* harmony export */ createSearchParams: () => (/* binding */ createSearchParams),
/* harmony export */ defer: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.defer),
/* harmony export */ generatePath: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.generatePath),
/* harmony export */ isRouteErrorResponse: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.isRouteErrorResponse),
/* harmony export */ json: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.json),
/* harmony export */ matchPath: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.matchPath),
/* harmony export */ matchRoutes: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.matchRoutes),
/* harmony export */ parsePath: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.parsePath),
/* harmony export */ redirect: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.redirect),
/* harmony export */ redirectDocument: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.redirectDocument),
/* harmony export */ renderMatches: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.renderMatches),
/* harmony export */ resolvePath: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_2__.resolvePath),
/* harmony export */ unstable_HistoryRouter: () => (/* binding */ HistoryRouter),
/* harmony export */ unstable_usePrompt: () => (/* binding */ usePrompt),
/* harmony export */ unstable_useViewTransitionState: () => (/* binding */ useViewTransitionState),
/* harmony export */ useActionData: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useActionData),
/* harmony export */ useAsyncError: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useAsyncError),
/* harmony export */ useAsyncValue: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useAsyncValue),
/* harmony export */ useBeforeUnload: () => (/* binding */ useBeforeUnload),
/* harmony export */ useBlocker: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useBlocker),
/* harmony export */ useFetcher: () => (/* binding */ useFetcher),
/* harmony export */ useFetchers: () => (/* binding */ useFetchers),
/* harmony export */ useFormAction: () => (/* binding */ useFormAction),
/* harmony export */ useHref: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useHref),
/* harmony export */ useInRouterContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useInRouterContext),
/* harmony export */ useLinkClickHandler: () => (/* binding */ useLinkClickHandler),
/* harmony export */ useLoaderData: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useLoaderData),
/* harmony export */ useLocation: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useLocation),
/* harmony export */ useMatch: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useMatch),
/* harmony export */ useMatches: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useMatches),
/* harmony export */ useNavigate: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useNavigate),
/* harmony export */ useNavigation: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useNavigation),
/* harmony export */ useNavigationType: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useNavigationType),
/* harmony export */ useOutlet: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useOutlet),
/* harmony export */ useOutletContext: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useOutletContext),
/* harmony export */ useParams: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useParams),
/* harmony export */ useResolvedPath: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useResolvedPath),
/* harmony export */ useRevalidator: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useRevalidator),
/* harmony export */ useRouteError: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useRouteError),
/* harmony export */ useRouteLoaderData: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useRouteLoaderData),
/* harmony export */ useRoutes: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_3__.useRoutes),
/* harmony export */ useSearchParams: () => (/* binding */ useSearchParams),
/* harmony export */ useSubmit: () => (/* binding */ useSubmit)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ "react-dom");
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-router */ "./node_modules/react-router/dist/index.js");
/* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @remix-run/router */ "./node_modules/@remix-run/router/dist/router.js");
/**
* React Router DOM v6.21.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 _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);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
const defaultMethod = "get";
const defaultEncType = "application/x-www-form-urlencoded";
function isHtmlElement(object) {
return object != null && typeof object.tagName === "string";
}
function isButtonElement(object) {
return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
}
function isFormElement(object) {
return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
}
function isInputElement(object) {
return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
}
function isModifiedEvent(event) {
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
}
function shouldProcessLinkClick(event, target) {
return event.button === 0 && (
// Ignore everything but left clicks
!target || target === "_self") &&
// Let browser handle "target=_blank" etc.
!isModifiedEvent(event) // Ignore clicks with modifier keys
;
}
/**
* Creates a URLSearchParams object using the given initializer.
*
* This is identical to `new URLSearchParams(init)` except it also
* supports arrays as values in the object form of the initializer
* instead of just strings. This is convenient when you need multiple
* values for a given key, but don't want to use an array initializer.
*
* For example, instead of:
*
* let searchParams = new URLSearchParams([
* ['sort', 'name'],
* ['sort', 'price']
* ]);
*
* you can do:
*
* let searchParams = createSearchParams({
* sort: ['name', 'price']
* });
*/
function createSearchParams(init) {
if (init === void 0) {
init = "";
}
return new URLSearchParams(typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo, key) => {
let value = init[key];
return memo.concat(Array.isArray(value) ? value.map(v => [key, v]) : [[key, value]]);
}, []));
}
function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
let searchParams = createSearchParams(locationSearch);
if (defaultSearchParams) {
// Use `defaultSearchParams.forEach(...)` here instead of iterating of
// `defaultSearchParams.keys()` to work-around a bug in Firefox related to
// web extensions. Relevant Bugzilla tickets:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1414602
// https://bugzilla.mozilla.org/show_bug.cgi?id=1023984
defaultSearchParams.forEach((_, key) => {
if (!searchParams.has(key)) {
defaultSearchParams.getAll(key).forEach(value => {
searchParams.append(key, value);
});
}
});
}
return searchParams;
}
// One-time check for submitter support
let _formDataSupportsSubmitter = null;
function isFormDataSubmitterSupported() {
if (_formDataSupportsSubmitter === null) {
try {
new FormData(document.createElement("form"),
// @ts-expect-error if FormData supports the submitter parameter, this will throw
0);
_formDataSupportsSubmitter = false;
} catch (e) {
_formDataSupportsSubmitter = true;
}
}
return _formDataSupportsSubmitter;
}
const supportedFormEncTypes = new Set(["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]);
function getFormEncType(encType) {
if (encType != null && !supportedFormEncTypes.has(encType)) {
true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_warning)(false, "\"" + encType + "\" is not a valid `encType` for `<Form>`/`<fetcher.Form>` " + ("and will default to \"" + defaultEncType + "\"")) : 0;
return null;
}
return encType;
}
function getFormSubmissionInfo(target, basename) {
let method;
let action;
let encType;
let formData;
let body;
if (isFormElement(target)) {
// When grabbing the action from the element, it will have had the basename
// prefixed to ensure non-JS scenarios work, so strip it since we'll
// re-prefix in the router
let attr = target.getAttribute("action");
action = attr ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.stripBasename)(attr, basename) : null;
method = target.getAttribute("method") || defaultMethod;
encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
formData = new FormData(target);
} else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
let form = target.form;
if (form == null) {
throw new Error("Cannot submit a <button> or <input type=\"submit\"> without a <form>");
}
// <button>/<input type="submit"> may override attributes of <form>
// When grabbing the action from the element, it will have had the basename
// prefixed to ensure non-JS scenarios work, so strip it since we'll
// re-prefix in the router
let attr = target.getAttribute("formaction") || form.getAttribute("action");
action = attr ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.stripBasename)(attr, basename) : null;
method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
// Build a FormData object populated from a form and submitter
formData = new FormData(form, target);
// If this browser doesn't support the `FormData(el, submitter)` format,
// then tack on the submitter value at the end. This is a lightweight
// solution that is not 100% spec compliant. For complete support in older
// browsers, consider using the `formdata-submitter-polyfill` package
if (!isFormDataSubmitterSupported()) {
let {
name,
type,
value
} = target;
if (type === "image") {
let prefix = name ? name + "." : "";
formData.append(prefix + "x", "0");
formData.append(prefix + "y", "0");
} else if (name) {
formData.append(name, value);
}
}
} else if (isHtmlElement(target)) {
throw new Error("Cannot submit element that is not <form>, <button>, or " + "<input type=\"submit|image\">");
} else {
method = defaultMethod;
action = null;
encType = defaultEncType;
body = target;
}
// Send body for <Form encType="text/plain" so we encode it into text
if (formData && encType === "text/plain") {
body = formData;
formData = undefined;
}
return {
action,
method: method.toLowerCase(),
encType,
formData,
body
};
}
const _excluded = ["onClick", "relative", "reloadDocument", "replace", "state", "target", "to", "preventScrollReset", "unstable_viewTransition"],
_excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "unstable_viewTransition", "children"],
_excluded3 = ["fetcherKey", "navigate", "reloadDocument", "replace", "state", "method", "action", "onSubmit", "relative", "preventScrollReset", "unstable_viewTransition"];
function createBrowserRouter(routes, opts) {
return (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createRouter)({
basename: opts == null ? void 0 : opts.basename,
future: _extends({}, opts == null ? void 0 : opts.future, {
v7_prependBasename: true
}),
history: (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createBrowserHistory)({
window: opts == null ? void 0 : opts.window
}),
hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
routes,
mapRouteProperties: react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_mapRouteProperties,
window: opts == null ? void 0 : opts.window
}).initialize();
}
function createHashRouter(routes, opts) {
return (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createRouter)({
basename: opts == null ? void 0 : opts.basename,
future: _extends({}, opts == null ? void 0 : opts.future, {
v7_prependBasename: true
}),
history: (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createHashHistory)({
window: opts == null ? void 0 : opts.window
}),
hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
routes,
mapRouteProperties: react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_mapRouteProperties,
window: opts == null ? void 0 : opts.window
}).initialize();
}
function parseHydrationData() {
var _window;
let state = (_window = window) == null ? void 0 : _window.__staticRouterHydrationData;
if (state && state.errors) {
state = _extends({}, state, {
errors: deserializeErrors(state.errors)
});
}
return state;
}
function deserializeErrors(errors) {
if (!errors) return null;
let entries = Object.entries(errors);
let serialized = {};
for (let [key, val] of entries) {
// Hey you! If you change this, please change the corresponding logic in
// serializeErrors in react-router-dom/server.tsx :)
if (val && val.__type === "RouteErrorResponse") {
serialized[key] = new react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_ErrorResponseImpl(val.status, val.statusText, val.data, val.internal === true);
} else if (val && val.__type === "Error") {
// Attempt to reconstruct the right type of Error (i.e., ReferenceError)
if (val.__subType) {
let ErrorConstructor = window[val.__subType];
if (typeof ErrorConstructor === "function") {
try {
// @ts-expect-error
let error = new ErrorConstructor(val.message);
// Wipe away the client-side stack trace. Nothing to fill it in with
// because we don't serialize SSR stack traces for security reasons
error.stack = "";
serialized[key] = error;
} catch (e) {
// no-op - fall through and create a normal Error
}
}
}
if (serialized[key] == null) {
let error = new Error(val.message);
// Wipe away the client-side stack trace. Nothing to fill it in with
// because we don't serialize SSR stack traces for security reasons
error.stack = "";
serialized[key] = error;
}
} else {
serialized[key] = val;
}
}
return serialized;
}
const ViewTransitionContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext({
isTransitioning: false
});
if (true) {
ViewTransitionContext.displayName = "ViewTransition";
}
const FetchersContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(new Map());
if (true) {
FetchersContext.displayName = "Fetchers";
}
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region Components
////////////////////////////////////////////////////////////////////////////////
/**
Webpack + React 17 fails to compile on any of the following because webpack
complains that `startTransition` doesn't exist in `React`:
* import { startTransition } from "react"
* import * as React from from "react";
"startTransition" in React ? React.startTransition(() => setState()) : setState()
* import * as React from from "react";
"startTransition" in React ? React["startTransition"](() => setState()) : setState()
Moving it to a constant such as the following solves the Webpack/React 17 issue:
* import * as React from from "react";
const START_TRANSITION = "startTransition";
START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()
However, that introduces webpack/terser minification issues in production builds
in React 18 where minification/obfuscation ends up removing the call of
React.startTransition entirely from the first half of the ternary. Grabbing
this exported reference once up front resolves that issue.
See https://github.com/remix-run/react-router/issues/10579
*/
const START_TRANSITION = "startTransition";
const startTransitionImpl = react__WEBPACK_IMPORTED_MODULE_0__[START_TRANSITION];
const FLUSH_SYNC = "flushSync";
const flushSyncImpl = react_dom__WEBPACK_IMPORTED_MODULE_1__[FLUSH_SYNC];
function startTransitionSafe(cb) {
if (startTransitionImpl) {
startTransitionImpl(cb);
} else {
cb();
}
}
function flushSyncSafe(cb) {
if (flushSyncImpl) {
flushSyncImpl(cb);
} else {
cb();
}
}
class Deferred {
constructor() {
this.status = "pending";
this.promise = new Promise((resolve, reject) => {
this.resolve = value => {
if (this.status === "pending") {
this.status = "resolved";
resolve(value);
}
};
this.reject = reason => {
if (this.status === "pending") {
this.status = "rejected";
reject(reason);
}
};
});
}
}
/**
* Given a Remix Router instance, render the appropriate UI
*/
function RouterProvider(_ref) {
let {
fallbackElement,
router,
future
} = _ref;
let [state, setStateImpl] = react__WEBPACK_IMPORTED_MODULE_0__.useState(router.state);
let [pendingState, setPendingState] = react__WEBPACK_IMPORTED_MODULE_0__.useState();
let [vtContext, setVtContext] = react__WEBPACK_IMPORTED_MODULE_0__.useState({
isTransitioning: false
});
let [renderDfd, setRenderDfd] = react__WEBPACK_IMPORTED_MODULE_0__.useState();
let [transition, setTransition] = react__WEBPACK_IMPORTED_MODULE_0__.useState();
let [interruption, setInterruption] = react__WEBPACK_IMPORTED_MODULE_0__.useState();
let fetcherData = react__WEBPACK_IMPORTED_MODULE_0__.useRef(new Map());
let {
v7_startTransition
} = future || {};
let optInStartTransition = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(cb => {
if (v7_startTransition) {
startTransitionSafe(cb);
} else {
cb();
}
}, [v7_startTransition]);
let setState = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((newState, _ref2) => {
let {
deletedFetchers,
unstable_flushSync: flushSync,
unstable_viewTransitionOpts: viewTransitionOpts
} = _ref2;
deletedFetchers.forEach(key => fetcherData.current.delete(key));
newState.fetchers.forEach((fetcher, key) => {
if (fetcher.data !== undefined) {
fetcherData.current.set(key, fetcher.data);
}
});
let isViewTransitionUnavailable = router.window == null || typeof router.window.document.startViewTransition !== "function";
// If this isn't a view transition or it's not available in this browser,
// just update and be done with it
if (!viewTransitionOpts || isViewTransitionUnavailable) {
if (flushSync) {
flushSyncSafe(() => setStateImpl(newState));
} else {
optInStartTransition(() => setStateImpl(newState));
}
return;
}
// flushSync + startViewTransition
if (flushSync) {
// Flush through the context to mark DOM elements as transition=ing
flushSyncSafe(() => {
// Cancel any pending transitions
if (transition) {
renderDfd && renderDfd.resolve();
transition.skipTransition();
}
setVtContext({
isTransitioning: true,
flushSync: true,
currentLocation: viewTransitionOpts.currentLocation,
nextLocation: viewTransitionOpts.nextLocation
});
});
// Update the DOM
let t = router.window.document.startViewTransition(() => {
flushSyncSafe(() => setStateImpl(newState));
});
// Clean up after the animation completes
t.finished.finally(() => {
flushSyncSafe(() => {
setRenderDfd(undefined);
setTransition(undefined);
setPendingState(undefined);
setVtContext({
isTransitioning: false
});
});
});
flushSyncSafe(() => setTransition(t));
return;
}
// startTransition + startViewTransition
if (transition) {
// Interrupting an in-progress transition, cancel and let everything flush
// out, and then kick off a new transition from the interruption state
renderDfd && renderDfd.resolve();
transition.skipTransition();
setInterruption({
state: newState,
currentLocation: viewTransitionOpts.currentLocation,
nextLocation: viewTransitionOpts.nextLocation
});
} else {
// Completed navigation update with opted-in view transitions, let 'er rip
setPendingState(newState);
setVtContext({
isTransitioning: true,
flushSync: false,
currentLocation: viewTransitionOpts.currentLocation,
nextLocation: viewTransitionOpts.nextLocation
});
}
}, [router.window, transition, renderDfd, fetcherData, optInStartTransition]);
// Need to use a layout effect here so we are subscribed early enough to
// pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
// When we start a view transition, create a Deferred we can use for the
// eventual "completed" render
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (vtContext.isTransitioning && !vtContext.flushSync) {
setRenderDfd(new Deferred());
}
}, [vtContext]);
// Once the deferred is created, kick off startViewTransition() to update the
// DOM and then wait on the Deferred to resolve (indicating the DOM update has
// happened)
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (renderDfd && pendingState && router.window) {
let newState = pendingState;
let renderPromise = renderDfd.promise;
let transition = router.window.document.startViewTransition(async () => {
optInStartTransition(() => setStateImpl(newState));
await renderPromise;
});
transition.finished.finally(() => {
setRenderDfd(undefined);
setTransition(undefined);
setPendingState(undefined);
setVtContext({
isTransitioning: false
});
});
setTransition(transition);
}
}, [optInStartTransition, pendingState, renderDfd, router.window]);
// When the new location finally renders and is committed to the DOM, this
// effect will run to resolve the transition
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (renderDfd && pendingState && state.location.key === pendingState.location.key) {
renderDfd.resolve();
}
}, [renderDfd, transition, state.location, pendingState]);
// If we get interrupted with a new navigation during a transition, we skip
// the active transition, let it cleanup, then kick it off again here
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (!vtContext.isTransitioning && interruption) {
setPendingState(interruption.state);
setVtContext({
isTransitioning: true,
flushSync: false,
currentLocation: interruption.currentLocation,
nextLocation: interruption.nextLocation
});
setInterruption(undefined);
}
}, [vtContext.isTransitioning, interruption]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_warning)(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using " + "`v7_partialHydration`, use a `HydrateFallback` component instead") : 0;
// Only log this once on initial mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
let navigator = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => {
return {
createHref: router.createHref,
encodeLocation: router.encodeLocation,
go: n => router.navigate(n),
push: (to, state, opts) => router.navigate(to, {
state,
preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
}),
replace: (to, state, opts) => router.navigate(to, {
replace: true,
state,
preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
})
};
}, [router]);
let basename = router.basename || "/";
let dataRouterContext = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => ({
router,
navigator,
static: false,
basename
}), [router, navigator, basename]);
// The fragment and {null} here are important! We need them to keep React 18's
// useId happy when we are server-rendering since we may have a <script> here
// containing the hydrated server-side staticContext (from StaticRouterProvider).
// useId relies on the component tree structure to generate deterministic id's
// so we need to ensure it remains the same on the client even though
// we don't need the <script> tag
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterContext.Provider, {
value: dataRouterContext
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterStateContext.Provider, {
value: state
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(FetchersContext.Provider, {
value: fetcherData.current
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(ViewTransitionContext.Provider, {
value: vtContext
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router__WEBPACK_IMPORTED_MODULE_3__.Router, {
basename: basename,
location: state.location,
navigationType: state.historyAction,
navigator: navigator,
future: {
v7_relativeSplatPath: router.future.v7_relativeSplatPath
}
}, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(DataRoutes, {
routes: router.routes,
future: router.future,
state: state
}) : fallbackElement))))), null);
}
function DataRoutes(_ref3) {
let {
routes,
future,
state
} = _ref3;
return (0,react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_useRoutesImpl)(routes, undefined, state, future);
}
/**
* A `<Router>` for use in web browsers. Provides the cleanest URLs.
*/
function BrowserRouter(_ref4) {
let {
basename,
children,
future,
window
} = _ref4;
let historyRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef();
if (historyRef.current == null) {
historyRef.current = (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createBrowserHistory)({
window,
v5Compat: true
});
}
let history = historyRef.current;
let [state, setStateImpl] = react__WEBPACK_IMPORTED_MODULE_0__.useState({
action: history.action,
location: history.location
});
let {
v7_startTransition
} = future || {};
let setState = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(newState => {
v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
}, [setStateImpl, v7_startTransition]);
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => history.listen(setState), [history, setState]);
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router__WEBPACK_IMPORTED_MODULE_3__.Router, {
basename: basename,
children: children,
location: state.location,
navigationType: state.action,
navigator: history,
future: future
});
}
/**
* A `<Router>` for use in web browsers. Stores the location in the hash
* portion of the URL so it is not sent to the server.
*/
function HashRouter(_ref5) {
let {
basename,
children,
future,
window
} = _ref5;
let historyRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef();
if (historyRef.current == null) {
historyRef.current = (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createHashHistory)({
window,
v5Compat: true
});
}
let history = historyRef.current;
let [state, setStateImpl] = react__WEBPACK_IMPORTED_MODULE_0__.useState({
action: history.action,
location: history.location
});
let {
v7_startTransition
} = future || {};
let setState = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(newState => {
v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
}, [setStateImpl, v7_startTransition]);
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => history.listen(setState), [history, setState]);
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router__WEBPACK_IMPORTED_MODULE_3__.Router, {
basename: basename,
children: children,
location: state.location,
navigationType: state.action,
navigator: history,
future: future
});
}
/**
* A `<Router>` that accepts a pre-instantiated history object. It's important
* to note that using your own history object is highly discouraged and may add
* two versions of the history library to your bundles unless you use the same
* version of the history library that React Router uses internally.
*/
function HistoryRouter(_ref6) {
let {
basename,
children,
future,
history
} = _ref6;
let [state, setStateImpl] = react__WEBPACK_IMPORTED_MODULE_0__.useState({
action: history.action,
location: history.location
});
let {
v7_startTransition
} = future || {};
let setState = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(newState => {
v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
}, [setStateImpl, v7_startTransition]);
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => history.listen(setState), [history, setState]);
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react_router__WEBPACK_IMPORTED_MODULE_3__.Router, {
basename: basename,
children: children,
location: state.location,
navigationType: state.action,
navigator: history,
future: future
});
}
if (true) {
HistoryRouter.displayName = "unstable_HistoryRouter";
}
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
/**
* The public API for rendering a history-aware `<a>`.
*/
const Link = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(function LinkWithRef(_ref7, ref) {
let {
onClick,
relative,
reloadDocument,
replace,
state,
target,
to,
preventScrollReset,
unstable_viewTransition
} = _ref7,
rest = _objectWithoutPropertiesLoose(_ref7, _excluded);
let {
basename
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_NavigationContext);
// Rendered into <a href> for absolute URLs
let absoluteHref;
let isExternal = false;
if (typeof to === "string" && ABSOLUTE_URL_REGEX.test(to)) {
// Render the absolute href server- and client-side
absoluteHref = to;
// Only check for external origins client-side
if (isBrowser) {
try {
let currentUrl = new URL(window.location.href);
let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
let path = (0,react_router__WEBPACK_IMPORTED_MODULE_2__.stripBasename)(targetUrl.pathname, basename);
if (targetUrl.origin === currentUrl.origin && path != null) {
// Strip the protocol/origin/basename for same-origin absolute URLs
to = path + targetUrl.search + targetUrl.hash;
} else {
isExternal = true;
}
} catch (e) {
// We can't do external URL detection without a valid URL
true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_warning)(false, "<Link to=\"" + to + "\"> contains an invalid URL which will probably break " + "when clicked - please update to a valid URL path.") : 0;
}
}
}
// Rendered into <a href> for relative URLs
let href = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useHref)(to, {
relative
});
let internalOnClick = useLinkClickHandler(to, {
replace,
state,
target,
preventScrollReset,
relative,
unstable_viewTransition
});
function handleClick(event) {
if (onClick) onClick(event);
if (!event.defaultPrevented) {
internalOnClick(event);
}
}
return (
/*#__PURE__*/
// eslint-disable-next-line jsx-a11y/anchor-has-content
react__WEBPACK_IMPORTED_MODULE_0__.createElement("a", _extends({}, rest, {
href: absoluteHref || href,
onClick: isExternal || reloadDocument ? onClick : handleClick,
ref: ref,
target: target
}))
);
});
if (true) {
Link.displayName = "Link";
}
/**
* A `<Link>` wrapper that knows if it's "active" or not.
*/
const NavLink = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(function NavLinkWithRef(_ref8, ref) {
let {
"aria-current": ariaCurrentProp = "page",
caseSensitive = false,
className: classNameProp = "",
end = false,
style: styleProp,
to,
unstable_viewTransition,
children
} = _ref8,
rest = _objectWithoutPropertiesLoose(_ref8, _excluded2);
let path = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useResolvedPath)(to, {
relative: rest.relative
});
let location = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useLocation)();
let routerState = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterStateContext);
let {
navigator
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_NavigationContext);
let isTransitioning = routerState != null &&
// Conditional usage is OK here because the usage of a data router is static
// eslint-disable-next-line react-hooks/rules-of-hooks
useViewTransitionState(path) && unstable_viewTransition === true;
let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
let locationPathname = location.pathname;
let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
if (!caseSensitive) {
locationPathname = locationPathname.toLowerCase();
nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
toPathname = toPathname.toLowerCase();
}
// If the `to` has a trailing slash, look at that exact spot. Otherwise,
// we're looking for a slash _after_ what's in `to`. For example:
//
// <NavLink to="/users"> and <NavLink to="/users/">
// both want to look for a / at index 6 to match URL `/users/matt`
const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
let renderProps = {
isActive,
isPending,
isTransitioning
};
let ariaCurrent = isActive ? ariaCurrentProp : undefined;
let className;
if (typeof classNameProp === "function") {
className = classNameProp(renderProps);
} else {
// If the className prop is not a function, we use a default `active`
// class for <NavLink />s that are active. In v5 `active` was the default
// value for `activeClassName`, but we are removing that API and can still
// use the old default behavior for a cleaner upgrade path and keep the
// simple styling rules working as they currently do.
className = [classNameProp, isActive ? "active" : null, isPending ? "pending" : null, isTransitioning ? "transitioning" : null].filter(Boolean).join(" ");
}
let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(Link, _extends({}, rest, {
"aria-current": ariaCurrent,
className: className,
ref: ref,
style: style,
to: to,
unstable_viewTransition: unstable_viewTransition
}), typeof children === "function" ? children(renderProps) : children);
});
if (true) {
NavLink.displayName = "NavLink";
}
/**
* A `@remix-run/router`-aware `<form>`. It behaves like a normal form except
* that the interaction with the server is with `fetch` instead of new document
* requests, allowing components to add nicer UX to the page as the form is
* submitted and returns with data.
*/
const Form = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef((_ref9, forwardedRef) => {
let {
fetcherKey,
navigate,
reloadDocument,
replace,
state,
method = defaultMethod,
action,
onSubmit,
relative,
preventScrollReset,
unstable_viewTransition
} = _ref9,
props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
let submit = useSubmit();
let formAction = useFormAction(action, {
relative
});
let formMethod = method.toLowerCase() === "get" ? "get" : "post";
let submitHandler = event => {
onSubmit && onSubmit(event);
if (event.defaultPrevented) return;
event.preventDefault();
let submitter = event.nativeEvent.submitter;
let submitMethod = (submitter == null ? void 0 : submitter.getAttribute("formmethod")) || method;
submit(submitter || event.currentTarget, {
fetcherKey,
method: submitMethod,
navigate,
replace,
state,
relative,
preventScrollReset,
unstable_viewTransition
});
};
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("form", _extends({
ref: forwardedRef,
method: formMethod,
action: formAction,
onSubmit: reloadDocument ? onSubmit : submitHandler
}, props));
});
if (true) {
Form.displayName = "Form";
}
/**
* This component will emulate the browser's scroll restoration on location
* changes.
*/
function ScrollRestoration(_ref10) {
let {
getKey,
storageKey
} = _ref10;
useScrollRestoration({
getKey,
storageKey
});
return null;
}
if (true) {
ScrollRestoration.displayName = "ScrollRestoration";
}
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region Hooks
////////////////////////////////////////////////////////////////////////////////
var DataRouterHook;
(function (DataRouterHook) {
DataRouterHook["UseScrollRestoration"] = "useScrollRestoration";
DataRouterHook["UseSubmit"] = "useSubmit";
DataRouterHook["UseSubmitFetcher"] = "useSubmitFetcher";
DataRouterHook["UseFetcher"] = "useFetcher";
DataRouterHook["useViewTransitionState"] = "useViewTransitionState";
})(DataRouterHook || (DataRouterHook = {}));
var DataRouterStateHook;
(function (DataRouterStateHook) {
DataRouterStateHook["UseFetcher"] = "useFetcher";
DataRouterStateHook["UseFetchers"] = "useFetchers";
DataRouterStateHook["UseScrollRestoration"] = "useScrollRestoration";
})(DataRouterStateHook || (DataRouterStateHook = {}));
// Internal hooks
function getDataRouterConsoleError(hookName) {
return hookName + " must be used within a data router. See https://reactrouter.com/routers/picking-a-router.";
}
function useDataRouterContext(hookName) {
let ctx = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterContext);
!ctx ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, getDataRouterConsoleError(hookName)) : 0 : void 0;
return ctx;
}
function useDataRouterState(hookName) {
let state = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_DataRouterStateContext);
!state ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, getDataRouterConsoleError(hookName)) : 0 : void 0;
return state;
}
// External hooks
/**
* Handles the click behavior for router `<Link>` components. This is useful if
* you need to create custom `<Link>` components with the same click behavior we
* use in our exported `<Link>`.
*/
function useLinkClickHandler(to, _temp) {
let {
target,
replace: replaceProp,
state,
preventScrollReset,
relative,
unstable_viewTransition
} = _temp === void 0 ? {} : _temp;
let navigate = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useNavigate)();
let location = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useLocation)();
let path = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useResolvedPath)(to, {
relative
});
return react__WEBPACK_IMPORTED_MODULE_0__.useCallback(event => {
if (shouldProcessLinkClick(event, target)) {
event.preventDefault();
// If the URL hasn't changed, a regular <a> will do a replace instead of
// a push, so do the same here unless the replace prop is explicitly set
let replace = replaceProp !== undefined ? replaceProp : (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createPath)(location) === (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createPath)(path);
navigate(to, {
replace,
state,
preventScrollReset,
relative,
unstable_viewTransition
});
}
}, [location, navigate, path, replaceProp, state, target, to, preventScrollReset, relative, unstable_viewTransition]);
}
/**
* A convenient wrapper for reading and writing search parameters via the
* URLSearchParams interface.
*/
function useSearchParams(defaultInit) {
true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_warning)(typeof URLSearchParams !== "undefined", "You cannot use the `useSearchParams` hook in a browser that does not " + "support the URLSearchParams API. If you need to support Internet " + "Explorer 11, we recommend you load a polyfill such as " + "https://github.com/ungap/url-search-params\n\n" + "If you're unsure how to load polyfills, we recommend you check out " + "https://polyfill.io/v3/ which provides some recommendations about how " + "to load polyfills only for users that need them, instead of for every " + "user.") : 0;
let defaultSearchParamsRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(createSearchParams(defaultInit));
let hasSetSearchParamsRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(false);
let location = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useLocation)();
let searchParams = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() =>
// Only merge in the defaults if we haven't yet called setSearchParams.
// Once we call that we want those to take precedence, otherwise you can't
// remove a param with setSearchParams({}) if it has an initial value
getSearchParamsForLocation(location.search, hasSetSearchParamsRef.current ? null : defaultSearchParamsRef.current), [location.search]);
let navigate = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useNavigate)();
let setSearchParams = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((nextInit, navigateOptions) => {
const newSearchParams = createSearchParams(typeof nextInit === "function" ? nextInit(searchParams) : nextInit);
hasSetSearchParamsRef.current = true;
navigate("?" + newSearchParams, navigateOptions);
}, [navigate, searchParams]);
return [searchParams, setSearchParams];
}
function validateClientSideSubmission() {
if (typeof document === "undefined") {
throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead.");
}
}
let fetcherId = 0;
let getUniqueFetcherId = () => "__" + String(++fetcherId) + "__";
/**
* Returns a function that may be used to programmatically submit a form (or
* some arbitrary data) to the server.
*/
function useSubmit() {
let {
router
} = useDataRouterContext(DataRouterHook.UseSubmit);
let {
basename
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_NavigationContext);
let currentRouteId = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_useRouteId)();
return react__WEBPACK_IMPORTED_MODULE_0__.useCallback(function (target, options) {
if (options === void 0) {
options = {};
}
validateClientSideSubmission();
let {
action,
method,
encType,
formData,
body
} = getFormSubmissionInfo(target, basename);
if (options.navigate === false) {
let key = options.fetcherKey || getUniqueFetcherId();
router.fetch(key, currentRouteId, options.action || action, {
preventScrollReset: options.preventScrollReset,
formData,
body,
formMethod: options.method || method,
formEncType: options.encType || encType,
unstable_flushSync: options.unstable_flushSync
});
} else {
router.navigate(options.action || action, {
preventScrollReset: options.preventScrollReset,
formData,
body,
formMethod: options.method || method,
formEncType: options.encType || encType,
replace: options.replace,
state: options.state,
fromRouteId: currentRouteId,
unstable_flushSync: options.unstable_flushSync,
unstable_viewTransition: options.unstable_viewTransition
});
}
}, [router, basename, currentRouteId]);
}
// v7: Eventually we should deprecate this entirely in favor of using the
// router method directly?
function useFormAction(action, _temp2) {
let {
relative
} = _temp2 === void 0 ? {} : _temp2;
let {
basename
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_NavigationContext);
let routeContext = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_RouteContext);
!routeContext ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, "useFormAction must be used inside a RouteContext") : 0 : void 0;
let [match] = routeContext.matches.slice(-1);
// Shallow clone path so we can modify it below, otherwise we modify the
// object referenced by useMemo inside useResolvedPath
let path = _extends({}, (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useResolvedPath)(action ? action : ".", {
relative
}));
// If no action was specified, browsers will persist current search params
// when determining the path, so match that behavior
// https://github.com/remix-run/remix/issues/927
let location = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useLocation)();
if (action == null) {
// Safe to write to this directly here since if action was undefined, we
// would have called useResolvedPath(".") which will never include a search
path.search = location.search;
// When grabbing search params from the URL, remove any included ?index param
// since it might not apply to our contextual route. We add it back based
// on match.route.index below
let params = new URLSearchParams(path.search);
if (params.has("index") && params.get("index") === "") {
params.delete("index");
path.search = params.toString() ? "?" + params.toString() : "";
}
}
if ((!action || action === ".") && match.route.index) {
path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
}
// If we're operating within a basename, prepend it to the pathname prior
// to creating the form action. If this is a root navigation, then just use
// the raw basename which allows the basename to have full control over the
// presence of a trailing slash on root actions
if (basename !== "/") {
path.pathname = path.pathname === "/" ? basename : (0,react_router__WEBPACK_IMPORTED_MODULE_2__.joinPaths)([basename, path.pathname]);
}
return (0,react_router__WEBPACK_IMPORTED_MODULE_2__.createPath)(path);
}
// TODO: (v7) Change the useFetcher generic default from `any` to `unknown`
/**
* Interacts with route loaders and actions without causing a navigation. Great
* for any interaction that stays on the same page.
*/
function useFetcher(_temp3) {
var _route$matches;
let {
key
} = _temp3 === void 0 ? {} : _temp3;
let {
router
} = useDataRouterContext(DataRouterHook.UseFetcher);
let state = useDataRouterState(DataRouterStateHook.UseFetcher);
let fetcherData = react__WEBPACK_IMPORTED_MODULE_0__.useContext(FetchersContext);
let route = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_RouteContext);
let routeId = (_route$matches = route.matches[route.matches.length - 1]) == null ? void 0 : _route$matches.route.id;
!fetcherData ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, "useFetcher must be used inside a FetchersContext") : 0 : void 0;
!route ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, "useFetcher must be used inside a RouteContext") : 0 : void 0;
!(routeId != null) ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, "useFetcher can only be used on routes that contain a unique \"id\"") : 0 : void 0;
// Fetcher key handling
let [fetcherKey, setFetcherKey] = react__WEBPACK_IMPORTED_MODULE_0__.useState(key || "");
if (key && key !== fetcherKey) {
setFetcherKey(key);
} else if (!fetcherKey) {
setFetcherKey(getUniqueFetcherId());
}
// Registration/cleanup
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
router.getFetcher(fetcherKey);
return () => {
// Tell the router we've unmounted - if v7_fetcherPersist is enabled this
// will not delete immediately but instead queue up a delete after the
// fetcher returns to an `idle` state
router.deleteFetcher(fetcherKey);
};
}, [router, fetcherKey]);
// Fetcher additions
let load = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((href, opts) => {
!routeId ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, "No routeId available for fetcher.load()") : 0 : void 0;
router.fetch(fetcherKey, routeId, href, opts);
}, [fetcherKey, routeId, router]);
let submitImpl = useSubmit();
let submit = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((target, opts) => {
submitImpl(target, _extends({}, opts, {
navigate: false,
fetcherKey
}));
}, [fetcherKey, submitImpl]);
let FetcherForm = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => {
let FetcherForm = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef((props, ref) => {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(Form, _extends({}, props, {
navigate: false,
fetcherKey: fetcherKey,
ref: ref
}));
});
if (true) {
FetcherForm.displayName = "fetcher.Form";
}
return FetcherForm;
}, [fetcherKey]);
// Exposed FetcherWithComponents
let fetcher = state.fetchers.get(fetcherKey) || react_router__WEBPACK_IMPORTED_MODULE_2__.IDLE_FETCHER;
let data = fetcherData.get(fetcherKey);
let fetcherWithComponents = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => _extends({
Form: FetcherForm,
submit,
load
}, fetcher, {
data
}), [FetcherForm, submit, load, fetcher, data]);
return fetcherWithComponents;
}
/**
* Provides all fetchers currently on the page. Useful for layouts and parent
* routes that need to provide pending/optimistic UI regarding the fetch.
*/
function useFetchers() {
let state = useDataRouterState(DataRouterStateHook.UseFetchers);
return Array.from(state.fetchers.entries()).map(_ref11 => {
let [key, fetcher] = _ref11;
return _extends({}, fetcher, {
key
});
});
}
const SCROLL_RESTORATION_STORAGE_KEY = "react-router-scroll-positions";
let savedScrollPositions = {};
/**
* When rendered inside a RouterProvider, will restore scroll positions on navigations
*/
function useScrollRestoration(_temp4) {
let {
getKey,
storageKey
} = _temp4 === void 0 ? {} : _temp4;
let {
router
} = useDataRouterContext(DataRouterHook.UseScrollRestoration);
let {
restoreScrollPosition,
preventScrollReset
} = useDataRouterState(DataRouterStateHook.UseScrollRestoration);
let {
basename
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(react_router__WEBPACK_IMPORTED_MODULE_3__.UNSAFE_NavigationContext);
let location = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useLocation)();
let matches = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useMatches)();
let navigation = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useNavigation)();
// Trigger manual scroll restoration while we're active
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
window.history.scrollRestoration = "manual";
return () => {
window.history.scrollRestoration = "auto";
};
}, []);
// Save positions on pagehide
usePageHide(react__WEBPACK_IMPORTED_MODULE_0__.useCallback(() => {
if (navigation.state === "idle") {
let key = (getKey ? getKey(location, matches) : null) || location.key;
savedScrollPositions[key] = window.scrollY;
}
try {
sessionStorage.setItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY, JSON.stringify(savedScrollPositions));
} catch (error) {
true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_warning)(false, "Failed to save scroll positions in sessionStorage, <ScrollRestoration /> will not work properly (" + error + ").") : 0;
}
window.history.scrollRestoration = "auto";
}, [storageKey, getKey, navigation.state, location, matches]));
// Read in any saved scroll locations
if (typeof document !== "undefined") {
// eslint-disable-next-line react-hooks/rules-of-hooks
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => {
try {
let sessionPositions = sessionStorage.getItem(storageKey || SCROLL_RESTORATION_STORAGE_KEY);
if (sessionPositions) {
savedScrollPositions = JSON.parse(sessionPositions);
}
} catch (e) {
// no-op, use default empty object
}
}, [storageKey]);
// Enable scroll restoration in the router
// eslint-disable-next-line react-hooks/rules-of-hooks
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => {
let getKeyWithoutBasename = getKey && basename !== "/" ? (location, matches) => getKey( // Strip the basename to match useLocation()
_extends({}, location, {
pathname: (0,react_router__WEBPACK_IMPORTED_MODULE_2__.stripBasename)(location.pathname, basename) || location.pathname
}), matches) : getKey;
let disableScrollRestoration = router == null ? void 0 : router.enableScrollRestoration(savedScrollPositions, () => window.scrollY, getKeyWithoutBasename);
return () => disableScrollRestoration && disableScrollRestoration();
}, [router, basename, getKey]);
// Restore scrolling when state.restoreScrollPosition changes
// eslint-disable-next-line react-hooks/rules-of-hooks
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => {
// Explicit false means don't do anything (used for submissions)
if (restoreScrollPosition === false) {
return;
}
// been here before, scroll to it
if (typeof restoreScrollPosition === "number") {
window.scrollTo(0, restoreScrollPosition);
return;
}
// try to scroll to the hash
if (location.hash) {
let el = document.getElementById(decodeURIComponent(location.hash.slice(1)));
if (el) {
el.scrollIntoView();
return;
}
}
// Don't reset if this navigation opted out
if (preventScrollReset === true) {
return;
}
// otherwise go to the top on new locations
window.scrollTo(0, 0);
}, [location, restoreScrollPosition, preventScrollReset]);
}
}
/**
* Setup a callback to be fired on the window's `beforeunload` event. This is
* useful for saving some data to `window.localStorage` just before the page
* refreshes.
*
* Note: The `callback` argument should be a function created with
* `React.useCallback()`.
*/
function useBeforeUnload(callback, options) {
let {
capture
} = options || {};
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
let opts = capture != null ? {
capture
} : undefined;
window.addEventListener("beforeunload", callback, opts);
return () => {
window.removeEventListener("beforeunload", callback, opts);
};
}, [callback, capture]);
}
/**
* Setup a callback to be fired on the window's `pagehide` event. This is
* useful for saving some data to `window.localStorage` just before the page
* refreshes. This event is better supported than beforeunload across browsers.
*
* Note: The `callback` argument should be a function created with
* `React.useCallback()`.
*/
function usePageHide(callback, options) {
let {
capture
} = options || {};
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
let opts = capture != null ? {
capture
} : undefined;
window.addEventListener("pagehide", callback, opts);
return () => {
window.removeEventListener("pagehide", callback, opts);
};
}, [callback, capture]);
}
/**
* Wrapper around useBlocker to show a window.confirm prompt to users instead
* of building a custom UI with useBlocker.
*
* Warning: This has *a lot of rough edges* and behaves very differently (and
* very incorrectly in some cases) across browsers if user click addition
* back/forward navigations while the confirm is open. Use at your own risk.
*/
function usePrompt(_ref12) {
let {
when,
message
} = _ref12;
let blocker = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useBlocker)(when);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (blocker.state === "blocked") {
let proceed = window.confirm(message);
if (proceed) {
// This timeout is needed to avoid a weird "race" on POP navigations
// between the `window.history` revert navigation and the result of
// `window.confirm`
setTimeout(blocker.proceed, 0);
} else {
blocker.reset();
}
}
}, [blocker, message]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (blocker.state === "blocked" && !when) {
blocker.reset();
}
}, [blocker, when]);
}
/**
* Return a boolean indicating if there is an active view transition to the
* given href. You can use this value to render CSS classes or viewTransitionName
* styles onto your elements
*
* @param href The destination href
* @param [opts.relative] Relative routing type ("route" | "path")
*/
function useViewTransitionState(to, opts) {
if (opts === void 0) {
opts = {};
}
let vtContext = react__WEBPACK_IMPORTED_MODULE_0__.useContext(ViewTransitionContext);
!(vtContext != null) ? true ? (0,react_router__WEBPACK_IMPORTED_MODULE_2__.UNSAFE_invariant)(false, "`unstable_useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. " + "Did you accidentally import `RouterProvider` from `react-router`?") : 0 : void 0;
let {
basename
} = useDataRouterContext(DataRouterHook.useViewTransitionState);
let path = (0,react_router__WEBPACK_IMPORTED_MODULE_3__.useResolvedPath)(to, {
relative: opts.relative
});
if (!vtContext.isTransitioning) {
return false;
}
let currentPath = (0,react_router__WEBPACK_IMPORTED_MODULE_2__.stripBasename)(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
let nextPath = (0,react_router__WEBPACK_IMPORTED_MODULE_2__.stripBasename)(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
// Transition is active if we're going to or coming from the indicated
// destination. This ensures that other PUSH navigations that reverse
// an indicated transition apply. I.e., on the list view you have:
//
// <NavLink to="/details/1" unstable_viewTransition>
//
// If you click the breadcrumb back to the list view:
//
// <NavLink to="/list" unstable_viewTransition>
//
// We should apply the transition because it's indicated as active going
// from /list -> /details/1 and therefore should be active on the reverse
// (even though this isn't strictly a POP reverse)
return (0,react_router__WEBPACK_IMPORTED_MODULE_2__.matchPath)(path.pathname, nextPath) != null || (0,react_router__WEBPACK_IMPORTED_MODULE_2__.matchPath)(path.pathname, currentPath) != null;
}
//#endregion
//# sourceMappingURL=index.js.map
/***/ }),
/***/ "./node_modules/react-router/dist/index.js":
/*!*************************************************!*\
!*** ./node_modules/react-router/dist/index.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ AbortedDeferredError: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.AbortedDeferredError),
/* harmony export */ Await: () => (/* binding */ Await),
/* harmony export */ MemoryRouter: () => (/* binding */ MemoryRouter),
/* harmony export */ Navigate: () => (/* binding */ Navigate),
/* harmony export */ NavigationType: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.Action),
/* harmony export */ Outlet: () => (/* binding */ Outlet),
/* harmony export */ Route: () => (/* binding */ Route),
/* harmony export */ Router: () => (/* binding */ Router),
/* harmony export */ RouterProvider: () => (/* binding */ RouterProvider),
/* harmony export */ Routes: () => (/* binding */ Routes),
/* harmony export */ UNSAFE_DataRouterContext: () => (/* binding */ DataRouterContext),
/* harmony export */ UNSAFE_DataRouterStateContext: () => (/* binding */ DataRouterStateContext),
/* harmony export */ UNSAFE_LocationContext: () => (/* binding */ LocationContext),
/* harmony export */ UNSAFE_NavigationContext: () => (/* binding */ NavigationContext),
/* harmony export */ UNSAFE_RouteContext: () => (/* binding */ RouteContext),
/* harmony export */ UNSAFE_mapRouteProperties: () => (/* binding */ mapRouteProperties),
/* harmony export */ UNSAFE_useRouteId: () => (/* binding */ useRouteId),
/* harmony export */ UNSAFE_useRoutesImpl: () => (/* binding */ useRoutesImpl),
/* harmony export */ createMemoryRouter: () => (/* binding */ createMemoryRouter),
/* harmony export */ createPath: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.createPath),
/* harmony export */ createRoutesFromChildren: () => (/* binding */ createRoutesFromChildren),
/* harmony export */ createRoutesFromElements: () => (/* binding */ createRoutesFromChildren),
/* harmony export */ defer: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.defer),
/* harmony export */ generatePath: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.generatePath),
/* harmony export */ isRouteErrorResponse: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.isRouteErrorResponse),
/* harmony export */ json: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.json),
/* harmony export */ matchPath: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.matchPath),
/* harmony export */ matchRoutes: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.matchRoutes),
/* harmony export */ parsePath: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.parsePath),
/* harmony export */ redirect: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.redirect),
/* harmony export */ redirectDocument: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.redirectDocument),
/* harmony export */ renderMatches: () => (/* binding */ renderMatches),
/* harmony export */ resolvePath: () => (/* reexport safe */ _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.resolvePath),
/* harmony export */ useActionData: () => (/* binding */ useActionData),
/* harmony export */ useAsyncError: () => (/* binding */ useAsyncError),
/* harmony export */ useAsyncValue: () => (/* binding */ useAsyncValue),
/* harmony export */ useBlocker: () => (/* binding */ useBlocker),
/* harmony export */ useHref: () => (/* binding */ useHref),
/* harmony export */ useInRouterContext: () => (/* binding */ useInRouterContext),
/* harmony export */ useLoaderData: () => (/* binding */ useLoaderData),
/* harmony export */ useLocation: () => (/* binding */ useLocation),
/* harmony export */ useMatch: () => (/* binding */ useMatch),
/* harmony export */ useMatches: () => (/* binding */ useMatches),
/* harmony export */ useNavigate: () => (/* binding */ useNavigate),
/* harmony export */ useNavigation: () => (/* binding */ useNavigation),
/* harmony export */ useNavigationType: () => (/* binding */ useNavigationType),
/* harmony export */ useOutlet: () => (/* binding */ useOutlet),
/* harmony export */ useOutletContext: () => (/* binding */ useOutletContext),
/* harmony export */ useParams: () => (/* binding */ useParams),
/* harmony export */ useResolvedPath: () => (/* binding */ useResolvedPath),
/* harmony export */ useRevalidator: () => (/* binding */ useRevalidator),
/* harmony export */ useRouteError: () => (/* binding */ useRouteError),
/* harmony export */ useRouteLoaderData: () => (/* binding */ useRouteLoaderData),
/* harmony export */ useRoutes: () => (/* binding */ useRoutes)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _remix_run_router__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @remix-run/router */ "./node_modules/@remix-run/router/dist/router.js");
/**
* React Router v6.21.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 _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);
}
// Create react-specific types from the agnostic types in @remix-run/router to
// export from react-router
const DataRouterContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
if (true) {
DataRouterContext.displayName = "DataRouter";
}
const DataRouterStateContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
if (true) {
DataRouterStateContext.displayName = "DataRouterState";
}
const AwaitContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
if (true) {
AwaitContext.displayName = "Await";
}
/**
* A Navigator is a "location changer"; it's how you get to different locations.
*
* Every history instance conforms to the Navigator interface, but the
* distinction is useful primarily when it comes to the low-level `<Router>` API
* where both the location and a navigator must be provided separately in order
* to avoid "tearing" that may occur in a suspense-enabled app if the action
* and/or location were to be read directly from the history instance.
*/
const NavigationContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
if (true) {
NavigationContext.displayName = "Navigation";
}
const LocationContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
if (true) {
LocationContext.displayName = "Location";
}
const RouteContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext({
outlet: null,
matches: [],
isDataRoute: false
});
if (true) {
RouteContext.displayName = "Route";
}
const RouteErrorContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
if (true) {
RouteErrorContext.displayName = "RouteError";
}
/**
* Returns the full href for the given "to" value. This is useful for building
* custom links that are also accessible and preserve right-click behavior.
*
* @see https://reactrouter.com/hooks/use-href
*/
function useHref(to, _temp) {
let {
relative
} = _temp === void 0 ? {} : _temp;
!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useHref() may be used only in the context of a <Router> component.") : 0 : void 0;
let {
basename,
navigator
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(NavigationContext);
let {
hash,
pathname,
search
} = useResolvedPath(to, {
relative
});
let joinedPathname = pathname;
// If we're operating within a basename, prepend it to the pathname prior
// to creating the href. If this is a root navigation, then just use the raw
// basename which allows the basename to have full control over the presence
// of a trailing slash on root links
if (basename !== "/") {
joinedPathname = pathname === "/" ? basename : (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.joinPaths)([basename, pathname]);
}
return navigator.createHref({
pathname: joinedPathname,
search,
hash
});
}
/**
* Returns true if this component is a descendant of a `<Router>`.
*
* @see https://reactrouter.com/hooks/use-in-router-context
*/
function useInRouterContext() {
return react__WEBPACK_IMPORTED_MODULE_0__.useContext(LocationContext) != null;
}
/**
* Returns the current location object, which represents the current URL in web
* browsers.
*
* Note: If you're using this it may mean you're doing some of your own
* "routing" in your app, and we'd like to know what your use case is. We may
* be able to provide something higher-level to better suit your needs.
*
* @see https://reactrouter.com/hooks/use-location
*/
function useLocation() {
!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useLocation() may be used only in the context of a <Router> component.") : 0 : void 0;
return react__WEBPACK_IMPORTED_MODULE_0__.useContext(LocationContext).location;
}
/**
* Returns the current navigation action which describes how the router came to
* the current location, either by a pop, push, or replace on the history stack.
*
* @see https://reactrouter.com/hooks/use-navigation-type
*/
function useNavigationType() {
return react__WEBPACK_IMPORTED_MODULE_0__.useContext(LocationContext).navigationType;
}
/**
* Returns a PathMatch object if the given pattern matches the current URL.
* This is useful for components that need to know "active" state, e.g.
* `<NavLink>`.
*
* @see https://reactrouter.com/hooks/use-match
*/
function useMatch(pattern) {
!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useMatch() may be used only in the context of a <Router> component.") : 0 : void 0;
let {
pathname
} = useLocation();
return react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.matchPath)(pattern, pathname), [pathname, pattern]);
}
/**
* The interface for the navigate() function returned from useNavigate().
*/
const navigateEffectWarning = "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered.";
// Mute warnings for calls to useNavigate in SSR environments
function useIsomorphicLayoutEffect(cb) {
let isStatic = react__WEBPACK_IMPORTED_MODULE_0__.useContext(NavigationContext).static;
if (!isStatic) {
// We should be able to get rid of this once react 18.3 is released
// See: https://github.com/facebook/react/pull/26395
// eslint-disable-next-line react-hooks/rules-of-hooks
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(cb);
}
}
/**
* Returns an imperative method for changing the location. Used by `<Link>`s, but
* may also be used by other elements to change the location.
*
* @see https://reactrouter.com/hooks/use-navigate
*/
function useNavigate() {
let {
isDataRoute
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
// Conditional usage is OK here because the usage of a data router is static
// eslint-disable-next-line react-hooks/rules-of-hooks
return isDataRoute ? useNavigateStable() : useNavigateUnstable();
}
function useNavigateUnstable() {
!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useNavigate() may be used only in the context of a <Router> component.") : 0 : void 0;
let dataRouterContext = react__WEBPACK_IMPORTED_MODULE_0__.useContext(DataRouterContext);
let {
basename,
future,
navigator
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(NavigationContext);
let {
matches
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
let {
pathname: locationPathname
} = useLocation();
let routePathnamesJson = JSON.stringify((0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_getResolveToMatches)(matches, future.v7_relativeSplatPath));
let activeRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(false);
useIsomorphicLayoutEffect(() => {
activeRef.current = true;
});
let navigate = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(function (to, options) {
if (options === void 0) {
options = {};
}
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(activeRef.current, navigateEffectWarning) : 0;
// Short circuit here since if this happens on first render the navigate
// is useless because we haven't wired up our history listener yet
if (!activeRef.current) return;
if (typeof to === "number") {
navigator.go(to);
return;
}
let path = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.resolveTo)(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
// If we're operating within a basename, prepend it to the pathname prior
// to handing off to history (but only if we're not in a data router,
// otherwise it'll prepend the basename inside of the router).
// If this is a root navigation, then we navigate to the raw basename
// which allows the basename to have full control over the presence of a
// trailing slash on root links
if (dataRouterContext == null && basename !== "/") {
path.pathname = path.pathname === "/" ? basename : (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.joinPaths)([basename, path.pathname]);
}
(!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
}, [basename, navigator, routePathnamesJson, locationPathname, dataRouterContext]);
return navigate;
}
const OutletContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
/**
* Returns the context (if provided) for the child route at this level of the route
* hierarchy.
* @see https://reactrouter.com/hooks/use-outlet-context
*/
function useOutletContext() {
return react__WEBPACK_IMPORTED_MODULE_0__.useContext(OutletContext);
}
/**
* Returns the element for the child route at this level of the route
* hierarchy. Used internally by `<Outlet>` to render child routes.
*
* @see https://reactrouter.com/hooks/use-outlet
*/
function useOutlet(context) {
let outlet = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext).outlet;
if (outlet) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(OutletContext.Provider, {
value: context
}, outlet);
}
return outlet;
}
/**
* Returns an object of key/value pairs of the dynamic params from the current
* URL that were matched by the route path.
*
* @see https://reactrouter.com/hooks/use-params
*/
function useParams() {
let {
matches
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
let routeMatch = matches[matches.length - 1];
return routeMatch ? routeMatch.params : {};
}
/**
* Resolves the pathname of the given `to` value against the current location.
*
* @see https://reactrouter.com/hooks/use-resolved-path
*/
function useResolvedPath(to, _temp2) {
let {
relative
} = _temp2 === void 0 ? {} : _temp2;
let {
future
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(NavigationContext);
let {
matches
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
let {
pathname: locationPathname
} = useLocation();
let routePathnamesJson = JSON.stringify((0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_getResolveToMatches)(matches, future.v7_relativeSplatPath));
return react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.resolveTo)(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
}
/**
* Returns the element of the route that matched the current location, prepared
* with the correct context to render the remainder of the route tree. Route
* elements in the tree must render an `<Outlet>` to render their child route's
* element.
*
* @see https://reactrouter.com/hooks/use-routes
*/
function useRoutes(routes, locationArg) {
return useRoutesImpl(routes, locationArg);
}
// Internal implementation with accept optional param for RouterProvider usage
function useRoutesImpl(routes, locationArg, dataRouterState, future) {
!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, // TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
"useRoutes() may be used only in the context of a <Router> component.") : 0 : void 0;
let {
navigator
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(NavigationContext);
let {
matches: parentMatches
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
let routeMatch = parentMatches[parentMatches.length - 1];
let parentParams = routeMatch ? routeMatch.params : {};
let parentPathname = routeMatch ? routeMatch.pathname : "/";
let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/";
let parentRoute = routeMatch && routeMatch.route;
if (true) {
// You won't get a warning about 2 different <Routes> under a <Route>
// without a trailing *, but this is a best-effort warning anyway since we
// cannot even give the warning unless they land at the parent route.
//
// Example:
//
// <Routes>
// {/* This route path MUST end with /* because otherwise
// it will never match /blog/post/123 */}
// <Route path="blog" element={<Blog />} />
// <Route path="blog/feed" element={<BlogFeed />} />
// </Routes>
//
// function Blog() {
// return (
// <Routes>
// <Route path="post/:id" element={<Post />} />
// </Routes>
// );
// }
let parentPath = parentRoute && parentRoute.path || "";
warningOnce(parentPathname, !parentRoute || parentPath.endsWith("*"), "You rendered descendant <Routes> (or called `useRoutes()`) at " + ("\"" + parentPathname + "\" (under <Route path=\"" + parentPath + "\">) but the ") + "parent route path has no trailing \"*\". This means if you navigate " + "deeper, the parent won't match anymore and therefore the child " + "routes will never render.\n\n" + ("Please change the parent <Route path=\"" + parentPath + "\"> to <Route ") + ("path=\"" + (parentPath === "/" ? "*" : parentPath + "/*") + "\">."));
}
let locationFromContext = useLocation();
let location;
if (locationArg) {
var _parsedLocationArg$pa;
let parsedLocationArg = typeof locationArg === "string" ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.parsePath)(locationArg) : locationArg;
!(parentPathnameBase === "/" || ((_parsedLocationArg$pa = parsedLocationArg.pathname) == null ? void 0 : _parsedLocationArg$pa.startsWith(parentPathnameBase))) ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, "When overriding the location using `<Routes location>` or `useRoutes(routes, location)`, " + "the location pathname must begin with the portion of the URL pathname that was " + ("matched by all parent routes. The current pathname base is \"" + parentPathnameBase + "\" ") + ("but pathname \"" + parsedLocationArg.pathname + "\" was given in the `location` prop.")) : 0 : void 0;
location = parsedLocationArg;
} else {
location = locationFromContext;
}
let pathname = location.pathname || "/";
let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
let matches = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.matchRoutes)(routes, {
pathname: remainingPathname
});
if (true) {
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(parentRoute || matches != null, "No routes matched location \"" + location.pathname + location.search + location.hash + "\" ") : 0;
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(matches == null || matches[matches.length - 1].route.element !== undefined || matches[matches.length - 1].route.Component !== undefined || matches[matches.length - 1].route.lazy !== undefined, "Matched leaf route at location \"" + location.pathname + location.search + location.hash + "\" " + "does not have an element or Component. This means it will render an <Outlet /> with a " + "null value by default resulting in an \"empty\" page.") : 0;
}
let renderedMatches = _renderMatches(matches && matches.map(match => Object.assign({}, match, {
params: Object.assign({}, parentParams, match.params),
pathname: (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.joinPaths)([parentPathnameBase,
// Re-encode pathnames that were decoded inside matchRoutes
navigator.encodeLocation ? navigator.encodeLocation(match.pathname).pathname : match.pathname]),
pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.joinPaths)([parentPathnameBase,
// Re-encode pathnames that were decoded inside matchRoutes
navigator.encodeLocation ? navigator.encodeLocation(match.pathnameBase).pathname : match.pathnameBase])
})), parentMatches, dataRouterState, future);
// When a user passes in a `locationArg`, the associated routes need to
// be wrapped in a new `LocationContext.Provider` in order for `useLocation`
// to use the scoped location instead of the global location.
if (locationArg && renderedMatches) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(LocationContext.Provider, {
value: {
location: _extends({
pathname: "/",
search: "",
hash: "",
state: null,
key: "default"
}, location),
navigationType: _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.Action.Pop
}
}, renderedMatches);
}
return renderedMatches;
}
function DefaultErrorComponent() {
let error = useRouteError();
let message = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.isRouteErrorResponse)(error) ? error.status + " " + error.statusText : error instanceof Error ? error.message : JSON.stringify(error);
let stack = error instanceof Error ? error.stack : null;
let lightgrey = "rgba(200,200,200, 0.5)";
let preStyles = {
padding: "0.5rem",
backgroundColor: lightgrey
};
let codeStyles = {
padding: "2px 4px",
backgroundColor: lightgrey
};
let devInfo = null;
if (true) {
console.error("Error handled by React Router default ErrorBoundary:", error);
devInfo = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("p", null, "\uD83D\uDCBF Hey developer \uD83D\uDC4B"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("code", {
style: codeStyles
}, "ErrorBoundary"), " or", " ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("code", {
style: codeStyles
}, "errorElement"), " prop on your route."));
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("h2", null, "Unexpected Application Error!"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("h3", {
style: {
fontStyle: "italic"
}
}, message), stack ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("pre", {
style: preStyles
}, stack) : null, devInfo);
}
const defaultErrorElement = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(DefaultErrorComponent, null);
class RenderErrorBoundary extends react__WEBPACK_IMPORTED_MODULE_0__.Component {
constructor(props) {
super(props);
this.state = {
location: props.location,
revalidation: props.revalidation,
error: props.error
};
}
static getDerivedStateFromError(error) {
return {
error: error
};
}
static getDerivedStateFromProps(props, state) {
// When we get into an error state, the user will likely click "back" to the
// previous page that didn't have an error. Because this wraps the entire
// application, that will have no effect--the error page continues to display.
// This gives us a mechanism to recover from the error when the location changes.
//
// Whether we're in an error state or not, we update the location in state
// so that when we are in an error state, it gets reset when a new location
// comes in and the user recovers from the error.
if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") {
return {
error: props.error,
location: props.location,
revalidation: props.revalidation
};
}
// If we're not changing locations, preserve the location but still surface
// any new errors that may come through. We retain the existing error, we do
// this because the error provided from the app state may be cleared without
// the location changing.
return {
error: props.error !== undefined ? props.error : state.error,
location: state.location,
revalidation: props.revalidation || state.revalidation
};
}
componentDidCatch(error, errorInfo) {
console.error("React Router caught the following error during render", error, errorInfo);
}
render() {
return this.state.error !== undefined ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(RouteContext.Provider, {
value: this.props.routeContext
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(RouteErrorContext.Provider, {
value: this.state.error,
children: this.props.component
})) : this.props.children;
}
}
function RenderedRoute(_ref) {
let {
routeContext,
match,
children
} = _ref;
let dataRouterContext = react__WEBPACK_IMPORTED_MODULE_0__.useContext(DataRouterContext);
// Track how deep we got in our render pass to emulate SSR componentDidCatch
// in a DataStaticRouter
if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) {
dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id;
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(RouteContext.Provider, {
value: routeContext
}, children);
}
function _renderMatches(matches, parentMatches, dataRouterState, future) {
var _dataRouterState2;
if (parentMatches === void 0) {
parentMatches = [];
}
if (dataRouterState === void 0) {
dataRouterState = null;
}
if (future === void 0) {
future = null;
}
if (matches == null) {
var _dataRouterState;
if ((_dataRouterState = dataRouterState) != null && _dataRouterState.errors) {
// Don't bail if we have data router errors so we can render them in the
// boundary. Use the pre-matched (or shimmed) matches
matches = dataRouterState.matches;
} else {
return null;
}
}
let renderedMatches = matches;
// If we have data errors, trim matches to the highest error boundary
let errors = (_dataRouterState2 = dataRouterState) == null ? void 0 : _dataRouterState2.errors;
if (errors != null) {
let errorIndex = renderedMatches.findIndex(m => m.route.id && (errors == null ? void 0 : errors[m.route.id]));
!(errorIndex >= 0) ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, "Could not find a matching route for errors on route IDs: " + Object.keys(errors).join(",")) : 0 : void 0;
renderedMatches = renderedMatches.slice(0, Math.min(renderedMatches.length, errorIndex + 1));
}
// If we're in a partial hydration mode, detect if we need to render down to
// a given HydrateFallback while we load the rest of the hydration data
let renderFallback = false;
let fallbackIndex = -1;
if (dataRouterState && future && future.v7_partialHydration) {
for (let i = 0; i < renderedMatches.length; i++) {
let match = renderedMatches[i];
// Track the deepest fallback up until the first route without data
if (match.route.HydrateFallback || match.route.hydrateFallbackElement) {
fallbackIndex = i;
}
if (match.route.id) {
let {
loaderData,
errors
} = dataRouterState;
let needsToRunLoader = match.route.loader && loaderData[match.route.id] === undefined && (!errors || errors[match.route.id] === undefined);
if (match.route.lazy || needsToRunLoader) {
// We found the first route that's not ready to render (waiting on
// lazy, or has a loader that hasn't run yet). Flag that we need to
// render a fallback and render up until the appropriate fallback
renderFallback = true;
if (fallbackIndex >= 0) {
renderedMatches = renderedMatches.slice(0, fallbackIndex + 1);
} else {
renderedMatches = [renderedMatches[0]];
}
break;
}
}
}
}
return renderedMatches.reduceRight((outlet, match, index) => {
// Only data routers handle errors/fallbacks
let error;
let shouldRenderHydrateFallback = false;
let errorElement = null;
let hydrateFallbackElement = null;
if (dataRouterState) {
error = errors && match.route.id ? errors[match.route.id] : undefined;
errorElement = match.route.errorElement || defaultErrorElement;
if (renderFallback) {
if (fallbackIndex < 0 && index === 0) {
warningOnce("route-fallback", false, "No `HydrateFallback` element provided to render during initial hydration");
shouldRenderHydrateFallback = true;
hydrateFallbackElement = null;
} else if (fallbackIndex === index) {
shouldRenderHydrateFallback = true;
hydrateFallbackElement = match.route.hydrateFallbackElement || null;
}
}
}
let matches = parentMatches.concat(renderedMatches.slice(0, index + 1));
let getChildren = () => {
let children;
if (error) {
children = errorElement;
} else if (shouldRenderHydrateFallback) {
children = hydrateFallbackElement;
} else if (match.route.Component) {
// Note: This is a de-optimized path since React won't re-use the
// ReactElement since it's identity changes with each new
// React.createElement call. We keep this so folks can use
// `<Route Component={...}>` in `<Routes>` but generally `Component`
// usage is only advised in `RouterProvider` when we can convert it to
// `element` ahead of time.
children = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(match.route.Component, null);
} else if (match.route.element) {
children = match.route.element;
} else {
children = outlet;
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(RenderedRoute, {
match: match,
routeContext: {
outlet,
matches,
isDataRoute: dataRouterState != null
},
children: children
});
};
// Only wrap in an error boundary within data router usages when we have an
// ErrorBoundary/errorElement on this route. Otherwise let it bubble up to
// an ancestor ErrorBoundary/errorElement
return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(RenderErrorBoundary, {
location: dataRouterState.location,
revalidation: dataRouterState.revalidation,
component: errorElement,
error: error,
children: getChildren(),
routeContext: {
outlet: null,
matches,
isDataRoute: true
}
}) : getChildren();
}, null);
}
var DataRouterHook = /*#__PURE__*/function (DataRouterHook) {
DataRouterHook["UseBlocker"] = "useBlocker";
DataRouterHook["UseRevalidator"] = "useRevalidator";
DataRouterHook["UseNavigateStable"] = "useNavigate";
return DataRouterHook;
}(DataRouterHook || {});
var DataRouterStateHook = /*#__PURE__*/function (DataRouterStateHook) {
DataRouterStateHook["UseBlocker"] = "useBlocker";
DataRouterStateHook["UseLoaderData"] = "useLoaderData";
DataRouterStateHook["UseActionData"] = "useActionData";
DataRouterStateHook["UseRouteError"] = "useRouteError";
DataRouterStateHook["UseNavigation"] = "useNavigation";
DataRouterStateHook["UseRouteLoaderData"] = "useRouteLoaderData";
DataRouterStateHook["UseMatches"] = "useMatches";
DataRouterStateHook["UseRevalidator"] = "useRevalidator";
DataRouterStateHook["UseNavigateStable"] = "useNavigate";
DataRouterStateHook["UseRouteId"] = "useRouteId";
return DataRouterStateHook;
}(DataRouterStateHook || {});
function getDataRouterConsoleError(hookName) {
return hookName + " must be used within a data router. See https://reactrouter.com/routers/picking-a-router.";
}
function useDataRouterContext(hookName) {
let ctx = react__WEBPACK_IMPORTED_MODULE_0__.useContext(DataRouterContext);
!ctx ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, getDataRouterConsoleError(hookName)) : 0 : void 0;
return ctx;
}
function useDataRouterState(hookName) {
let state = react__WEBPACK_IMPORTED_MODULE_0__.useContext(DataRouterStateContext);
!state ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, getDataRouterConsoleError(hookName)) : 0 : void 0;
return state;
}
function useRouteContext(hookName) {
let route = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
!route ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, getDataRouterConsoleError(hookName)) : 0 : void 0;
return route;
}
// Internal version with hookName-aware debugging
function useCurrentRouteId(hookName) {
let route = useRouteContext(hookName);
let thisRoute = route.matches[route.matches.length - 1];
!thisRoute.route.id ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, hookName + " can only be used on routes that contain a unique \"id\"") : 0 : void 0;
return thisRoute.route.id;
}
/**
* Returns the ID for the nearest contextual route
*/
function useRouteId() {
return useCurrentRouteId(DataRouterStateHook.UseRouteId);
}
/**
* Returns the current navigation, defaulting to an "idle" navigation when
* no navigation is in progress
*/
function useNavigation() {
let state = useDataRouterState(DataRouterStateHook.UseNavigation);
return state.navigation;
}
/**
* Returns a revalidate function for manually triggering revalidation, as well
* as the current state of any manual revalidations
*/
function useRevalidator() {
let dataRouterContext = useDataRouterContext(DataRouterHook.UseRevalidator);
let state = useDataRouterState(DataRouterStateHook.UseRevalidator);
return react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => ({
revalidate: dataRouterContext.router.revalidate,
state: state.revalidation
}), [dataRouterContext.router.revalidate, state.revalidation]);
}
/**
* Returns the active route matches, useful for accessing loaderData for
* parent/child routes or the route "handle" property
*/
function useMatches() {
let {
matches,
loaderData
} = useDataRouterState(DataRouterStateHook.UseMatches);
return react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => matches.map(m => (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_convertRouteMatchToUiMatch)(m, loaderData)), [matches, loaderData]);
}
/**
* Returns the loader data for the nearest ancestor Route loader
*/
function useLoaderData() {
let state = useDataRouterState(DataRouterStateHook.UseLoaderData);
let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
if (state.errors && state.errors[routeId] != null) {
console.error("You cannot `useLoaderData` in an errorElement (routeId: " + routeId + ")");
return undefined;
}
return state.loaderData[routeId];
}
/**
* Returns the loaderData for the given routeId
*/
function useRouteLoaderData(routeId) {
let state = useDataRouterState(DataRouterStateHook.UseRouteLoaderData);
return state.loaderData[routeId];
}
/**
* Returns the action data for the nearest ancestor Route action
*/
function useActionData() {
let state = useDataRouterState(DataRouterStateHook.UseActionData);
let routeId = useCurrentRouteId(DataRouterStateHook.UseLoaderData);
return state.actionData ? state.actionData[routeId] : undefined;
}
/**
* Returns the nearest ancestor Route error, which could be a loader/action
* error or a render error. This is intended to be called from your
* ErrorBoundary/errorElement to display a proper error message.
*/
function useRouteError() {
var _state$errors;
let error = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteErrorContext);
let state = useDataRouterState(DataRouterStateHook.UseRouteError);
let routeId = useCurrentRouteId(DataRouterStateHook.UseRouteError);
// If this was a render error, we put it in a RouteError context inside
// of RenderErrorBoundary
if (error !== undefined) {
return error;
}
// Otherwise look for errors from our data router state
return (_state$errors = state.errors) == null ? void 0 : _state$errors[routeId];
}
/**
* Returns the happy-path data from the nearest ancestor `<Await />` value
*/
function useAsyncValue() {
let value = react__WEBPACK_IMPORTED_MODULE_0__.useContext(AwaitContext);
return value == null ? void 0 : value._data;
}
/**
* Returns the error from the nearest ancestor `<Await />` value
*/
function useAsyncError() {
let value = react__WEBPACK_IMPORTED_MODULE_0__.useContext(AwaitContext);
return value == null ? void 0 : value._error;
}
let blockerId = 0;
/**
* Allow the application to block navigations within the SPA and present the
* user a confirmation dialog to confirm the navigation. Mostly used to avoid
* using half-filled form data. This does not handle hard-reloads or
* cross-origin navigations.
*/
function useBlocker(shouldBlock) {
let {
router,
basename
} = useDataRouterContext(DataRouterHook.UseBlocker);
let state = useDataRouterState(DataRouterStateHook.UseBlocker);
let [blockerKey, setBlockerKey] = react__WEBPACK_IMPORTED_MODULE_0__.useState("");
let blockerFunction = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(arg => {
if (typeof shouldBlock !== "function") {
return !!shouldBlock;
}
if (basename === "/") {
return shouldBlock(arg);
}
// If they provided us a function and we've got an active basename, strip
// it from the locations we expose to the user to match the behavior of
// useLocation
let {
currentLocation,
nextLocation,
historyAction
} = arg;
return shouldBlock({
currentLocation: _extends({}, currentLocation, {
pathname: (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.stripBasename)(currentLocation.pathname, basename) || currentLocation.pathname
}),
nextLocation: _extends({}, nextLocation, {
pathname: (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.stripBasename)(nextLocation.pathname, basename) || nextLocation.pathname
}),
historyAction
});
}, [basename, shouldBlock]);
// This effect is in charge of blocker key assignment and deletion (which is
// tightly coupled to the key)
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
let key = String(++blockerId);
setBlockerKey(key);
return () => router.deleteBlocker(key);
}, [router]);
// This effect handles assigning the blockerFunction. This is to handle
// unstable blocker function identities, and happens only after the prior
// effect so we don't get an orphaned blockerFunction in the router with a
// key of "". Until then we just have the IDLE_BLOCKER.
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (blockerKey !== "") {
router.getBlocker(blockerKey, blockerFunction);
}
}, [router, blockerKey, blockerFunction]);
// Prefer the blocker from `state` not `router.state` since DataRouterContext
// is memoized so this ensures we update on blocker state updates
return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.IDLE_BLOCKER;
}
/**
* Stable version of useNavigate that is used when we are in the context of
* a RouterProvider.
*/
function useNavigateStable() {
let {
router
} = useDataRouterContext(DataRouterHook.UseNavigateStable);
let id = useCurrentRouteId(DataRouterStateHook.UseNavigateStable);
let activeRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(false);
useIsomorphicLayoutEffect(() => {
activeRef.current = true;
});
let navigate = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(function (to, options) {
if (options === void 0) {
options = {};
}
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(activeRef.current, navigateEffectWarning) : 0;
// Short circuit here since if this happens on first render the navigate
// is useless because we haven't wired up our router subscriber yet
if (!activeRef.current) return;
if (typeof to === "number") {
router.navigate(to);
} else {
router.navigate(to, _extends({
fromRouteId: id
}, options));
}
}, [router, id]);
return navigate;
}
const alreadyWarned = {};
function warningOnce(key, cond, message) {
if (!cond && !alreadyWarned[key]) {
alreadyWarned[key] = true;
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(false, message) : 0;
}
}
/**
Webpack + React 17 fails to compile on any of the following because webpack
complains that `startTransition` doesn't exist in `React`:
* import { startTransition } from "react"
* import * as React from from "react";
"startTransition" in React ? React.startTransition(() => setState()) : setState()
* import * as React from from "react";
"startTransition" in React ? React["startTransition"](() => setState()) : setState()
Moving it to a constant such as the following solves the Webpack/React 17 issue:
* import * as React from from "react";
const START_TRANSITION = "startTransition";
START_TRANSITION in React ? React[START_TRANSITION](() => setState()) : setState()
However, that introduces webpack/terser minification issues in production builds
in React 18 where minification/obfuscation ends up removing the call of
React.startTransition entirely from the first half of the ternary. Grabbing
this exported reference once up front resolves that issue.
See https://github.com/remix-run/react-router/issues/10579
*/
const START_TRANSITION = "startTransition";
const startTransitionImpl = react__WEBPACK_IMPORTED_MODULE_0__[START_TRANSITION];
/**
* Given a Remix Router instance, render the appropriate UI
*/
function RouterProvider(_ref) {
let {
fallbackElement,
router,
future
} = _ref;
let [state, setStateImpl] = react__WEBPACK_IMPORTED_MODULE_0__.useState(router.state);
let {
v7_startTransition
} = future || {};
let setState = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(newState => {
if (v7_startTransition && startTransitionImpl) {
startTransitionImpl(() => setStateImpl(newState));
} else {
setStateImpl(newState);
}
}, [setStateImpl, v7_startTransition]);
// Need to use a layout effect here so we are subscribed early enough to
// pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(fallbackElement == null || !router.future.v7_partialHydration, "`<RouterProvider fallbackElement>` is deprecated when using " + "`v7_partialHydration`, use a `HydrateFallback` component instead") : 0;
// Only log this once on initial mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
let navigator = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => {
return {
createHref: router.createHref,
encodeLocation: router.encodeLocation,
go: n => router.navigate(n),
push: (to, state, opts) => router.navigate(to, {
state,
preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
}),
replace: (to, state, opts) => router.navigate(to, {
replace: true,
state,
preventScrollReset: opts == null ? void 0 : opts.preventScrollReset
})
};
}, [router]);
let basename = router.basename || "/";
let dataRouterContext = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => ({
router,
navigator,
static: false,
basename
}), [router, navigator, basename]);
// The fragment and {null} here are important! We need them to keep React 18's
// useId happy when we are server-rendering since we may have a <script> here
// containing the hydrated server-side staticContext (from StaticRouterProvider).
// useId relies on the component tree structure to generate deterministic id's
// so we need to ensure it remains the same on the client even though
// we don't need the <script> tag
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(DataRouterContext.Provider, {
value: dataRouterContext
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(DataRouterStateContext.Provider, {
value: state
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(Router, {
basename: basename,
location: state.location,
navigationType: state.historyAction,
navigator: navigator,
future: {
v7_relativeSplatPath: router.future.v7_relativeSplatPath
}
}, state.initialized || router.future.v7_partialHydration ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(DataRoutes, {
routes: router.routes,
future: router.future,
state: state
}) : fallbackElement))), null);
}
function DataRoutes(_ref2) {
let {
routes,
future,
state
} = _ref2;
return useRoutesImpl(routes, undefined, state, future);
}
/**
* A `<Router>` that stores all entries in memory.
*
* @see https://reactrouter.com/router-components/memory-router
*/
function MemoryRouter(_ref3) {
let {
basename,
children,
initialEntries,
initialIndex,
future
} = _ref3;
let historyRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef();
if (historyRef.current == null) {
historyRef.current = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.createMemoryHistory)({
initialEntries,
initialIndex,
v5Compat: true
});
}
let history = historyRef.current;
let [state, setStateImpl] = react__WEBPACK_IMPORTED_MODULE_0__.useState({
action: history.action,
location: history.location
});
let {
v7_startTransition
} = future || {};
let setState = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(newState => {
v7_startTransition && startTransitionImpl ? startTransitionImpl(() => setStateImpl(newState)) : setStateImpl(newState);
}, [setStateImpl, v7_startTransition]);
react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect(() => history.listen(setState), [history, setState]);
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(Router, {
basename: basename,
children: children,
location: state.location,
navigationType: state.action,
navigator: history,
future: future
});
}
/**
* Changes the current location.
*
* Note: This API is mostly useful in React.Component subclasses that are not
* able to use hooks. In functional components, we recommend you use the
* `useNavigate` hook instead.
*
* @see https://reactrouter.com/components/navigate
*/
function Navigate(_ref4) {
let {
to,
replace,
state,
relative
} = _ref4;
!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, // TODO: This error is probably because they somehow have 2 versions of
// the router loaded. We can help them understand how to avoid that.
"<Navigate> may be used only in the context of a <Router> component.") : 0 : void 0;
let {
future,
static: isStatic
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(NavigationContext);
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(!isStatic, "<Navigate> must not be used on the initial render in a <StaticRouter>. " + "This is a no-op, but you should modify your code so the <Navigate> is " + "only ever rendered in response to some user interaction or state change.") : 0;
let {
matches
} = react__WEBPACK_IMPORTED_MODULE_0__.useContext(RouteContext);
let {
pathname: locationPathname
} = useLocation();
let navigate = useNavigate();
// Resolve the path outside of the effect so that when effects run twice in
// StrictMode they navigate to the same place
let path = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.resolveTo)(to, (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_getResolveToMatches)(matches, future.v7_relativeSplatPath), locationPathname, relative === "path");
let jsonPath = JSON.stringify(path);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => navigate(JSON.parse(jsonPath), {
replace,
state,
relative
}), [navigate, jsonPath, relative, replace, state]);
return null;
}
/**
* Renders the child route's element, if there is one.
*
* @see https://reactrouter.com/components/outlet
*/
function Outlet(props) {
return useOutlet(props.context);
}
/**
* Declares an element that should be rendered at a certain URL path.
*
* @see https://reactrouter.com/components/route
*/
function Route(_props) {
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, "A <Route> is only ever to be used as the child of <Routes> element, " + "never rendered directly. Please wrap your <Route> in a <Routes>.") : 0 ;
}
/**
* Provides location context for the rest of the app.
*
* Note: You usually won't render a `<Router>` directly. Instead, you'll render a
* router that is more specific to your environment such as a `<BrowserRouter>`
* in web browsers or a `<StaticRouter>` for server rendering.
*
* @see https://reactrouter.com/router-components/router
*/
function Router(_ref5) {
let {
basename: basenameProp = "/",
children = null,
location: locationProp,
navigationType = _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.Action.Pop,
navigator,
static: staticProp = false,
future
} = _ref5;
!!useInRouterContext() ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, "You cannot render a <Router> inside another <Router>." + " You should never have more than one in your app.") : 0 : void 0;
// Preserve trailing slashes on basename, so we can let the user control
// the enforcement of trailing slashes throughout the app
let basename = basenameProp.replace(/^\/*/, "/");
let navigationContext = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => ({
basename,
navigator,
static: staticProp,
future: _extends({
v7_relativeSplatPath: false
}, future)
}), [basename, future, navigator, staticProp]);
if (typeof locationProp === "string") {
locationProp = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.parsePath)(locationProp);
}
let {
pathname = "/",
search = "",
hash = "",
state = null,
key = "default"
} = locationProp;
let locationContext = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => {
let trailingPathname = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.stripBasename)(pathname, basename);
if (trailingPathname == null) {
return null;
}
return {
location: {
pathname: trailingPathname,
search,
hash,
state,
key
},
navigationType
};
}, [basename, pathname, search, hash, state, key, navigationType]);
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(locationContext != null, "<Router basename=\"" + basename + "\"> is not able to match the URL " + ("\"" + pathname + search + hash + "\" because it does not start with the ") + "basename, so the <Router> won't render anything.") : 0;
if (locationContext == null) {
return null;
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(NavigationContext.Provider, {
value: navigationContext
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(LocationContext.Provider, {
children: children,
value: locationContext
}));
}
/**
* A container for a nested tree of `<Route>` elements that renders the branch
* that best matches the current location.
*
* @see https://reactrouter.com/components/routes
*/
function Routes(_ref6) {
let {
children,
location
} = _ref6;
return useRoutes(createRoutesFromChildren(children), location);
}
/**
* Component to use for rendering lazily loaded data from returning defer()
* in a loader function
*/
function Await(_ref7) {
let {
children,
errorElement,
resolve
} = _ref7;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(AwaitErrorBoundary, {
resolve: resolve,
errorElement: errorElement
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(ResolveAwait, null, children));
}
var AwaitRenderStatus = /*#__PURE__*/function (AwaitRenderStatus) {
AwaitRenderStatus[AwaitRenderStatus["pending"] = 0] = "pending";
AwaitRenderStatus[AwaitRenderStatus["success"] = 1] = "success";
AwaitRenderStatus[AwaitRenderStatus["error"] = 2] = "error";
return AwaitRenderStatus;
}(AwaitRenderStatus || {});
const neverSettledPromise = new Promise(() => {});
class AwaitErrorBoundary extends react__WEBPACK_IMPORTED_MODULE_0__.Component {
constructor(props) {
super(props);
this.state = {
error: null
};
}
static getDerivedStateFromError(error) {
return {
error
};
}
componentDidCatch(error, errorInfo) {
console.error("<Await> caught the following error during render", error, errorInfo);
}
render() {
let {
children,
errorElement,
resolve
} = this.props;
let promise = null;
let status = AwaitRenderStatus.pending;
if (!(resolve instanceof Promise)) {
// Didn't get a promise - provide as a resolved promise
status = AwaitRenderStatus.success;
promise = Promise.resolve();
Object.defineProperty(promise, "_tracked", {
get: () => true
});
Object.defineProperty(promise, "_data", {
get: () => resolve
});
} else if (this.state.error) {
// Caught a render error, provide it as a rejected promise
status = AwaitRenderStatus.error;
let renderError = this.state.error;
promise = Promise.reject().catch(() => {}); // Avoid unhandled rejection warnings
Object.defineProperty(promise, "_tracked", {
get: () => true
});
Object.defineProperty(promise, "_error", {
get: () => renderError
});
} else if (resolve._tracked) {
// Already tracked promise - check contents
promise = resolve;
status = promise._error !== undefined ? AwaitRenderStatus.error : promise._data !== undefined ? AwaitRenderStatus.success : AwaitRenderStatus.pending;
} else {
// Raw (untracked) promise - track it
status = AwaitRenderStatus.pending;
Object.defineProperty(resolve, "_tracked", {
get: () => true
});
promise = resolve.then(data => Object.defineProperty(resolve, "_data", {
get: () => data
}), error => Object.defineProperty(resolve, "_error", {
get: () => error
}));
}
if (status === AwaitRenderStatus.error && promise._error instanceof _remix_run_router__WEBPACK_IMPORTED_MODULE_1__.AbortedDeferredError) {
// Freeze the UI by throwing a never resolved promise
throw neverSettledPromise;
}
if (status === AwaitRenderStatus.error && !errorElement) {
// No errorElement, throw to the nearest route-level error boundary
throw promise._error;
}
if (status === AwaitRenderStatus.error) {
// Render via our errorElement
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(AwaitContext.Provider, {
value: promise,
children: errorElement
});
}
if (status === AwaitRenderStatus.success) {
// Render children with resolved value
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(AwaitContext.Provider, {
value: promise,
children: children
});
}
// Throw to the suspense boundary
throw promise;
}
}
/**
* @private
* Indirection to leverage useAsyncValue for a render-prop API on `<Await>`
*/
function ResolveAwait(_ref8) {
let {
children
} = _ref8;
let data = useAsyncValue();
let toRender = typeof children === "function" ? children(data) : children;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, toRender);
}
///////////////////////////////////////////////////////////////////////////////
// UTILS
///////////////////////////////////////////////////////////////////////////////
/**
* Creates a route config from a React "children" object, which is usually
* either a `<Route>` element or an array of them. Used internally by
* `<Routes>` to create a route config from its children.
*
* @see https://reactrouter.com/utils/create-routes-from-children
*/
function createRoutesFromChildren(children, parentPath) {
if (parentPath === void 0) {
parentPath = [];
}
let routes = [];
react__WEBPACK_IMPORTED_MODULE_0__.Children.forEach(children, (element, index) => {
if (! /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.isValidElement(element)) {
// Ignore non-elements. This allows people to more easily inline
// conditionals in their route config.
return;
}
let treePath = [...parentPath, index];
if (element.type === react__WEBPACK_IMPORTED_MODULE_0__.Fragment) {
// Transparently support React.Fragment and its children.
routes.push.apply(routes, createRoutesFromChildren(element.props.children, treePath));
return;
}
!(element.type === Route) ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, "[" + (typeof element.type === "string" ? element.type : element.type.name) + "] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>") : 0 : void 0;
!(!element.props.index || !element.props.children) ? true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_invariant)(false, "An index route cannot have child routes.") : 0 : void 0;
let route = {
id: element.props.id || treePath.join("-"),
caseSensitive: element.props.caseSensitive,
element: element.props.element,
Component: element.props.Component,
index: element.props.index,
path: element.props.path,
loader: element.props.loader,
action: element.props.action,
errorElement: element.props.errorElement,
ErrorBoundary: element.props.ErrorBoundary,
hasErrorBoundary: element.props.ErrorBoundary != null || element.props.errorElement != null,
shouldRevalidate: element.props.shouldRevalidate,
handle: element.props.handle,
lazy: element.props.lazy
};
if (element.props.children) {
route.children = createRoutesFromChildren(element.props.children, treePath);
}
routes.push(route);
});
return routes;
}
/**
* Renders the result of `matchRoutes()` into a React element.
*/
function renderMatches(matches) {
return _renderMatches(matches);
}
function mapRouteProperties(route) {
let updates = {
// Note: this check also occurs in createRoutesFromChildren so update
// there if you change this -- please and thank you!
hasErrorBoundary: route.ErrorBoundary != null || route.errorElement != null
};
if (route.Component) {
if (true) {
if (route.element) {
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(false, "You should not include both `Component` and `element` on your route - " + "`Component` will be used.") : 0;
}
}
Object.assign(updates, {
element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(route.Component),
Component: undefined
});
}
if (route.HydrateFallback) {
if (true) {
if (route.hydrateFallbackElement) {
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(false, "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - " + "`HydrateFallback` will be used.") : 0;
}
}
Object.assign(updates, {
hydrateFallbackElement: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(route.HydrateFallback),
HydrateFallback: undefined
});
}
if (route.ErrorBoundary) {
if (true) {
if (route.errorElement) {
true ? (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.UNSAFE_warning)(false, "You should not include both `ErrorBoundary` and `errorElement` on your route - " + "`ErrorBoundary` will be used.") : 0;
}
}
Object.assign(updates, {
errorElement: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(route.ErrorBoundary),
ErrorBoundary: undefined
});
}
return updates;
}
function createMemoryRouter(routes, opts) {
return (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.createRouter)({
basename: opts == null ? void 0 : opts.basename,
future: _extends({}, opts == null ? void 0 : opts.future, {
v7_prependBasename: true
}),
history: (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__.createMemoryHistory)({
initialEntries: opts == null ? void 0 : opts.initialEntries,
initialIndex: opts == null ? void 0 : opts.initialIndex
}),
hydrationData: opts == null ? void 0 : opts.hydrationData,
routes,
mapRouteProperties
}).initialize();
}
//# sourceMappingURL=index.js.map
/***/ }),
/***/ "react":
/*!************************!*\
!*** external "React" ***!
\************************/
/***/ ((module) => {
module.exports = window["React"];
/***/ }),
/***/ "react-dom":
/*!***************************!*\
!*** external "ReactDOM" ***!
\***************************/
/***/ ((module) => {
module.exports = window["ReactDOM"];
/***/ }),
/***/ "@wordpress/api-fetch":
/*!**********************************!*\
!*** external ["wp","apiFetch"] ***!
\**********************************/
/***/ ((module) => {
module.exports = window["wp"]["apiFetch"];
/***/ }),
/***/ "@wordpress/components":
/*!************************************!*\
!*** external ["wp","components"] ***!
\************************************/
/***/ ((module) => {
module.exports = window["wp"]["components"];
/***/ }),
/***/ "@wordpress/element":
/*!*********************************!*\
!*** external ["wp","element"] ***!
\*********************************/
/***/ ((module) => {
module.exports = window["wp"]["element"];
/***/ }),
/***/ "@wordpress/i18n":
/*!******************************!*\
!*** external ["wp","i18n"] ***!
\******************************/
/***/ ((module) => {
module.exports = window["wp"]["i18n"];
/***/ }),
/***/ "@wordpress/primitives":
/*!************************************!*\
!*** external ["wp","primitives"] ***!
\************************************/
/***/ ((module) => {
module.exports = window["wp"]["primitives"];
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/chunk loaded */
/******/ (() => {
/******/ var deferred = [];
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
/******/ if(chunkIds) {
/******/ priority = priority || 0;
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
/******/ deferred[i] = [chunkIds, fn, priority];
/******/ return;
/******/ }
/******/ var notFulfilled = Infinity;
/******/ for (var i = 0; i < deferred.length; i++) {
/******/ var [chunkIds, fn, priority] = deferred[i];
/******/ var fulfilled = true;
/******/ for (var j = 0; j < chunkIds.length; j++) {
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
/******/ chunkIds.splice(j--, 1);
/******/ } else {
/******/ fulfilled = false;
/******/ if(priority < notFulfilled) notFulfilled = priority;
/******/ }
/******/ }
/******/ if(fulfilled) {
/******/ deferred.splice(i--, 1)
/******/ var r = fn();
/******/ if (r !== undefined) result = r;
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".js";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get mini-css chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.miniCssF = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".css";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/global */
/******/ (() => {
/******/ __webpack_require__.g = (function() {
/******/ if (typeof globalThis === 'object') return globalThis;
/******/ try {
/******/ return this || new Function('return this')();
/******/ } catch (e) {
/******/ if (typeof window === 'object') return window;
/******/ }
/******/ })();
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/load script */
/******/ (() => {
/******/ var inProgress = {};
/******/ var dataWebpackPrefix = "webdevia-onboarding:";
/******/ // loadScript function to load a script via script tag
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
/******/ var script, needAttach;
/******/ if(key !== undefined) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ for(var i = 0; i < scripts.length; i++) {
/******/ var s = scripts[i];
/******/ if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }
/******/ }
/******/ }
/******/ if(!script) {
/******/ needAttach = true;
/******/ script = document.createElement('script');
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
/******/
/******/ script.src = url;
/******/ }
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var doneFns = inProgress[url];
/******/ delete inProgress[url];
/******/ script.parentNode && script.parentNode.removeChild(script);
/******/ doneFns && doneFns.forEach((fn) => (fn(event)));
/******/ if(prev) return prev(event);
/******/ }
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ needAttach && document.head.appendChild(script);
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/publicPath */
/******/ (() => {
/******/ var scriptUrl;
/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
/******/ var document = __webpack_require__.g.document;
/******/ if (!scriptUrl && document) {
/******/ if (document.currentScript)
/******/ scriptUrl = document.currentScript.src;
/******/ if (!scriptUrl) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ if(scripts.length) {
/******/ var i = scripts.length - 1;
/******/ while (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src;
/******/ }
/******/ }
/******/ }
/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
/******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
/******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
/******/ scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
/******/ __webpack_require__.p = scriptUrl;
/******/ })();
/******/
/******/ /* webpack/runtime/css loading */
/******/ (() => {
/******/ if (typeof document === "undefined") return;
/******/ var createStylesheet = (chunkId, fullhref, oldTag, resolve, reject) => {
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ var onLinkComplete = (event) => {
/******/ // avoid mem leaks.
/******/ linkTag.onerror = linkTag.onload = null;
/******/ if (event.type === 'load') {
/******/ resolve();
/******/ } else {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realHref = event && event.target && event.target.href || fullhref;
/******/ var err = new Error("Loading CSS chunk " + chunkId + " failed.\n(" + realHref + ")");
/******/ err.code = "CSS_CHUNK_LOAD_FAILED";
/******/ err.type = errorType;
/******/ err.request = realHref;
/******/ if (linkTag.parentNode) linkTag.parentNode.removeChild(linkTag)
/******/ reject(err);
/******/ }
/******/ }
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/ if (oldTag) {
/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);
/******/ } else {
/******/ document.head.appendChild(linkTag);
/******/ }
/******/ return linkTag;
/******/ };
/******/ var findStylesheet = (href, fullhref) => {
/******/ var existingLinkTags = document.getElementsByTagName("link");
/******/ for(var i = 0; i < existingLinkTags.length; i++) {
/******/ var tag = existingLinkTags[i];
/******/ var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");
/******/ if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag;
/******/ }
/******/ var existingStyleTags = document.getElementsByTagName("style");
/******/ for(var i = 0; i < existingStyleTags.length; i++) {
/******/ var tag = existingStyleTags[i];
/******/ var dataHref = tag.getAttribute("data-href");
/******/ if(dataHref === href || dataHref === fullhref) return tag;
/******/ }
/******/ };
/******/ var loadStylesheet = (chunkId) => {
/******/ return new Promise((resolve, reject) => {
/******/ var href = __webpack_require__.miniCssF(chunkId);
/******/ var fullhref = __webpack_require__.p + href;
/******/ if(findStylesheet(href, fullhref)) return resolve();
/******/ createStylesheet(chunkId, fullhref, null, resolve, reject);
/******/ });
/******/ }
/******/ // object to store loaded CSS chunks
/******/ var installedCssChunks = {
/******/ "index": 0
/******/ };
/******/
/******/ __webpack_require__.f.miniCss = (chunkId, promises) => {
/******/ var cssChunks = {"src_panel_pages_theme-activation_jsx":1};
/******/ if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);
/******/ else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {
/******/ promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(() => {
/******/ installedCssChunks[chunkId] = 0;
/******/ }, (e) => {
/******/ delete installedCssChunks[chunkId];
/******/ throw e;
/******/ }));
/******/ }
/******/ };
/******/
/******/ // no hmr
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ "index": 0,
/******/ "./style-index": 0
/******/ };
/******/
/******/ __webpack_require__.f.j = (chunkId, promises) => {
/******/ // JSONP chunk loading for javascript
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ if("./style-index" != chunkId) {
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ }
/******/ }
/******/ };
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
/******/ } else installedChunks[chunkId] = 0;
/******/ }
/******/ }
/******/ };
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ return __webpack_require__.O(result);
/******/ }
/******/
/******/ var chunkLoadingGlobal = globalThis["webpackChunkwebdevia_onboarding"] = globalThis["webpackChunkwebdevia_onboarding"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module depends on other loaded chunks and execution need to be delayed
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["./style-index"], () => (__webpack_require__("./src/index.js")))
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
/******/
/******/ })()
;
//# sourceMappingURL=index.js.map