Socket
Socket
Sign inDemoInstall

@remix-run/router

Package Overview
Dependencies
0
Maintainers
2
Versions
182
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.0-experimental-00c655af to 0.0.0-experimental-0141b5ec

473

CHANGELOG.md
# `@remix-run/router`
## 1.15.2
### Patch Changes
- Preserve hydrated errors during partial hydration runs ([#11305](https://github.com/remix-run/react-router/pull/11305))
## 1.15.1
### Patch Changes
- Fix encoding/decoding issues with pre-encoded dynamic parameter values ([#11199](https://github.com/remix-run/react-router/pull/11199))
## 1.15.0
### Minor Changes
- Add a `createStaticHandler` `future.v7_throwAbortReason` flag to throw `request.signal.reason` (defaults to a `DOMException`) when a request is aborted instead of an `Error` such as `new Error("query() call aborted: GET /path")` ([#11104](https://github.com/remix-run/react-router/pull/11104))
- Please note that `DOMException` was added in Node v17 so you will not get a `DOMException` on Node 16 and below.
### Patch Changes
- Respect the `ErrorResponse` status code if passed to `getStaticContextFormError` ([#11213](https://github.com/remix-run/react-router/pull/11213))
## 1.14.2
### Patch Changes
- Fix bug where dashes were not picked up in dynamic parameter names ([#11160](https://github.com/remix-run/react-router/pull/11160))
- Do not attempt to deserialize empty JSON responses ([#11164](https://github.com/remix-run/react-router/pull/11164))
## 1.14.1
### Patch Changes
- Fix bug with `route.lazy` not working correctly on initial SPA load when `v7_partialHydration` is specified ([#11121](https://github.com/remix-run/react-router/pull/11121))
- Fix bug preventing revalidation from occurring for persisted fetchers unmounted during the `submitting` phase ([#11102](https://github.com/remix-run/react-router/pull/11102))
- De-dup relative path logic in `resolveTo` ([#11097](https://github.com/remix-run/react-router/pull/11097))
## 1.14.0
### Minor Changes
- Added a new `future.v7_partialHydration` future flag that enables partial hydration of a data router when Server-Side Rendering. This allows you to provide `hydrationData.loaderData` that has values for _some_ initially matched route loaders, but not all. When this flag is enabled, the router will call `loader` functions for routes that do not have hydration loader data during `router.initialize()`, and it will render down to the deepest provided `HydrateFallback` (up to the first route without hydration data) while it executes the unhydrated routes. ([#11033](https://github.com/remix-run/react-router/pull/11033))
For example, the following router has a `root` and `index` route, but only provided `hydrationData.loaderData` for the `root` route. Because the `index` route has a `loader`, we need to run that during initialization. With `future.v7_partialHydration` specified, `<RouterProvider>` will render the `RootComponent` (because it has data) and then the `IndexFallback` (since it does not have data). Once `indexLoader` finishes, application will update and display `IndexComponent`.
```jsx
let router = createBrowserRouter(
[
{
id: "root",
path: "/",
loader: rootLoader,
Component: RootComponent,
Fallback: RootFallback,
children: [
{
id: "index",
index: true,
loader: indexLoader,
Component: IndexComponent,
HydrateFallback: IndexFallback,
},
],
},
],
{
future: {
v7_partialHydration: true,
},
hydrationData: {
loaderData: {
root: { message: "Hydrated from Root!" },
},
},
}
);
```
If the above example did not have an `IndexFallback`, then `RouterProvider` would instead render the `RootFallback` while it executed the `indexLoader`.
**Note:** When `future.v7_partialHydration` is provided, the `<RouterProvider fallbackElement>` prop is ignored since you can move it to a `Fallback` on your top-most route. The `fallbackElement` prop will be removed in React Router v7 when `v7_partialHydration` behavior becomes the standard behavior.
- Add a new `future.v7_relativeSplatPath` flag to implement a breaking bug fix to relative routing when inside a splat route. ([#11087](https://github.com/remix-run/react-router/pull/11087))
This fix was originally added in [#10983](https://github.com/remix-run/react-router/issues/10983) and was later reverted in [#11078](https://github.com/remix-run/react-router/pull/11078) because it was determined that a large number of existing applications were relying on the buggy behavior (see [#11052](https://github.com/remix-run/react-router/issues/11052))
**The Bug**
The buggy behavior is that without this flag, the default behavior when resolving relative paths is to _ignore_ any splat (`*`) portion of the current route path.
**The Background**
This decision was originally made thinking that it would make the concept of nested different sections of your apps in `<Routes>` easier if relative routing would _replace_ the current splat:
```jsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="dashboard/*" element={<Dashboard />} />
</Routes>
</BrowserRouter>
```
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects` will match the `Dashboard` route. The dashboard component itself can then render nested `<Routes>`:
```jsx
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="/">Dashboard Home</Link>
<Link to="team">Team</Link>
<Link to="projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Routes>
</div>
);
}
```
Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the `Dashboard` as its own independent app, or embed it into your large app without making any changes to it.
**The Problem**
The problem is that this concept of ignoring part of a path breaks a lot of other assumptions in React Router - namely that `"."` always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using `"."`:
```jsx
// If we are on URL /dashboard/team, and we want to link to /dashboard/team:
function DashboardTeam() {
// ❌ This is broken and results in <a href="/dashboard">
return <Link to=".">A broken link to the Current URL</Link>;
// ✅ This is fixed but super unintuitive since we're already at /dashboard/team!
return <Link to="./team">A broken link to the Current URL</Link>;
}
```
We've also introduced an issue that we can no longer move our `DashboardTeam` component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as `/dashboard/:widget`. Now, our `"."` links will, properly point to ourself _inclusive of the dynamic param value_ so behavior will break from it's corresponding usage in a `/dashboard/*` route.
Even worse, consider a nested splat route configuration:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
```
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard` component go to the same place! That is definitely not correct!
Another common issue arose in Data Routers (and Remix) where any `<Form>` should post to it's own route `action` if you the user doesn't specify a form action:
```jsx
let router = createBrowserRouter({
path: "/dashboard",
children: [
{
path: "*",
action: dashboardAction,
Component() {
// ❌ This form is broken! It throws a 405 error when it submits because
// it tries to submit to /dashboard (without the splat value) and the parent
// `/dashboard` route doesn't have an action
return <Form method="post">...</Form>;
},
},
],
});
```
This is just a compounded issue from the above because the default location for a `Form` to submit to is itself (`"."`) - and if we ignore the splat portion, that now resolves to the parent route.
**The Solution**
If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage `../` for any links to "sibling" pages:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route index path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="..">Dashboard Home</Link>
<Link to="../team">Team</Link>
<Link to="../projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Router>
</div>
);
}
```
This way, `.` means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and `..` always means "my parents pathname".
### Patch Changes
- Catch and bubble errors thrown when trying to unwrap responses from `loader`/`action` functions ([#11061](https://github.com/remix-run/react-router/pull/11061))
- Fix `relative="path"` issue when rendering `Link`/`NavLink` outside of matched routes ([#11062](https://github.com/remix-run/react-router/pull/11062))
## 1.13.1
### Patch Changes
- Revert the `useResolvedPath` fix for splat routes due to a large number of applications that were relying on the buggy behavior (see <https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329>). We plan to re-introduce this fix behind a future flag in the next minor version. ([#11078](https://github.com/remix-run/react-router/pull/11078))
## 1.13.0
### Minor Changes
- Export the `PathParam` type from the public API ([#10719](https://github.com/remix-run/react-router/pull/10719))
### Patch Changes
- Fix bug with `resolveTo` in splat routes ([#11045](https://github.com/remix-run/react-router/pull/11045))
- This is a follow up to [#10983](https://github.com/remix-run/react-router/pull/10983) to handle the few other code paths using `getPathContributingMatches`
- This removes the `UNSAFE_getPathContributingMatches` export from `@remix-run/router` since we no longer need this in the `react-router`/`react-router-dom` layers
- Do not revalidate unmounted fetchers when `v7_fetcherPersist` is enabled ([#11044](https://github.com/remix-run/react-router/pull/11044))
## 1.12.0
### Minor Changes
- Add `unstable_flushSync` option to `router.navigate` and `router.fetch` to tell the React Router layer to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#11005](https://github.com/remix-run/react-router/pull/11005))
### Patch Changes
- Fix `relative="path"` bug where relative path calculations started from the full location pathname, instead of from the current contextual route pathname. ([#11006](https://github.com/remix-run/react-router/pull/11006))
```jsx
<Route path="/a">
<Route path="/b" element={<Component />}>
<Route path="/c" />
</Route>
</Route>;
function Component() {
return (
<>
{/* This is now correctly relative to /a/b, not /a/b/c */}
<Link to=".." relative="path" />
<Outlet />
</>
);
}
```
## 1.11.0
### Minor Changes
- Add a new `future.v7_fetcherPersist` flag to the `@remix-run/router` to change the persistence behavior of fetchers when `router.deleteFetcher` is called. Instead of being immediately cleaned up, fetchers will persist until they return to an `idle` state ([RFC](https://github.com/remix-run/remix/discussions/7698)) ([#10962](https://github.com/remix-run/react-router/pull/10962))
- This is sort of a long-standing bug fix as the `useFetchers()` API was always supposed to only reflect **in-flight** fetcher information for pending/optimistic UI -- it was not intended to reflect fetcher data or hang onto fetchers after they returned to an `idle` state
- Keep an eye out for the following specific behavioral changes when opting into this flag and check your app for compatibility:
- Fetchers that complete _while still mounted_ will no longer appear in `useFetchers()`. They served effectively no purpose in there since you can access the data via `useFetcher().data`).
- Fetchers that previously unmounted _while in-flight_ will not be immediately aborted and will instead be cleaned up once they return to an `idle` state. They will remain exposed via `useFetchers` while in-flight so you can still access pending/optimistic data after unmount.
- When `v7_fetcherPersist` is enabled, the router now performs ref-counting on fetcher keys via `getFetcher`/`deleteFetcher` so it knows when a given fetcher is totally unmounted from the UI ([#10977](https://github.com/remix-run/react-router/pull/10977))
- Once a fetcher has been totally unmounted, we can ignore post-processing of a persisted fetcher result such as a redirect or an error
- The router will also pass a new `deletedFetchers` array to the subscriber callbacks so that the UI layer can remove associated fetcher data
- Add support for optional path segments in `matchPath` ([#10768](https://github.com/remix-run/react-router/pull/10768))
### Patch Changes
- Fix `router.getFetcher`/`router.deleteFetcher` type definitions which incorrectly specified `key` as an optional parameter ([#10960](https://github.com/remix-run/react-router/pull/10960))
## 1.10.0
### Minor Changes
- Add experimental support for the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) by allowing users to opt-into view transitions on navigations via the new `unstable_viewTransition` option to `router.navigate` ([#10916](https://github.com/remix-run/react-router/pull/10916))
### Patch Changes
- Allow 404 detection to leverage root route error boundary if path contains a URL segment ([#10852](https://github.com/remix-run/react-router/pull/10852))
- Fix `ErrorResponse` type to avoid leaking internal field ([#10876](https://github.com/remix-run/react-router/pull/10876))
## 1.9.0
### Minor Changes
- In order to move towards stricter TypeScript support in the future, we're aiming to replace current usages of `any` with `unknown` on exposed typings for user-provided data. To do this in Remix v2 without introducing breaking changes in React Router v6, we have added generics to a number of shared types. These continue to default to `any` in React Router and are overridden with `unknown` in Remix. In React Router v7 we plan to move these to `unknown` as a breaking change. ([#10843](https://github.com/remix-run/react-router/pull/10843))
- `Location` now accepts a generic for the `location.state` value
- `ActionFunctionArgs`/`ActionFunction`/`LoaderFunctionArgs`/`LoaderFunction` now accept a generic for the `context` parameter (only used in SSR usages via `createStaticHandler`)
- The return type of `useMatches` (now exported as `UIMatch`) accepts generics for `match.data` and `match.handle` - both of which were already set to `unknown`
- Move the `@private` class export `ErrorResponse` to an `UNSAFE_ErrorResponseImpl` export since it is an implementation detail and there should be no construction of `ErrorResponse` instances in userland. This frees us up to export a `type ErrorResponse` which correlates to an instance of the class via `InstanceType`. Userland code should only ever be using `ErrorResponse` as a type and should be type-narrowing via `isRouteErrorResponse`. ([#10811](https://github.com/remix-run/react-router/pull/10811))
- Export `ShouldRevalidateFunctionArgs` interface ([#10797](https://github.com/remix-run/react-router/pull/10797))
- Removed private/internal APIs only required for the Remix v1 backwards compatibility layer and no longer needed in Remix v2 (`_isFetchActionRedirect`, `_hasFetcherDoneAnything`) ([#10715](https://github.com/remix-run/react-router/pull/10715))
### Patch Changes
- Add method/url to error message on aborted `query`/`queryRoute` calls ([#10793](https://github.com/remix-run/react-router/pull/10793))
- Fix a race-condition with loader/action-thrown errors on `route.lazy` routes ([#10778](https://github.com/remix-run/react-router/pull/10778))
- Fix type for `actionResult` on the arguments object passed to `shouldRevalidate` ([#10779](https://github.com/remix-run/react-router/pull/10779))
## 1.8.0
### Minor Changes
- Add's a new `redirectDocument()` function which allows users to specify that a redirect from a `loader`/`action` should trigger a document reload (via `window.location`) instead of attempting to navigate to the redirected location via React Router ([#10705](https://github.com/remix-run/react-router/pull/10705))
### Patch Changes
- Fix an issue in `queryRoute` that was not always identifying thrown `Response` instances ([#10717](https://github.com/remix-run/react-router/pull/10717))
- Ensure hash history always includes a leading slash on hash pathnames ([#10753](https://github.com/remix-run/react-router/pull/10753))
## 1.7.2
### Patch Changes
- Trigger an error if a `defer` promise resolves/rejects with `undefined` in order to match the behavior of loaders and actions which must return a value or `null` ([#10690](https://github.com/remix-run/react-router/pull/10690))
- Properly handle fetcher redirects interrupted by normal navigations ([#10674](https://github.com/remix-run/react-router/pull/10674), [#10709](https://github.com/remix-run/react-router/pull/10709))
- Initial-load fetchers should not automatically revalidate on GET navigations ([#10688](https://github.com/remix-run/react-router/pull/10688))
- Enhance the return type of `Route.lazy` to prohibit returning an empty object ([#10634](https://github.com/remix-run/react-router/pull/10634))
## 1.7.1
### Patch Changes
- Fix issues with reused blockers on subsequent navigations ([#10656](https://github.com/remix-run/react-router/pull/10656))
## 1.7.0
### Minor Changes
- Add support for `application/json` and `text/plain` encodings for `router.navigate`/`router.fetch` submissions. To leverage these encodings, pass your data in a `body` parameter and specify the desired `formEncType`: ([#10413](https://github.com/remix-run/react-router/pull/10413))
```js
// By default, the encoding is "application/x-www-form-urlencoded"
router.navigate("/", {
formMethod: "post",
body: { key: "value" },
});
async function action({ request }) {
// await request.formData() => FormData instance with entry [key=value]
}
```
```js
// Pass `formEncType` to opt-into a different encoding (json)
router.navigate("/", {
formMethod: "post",
formEncType: "application/json",
body: { key: "value" },
});
async function action({ request }) {
// await request.json() => { key: "value" }
}
```
```js
// Pass `formEncType` to opt-into a different encoding (text)
router.navigate("/", {
formMethod: "post",
formEncType: "text/plain",
body: "Text submission",
});
async function action({ request }) {
// await request.text() => "Text submission"
}
```
### Patch Changes
- Call `window.history.pushState/replaceState` before updating React Router state (instead of after) so that `window.location` matches `useLocation` during synchronous React 17 rendering ([#10448](https://github.com/remix-run/react-router/pull/10448))
- ⚠️ However, generally apps should not be relying on `window.location` and should always reference `useLocation` when possible, as `window.location` will not be in sync 100% of the time (due to `popstate` events, concurrent mode, etc.)
- Strip `basename` from the `location` provided to `<ScrollRestoration getKey>` to match the `useLocation` behavior ([#10550](https://github.com/remix-run/react-router/pull/10550))
- Avoid calling `shouldRevalidate` for fetchers that have not yet completed a data load ([#10623](https://github.com/remix-run/react-router/pull/10623))
- Fix `unstable_useBlocker` key issues in `StrictMode` ([#10573](https://github.com/remix-run/react-router/pull/10573))
- Upgrade `typescript` to 5.1 ([#10581](https://github.com/remix-run/react-router/pull/10581))
## 1.6.3
### Patch Changes
- Allow fetcher revalidations to complete if submitting fetcher is deleted ([#10535](https://github.com/remix-run/react-router/pull/10535))
- Re-throw `DOMException` (`DataCloneError`) when attempting to perform a `PUSH` navigation with non-serializable state. ([#10427](https://github.com/remix-run/react-router/pull/10427))
- Ensure revalidations happen when hash is present ([#10516](https://github.com/remix-run/react-router/pull/10516))
- upgrade jest and jsdom ([#10453](https://github.com/remix-run/react-router/pull/10453))
## 1.6.2
### Patch Changes
- Fix HMR-driven error boundaries by properly reconstructing new routes and `manifest` in `\_internalSetRoutes` ([#10437](https://github.com/remix-run/react-router/pull/10437))
- Fix bug where initial data load would not kick off when hash is present ([#10493](https://github.com/remix-run/react-router/pull/10493))
## 1.6.1
### Patch Changes
- Fix `basename` handling when navigating without a path ([#10433](https://github.com/remix-run/react-router/pull/10433))
- "Same hash" navigations no longer re-run loaders to match browser behavior (i.e. `/path#hash -> /path#hash`) ([#10408](https://github.com/remix-run/react-router/pull/10408))
## 1.6.0
### Minor Changes
- Enable relative routing in the `@remix-run/router` when providing a source route ID from which the path is relative to: ([#10336](https://github.com/remix-run/react-router/pull/10336))
- Example: `router.navigate("../path", { fromRouteId: "some-route" })`.
- This also applies to `router.fetch` which already receives a source route ID
- Introduce a new `@remix-run/router` `future.v7_prependBasename` flag to enable `basename` prefixing to all paths coming into `router.navigate` and `router.fetch`.
- Previously the `basename` was prepended in the React Router layer, but now that relative routing is being handled by the router we need prepend the `basename` _after_ resolving any relative paths
- This also enables `basename` support in `useFetcher` as well
### Patch Changes
- Enhance `LoaderFunction`/`ActionFunction` return type to prevent `undefined` from being a valid return value ([#10267](https://github.com/remix-run/react-router/pull/10267))
- Ensure proper 404 error on `fetcher.load` call to a route without a `loader` ([#10345](https://github.com/remix-run/react-router/pull/10345))
- Deprecate the `createRouter` `detectErrorBoundary` option in favor of the new `mapRouteProperties` option for converting a framework-agnostic route to a framework-aware route. This allows us to set more than just the `hasErrorBoundary` property during route pre-processing, and is now used for mapping `Component -> element` and `ErrorBoundary -> errorElement` in `react-router`. ([#10287](https://github.com/remix-run/react-router/pull/10287))
- Fixed a bug where fetchers were incorrectly attempting to revalidate on search params changes or routing to the same URL (using the same logic for route `loader` revalidations). However, since fetchers have a static href, they should only revalidate on `action` submissions or `router.revalidate` calls. ([#10344](https://github.com/remix-run/react-router/pull/10344))
- Decouple `AbortController` usage between revalidating fetchers and the thing that triggered them such that the unmount/deletion of a revalidating fetcher doesn't impact the ongoing triggering navigation/revalidation ([#10271](https://github.com/remix-run/react-router/pull/10271))
## 1.5.0
### Minor Changes
- Added support for [**Future Flags**](https://reactrouter.com/en/main/guides/api-development-strategy) in React Router. The first flag being introduced is `future.v7_normalizeFormMethod` which will normalize the exposed `useNavigation()/useFetcher()` `formMethod` fields as uppercase HTTP methods to align with the `fetch()` behavior. ([#10207](https://github.com/remix-run/react-router/pull/10207))
- When `future.v7_normalizeFormMethod === false` (default v6 behavior),
- `useNavigation().formMethod` is lowercase
- `useFetcher().formMethod` is lowercase
- When `future.v7_normalizeFormMethod === true`:
- `useNavigation().formMethod` is uppercase
- `useFetcher().formMethod` is uppercase
### Patch Changes
- Provide fetcher submission to `shouldRevalidate` if the fetcher action redirects ([#10208](https://github.com/remix-run/react-router/pull/10208))
- Properly handle `lazy()` errors during router initialization ([#10201](https://github.com/remix-run/react-router/pull/10201))
- Remove `instanceof` check for `DeferredData` to be resilient to ESM/CJS boundaries in SSR bundling scenarios ([#10247](https://github.com/remix-run/react-router/pull/10247))
- Update to latest `@remix-run/web-fetch@4.3.3` ([#10216](https://github.com/remix-run/react-router/pull/10216))
## 1.4.0

@@ -67,3 +529,3 @@

- Fix `generatePath` incorrectly applying parameters in some cases ([`bc6fefa1`](https://github.com/remix-run/react-router/commit/bc6fefa19019ce9f5250c8b5af9b8c5d3390e9d1))
- Fix `generatePath` incorrectly applying parameters in some cases ([#10078](https://github.com/remix-run/react-router/pull/10078))

@@ -246,9 +708,4 @@ ## 1.3.3

For an overview of the features provided by `react-router`, we recommend you go check out the [docs][rr-docs], especially the [feature overview][rr-feature-overview] and the [tutorial][rr-tutorial].
For an overview of the features provided by `react-router`, we recommend you go check out the [docs](https://reactrouter.com), especially the [feature overview](https://reactrouter.com/start/overview) and the [tutorial](https://reactrouter.com/start/tutorial).
For an overview of the features provided by `@remix-run/router`, please check out the [`README`][remix-router-readme].
[rr-docs]: https://reactrouter.com
[rr-feature-overview]: https://reactrouter.com/start/overview
[rr-tutorial]: https://reactrouter.com/start/tutorial
[remix-router-readme]: https://github.com/remix-run/react-router/blob/main/packages/router/README.md
For an overview of the features provided by `@remix-run/router`, please check out the [`README`](./README.md).

20

dist/history.d.ts

@@ -46,7 +46,7 @@ /**

*/
export interface Location extends Path {
export interface Location<State = any> extends Path {
/**
* A value of arbitrary data associated with this location.
*/
state: any;
state: State;
/**

@@ -85,6 +85,6 @@ * A unique string associated with this location. May be used to safely store

* Describes a location that is the destination of some navigation, either via
* `history.push` or `history.replace`. May be either a URL or the pieces of a
* URL path.
* `history.push` or `history.replace`. This may be either a URL or the pieces
* of a URL path.
*/
export declare type To = string | Partial<Path>;
export type To = string | Partial<Path>;
/**

@@ -166,4 +166,4 @@ * A history is an interface to the navigation stack. The history serves as the

*/
export declare type InitialEntry = string | Partial<Location>;
export declare type MemoryHistoryOptions = {
export type InitialEntry = string | Partial<Location>;
export type MemoryHistoryOptions = {
initialEntries?: InitialEntry[];

@@ -198,3 +198,3 @@ initialIndex?: number;

}
export declare type BrowserHistoryOptions = UrlHistoryOptions;
export type BrowserHistoryOptions = UrlHistoryOptions;
/**

@@ -221,3 +221,3 @@ * Browser history stores the location in regular URLs. This is the standard for

}
export declare type HashHistoryOptions = UrlHistoryOptions;
export type HashHistoryOptions = UrlHistoryOptions;
/**

@@ -252,5 +252,5 @@ * Hash history stores the location in window.location.hash. This makes it ideal

}
export declare type UrlHistoryOptions = {
export type UrlHistoryOptions = {
window?: Window;
v5Compat?: boolean;
};

@@ -1,9 +0,9 @@

export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, LazyRouteFunction, TrackedPromise, FormEncType, FormMethod, HTMLFormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, V7_FormMethod, } from "./utils";
export { AbortedDeferredError, ErrorResponse, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, } from "./utils";
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, DataStrategyFunction, DataStrategyFunctionArgs, DataStrategyMatch, ErrorResponse, FormEncType, FormMethod, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathParam, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, } from "./utils";
export { AbortedDeferredError, DecodedResponse as unstable_DecodedResponse, defer, generatePath, getToPathname, isDecodedResponse as unstable_isDecodedResponse, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, redirectDocument, resolvePath, resolveTo, stripBasename, } from "./utils";
export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
export { Action, createBrowserHistory, createPath, createHashHistory, createMemoryHistory, parsePath, } from "./history";
export { Action, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, parsePath, } from "./history";
export * from "./router";
/** @internal */
export type { RouteManifest as UNSAFE_RouteManifest } from "./utils";
export { DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, } from "./utils";
export { DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, getResolveToMatches as UNSAFE_getResolveToMatches, } from "./utils";
export { invariant as UNSAFE_invariant, warning as UNSAFE_warning, } from "./history";
import type { History, Location, Path, To } from "./history";
import { Action as HistoryAction } from "./history";
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, FormEncType, FormMethod, DetectErrorBoundaryFunction, RouteData, AgnosticRouteObject, AgnosticRouteMatch, V7_FormMethod, HTMLFormMethod } from "./utils";
import { DeferredData } from "./utils";
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteObject, DataStrategyFunction, DeferredData, DetectErrorBoundaryFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, RouteData, Submission, UIMatch } from "./utils";
/**

@@ -20,2 +19,9 @@ * A Router instance manages all navigation and data loading/mutations

*
* Return the future config for the router
*/
get future(): FutureConfig;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Return the current state of the router

@@ -35,2 +41,9 @@ */

*
* Return the window associated with the router
*/
get window(): RouterInit["window"];
/**
* @internal
* PRIVATE - DO NOT USE
*
* Initialize the router, including adding history listeners and kicking off

@@ -75,3 +88,3 @@ * initial data fetches. Returns a function to cleanup listeners and abort

*/
navigate(to: To, opts?: RouterNavigateOptions): Promise<void>;
navigate(to: To | null, opts?: RouterNavigateOptions): Promise<void>;
/**

@@ -88,3 +101,3 @@ * @internal

*/
fetch(key: string, routeId: string, href: string, opts?: RouterNavigateOptions): void;
fetch(key: string, routeId: string, href: string | null, opts?: RouterFetchOptions): void;
/**

@@ -121,3 +134,3 @@ * @internal

*/
getFetcher<TData = any>(key?: string): Fetcher<TData>;
getFetcher<TData = any>(key: string): Fetcher<TData>;
/**

@@ -130,3 +143,3 @@ * @internal

*/
deleteFetcher(key?: string): void;
deleteFetcher(key: string): void;
/**

@@ -244,3 +257,3 @@ * @internal

*/
export declare type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">>;
export type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">>;
/**

@@ -250,3 +263,8 @@ * Future flags to toggle new feature behavior

export interface FutureConfig {
v7_fetcherPersist: boolean;
v7_normalizeFormMethod: boolean;
v7_partialHydration: boolean;
v7_prependBasename: boolean;
v7_relativeSplatPath: boolean;
unstable_skipActionErrorRevalidation: boolean;
}

@@ -260,5 +278,11 @@ /**

basename?: string;
/**
* @deprecated Use `mapRouteProperties` instead
*/
detectErrorBoundary?: DetectErrorBoundaryFunction;
future?: FutureConfig;
mapRouteProperties?: MapRoutePropertiesFunction;
future?: Partial<FutureConfig>;
hydrationData?: HydrationState;
window?: Window;
unstable_dataStrategy?: DataStrategyFunction;
}

@@ -287,2 +311,3 @@ /**

query(request: Request, opts?: {
loadRouteIds?: string[];
requestContext?: unknown;

@@ -295,2 +320,6 @@ }): Promise<StaticHandlerContext | Response>;

}
type ViewTransitionOpts = {
currentLocation: Location;
nextLocation: Location;
};
/**

@@ -300,11 +329,8 @@ * Subscriber function signature for changes to router state

export interface RouterSubscriber {
(state: RouterState): void;
(state: RouterState, opts: {
deletedFetchers: string[];
unstable_viewTransitionOpts?: ViewTransitionOpts;
unstable_flushSync: boolean;
}): void;
}
interface UseMatchesMatch {
id: string;
pathname: string;
params: AgnosticRouteMatch["params"];
data: unknown;
handle: unknown;
}
/**

@@ -315,3 +341,3 @@ * Function signature for determining the key to be used in scroll restoration

export interface GetScrollRestorationKeyFunction {
(location: Location, matches: UseMatchesMatch[]): string | null;
(location: Location, matches: UIMatch[]): string | null;
}

@@ -324,33 +350,52 @@ /**

}
/**
* Options for a navigate() call for a Link navigation
*/
declare type LinkNavigateOptions = {
replace?: boolean;
state?: any;
export type RelativeRoutingType = "route" | "path";
type BaseNavigateOrFetchOptions = {
preventScrollReset?: boolean;
relative?: RelativeRoutingType;
unstable_flushSync?: boolean;
};
/**
* Options for a navigate() call for a Form navigation
*/
declare type SubmissionNavigateOptions = {
type BaseNavigateOptions = BaseNavigateOrFetchOptions & {
replace?: boolean;
state?: any;
preventScrollReset?: boolean;
fromRouteId?: string;
unstable_viewTransition?: boolean;
};
type BaseSubmissionOptions = {
formMethod?: HTMLFormMethod;
formEncType?: FormEncType;
} & ({
formData: FormData;
};
body?: undefined;
} | {
formData?: undefined;
body: any;
});
/**
* Options to pass to navigate() for either a Link or Form navigation
* Options for a navigate() call for a normal (non-submission) navigation
*/
export declare type RouterNavigateOptions = LinkNavigateOptions | SubmissionNavigateOptions;
type LinkNavigateOptions = BaseNavigateOptions;
/**
* Options for a navigate() call for a submission navigation
*/
type SubmissionNavigateOptions = BaseNavigateOptions & BaseSubmissionOptions;
/**
* Options to pass to navigate() for a navigation
*/
export type RouterNavigateOptions = LinkNavigateOptions | SubmissionNavigateOptions;
/**
* Options for a fetch() load
*/
type LoadFetchOptions = BaseNavigateOrFetchOptions;
/**
* Options for a fetch() submission
*/
type SubmitFetchOptions = BaseNavigateOrFetchOptions & BaseSubmissionOptions;
/**
* Options to pass to fetch()
*/
export declare type RouterFetchOptions = Omit<LinkNavigateOptions, "replace"> | Omit<SubmissionNavigateOptions, "replace">;
export type RouterFetchOptions = LoadFetchOptions | SubmitFetchOptions;
/**
* Potential states for state.navigation
*/
export declare type NavigationStates = {
export type NavigationStates = {
Idle: {

@@ -363,2 +408,4 @@ state: "idle";

formData: undefined;
json: undefined;
text: undefined;
};

@@ -368,6 +415,8 @@ Loading: {

location: Location;
formMethod: FormMethod | V7_FormMethod | undefined;
formAction: string | undefined;
formEncType: FormEncType | undefined;
formData: FormData | undefined;
formMethod: Submission["formMethod"] | undefined;
formAction: Submission["formAction"] | undefined;
formEncType: Submission["formEncType"] | undefined;
formData: Submission["formData"] | undefined;
json: Submission["json"] | undefined;
text: Submission["text"] | undefined;
};

@@ -377,14 +426,16 @@ Submitting: {

location: Location;
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: FormData;
formMethod: Submission["formMethod"];
formAction: Submission["formAction"];
formEncType: Submission["formEncType"];
formData: Submission["formData"];
json: Submission["json"];
text: Submission["text"];
};
};
export declare type Navigation = NavigationStates[keyof NavigationStates];
export declare type RevalidationState = "idle" | "loading";
export type Navigation = NavigationStates[keyof NavigationStates];
export type RevalidationState = "idle" | "loading";
/**
* Potential states for fetchers
*/
declare type FetcherStates<TData = any> = {
type FetcherStates<TData = any> = {
Idle: {

@@ -395,3 +446,5 @@ state: "idle";

formEncType: undefined;
text: undefined;
formData: undefined;
json: undefined;
data: TData | undefined;

@@ -401,6 +454,8 @@ };

state: "loading";
formMethod: FormMethod | V7_FormMethod | undefined;
formAction: string | undefined;
formEncType: FormEncType | undefined;
formData: FormData | undefined;
formMethod: Submission["formMethod"] | undefined;
formAction: Submission["formAction"] | undefined;
formEncType: Submission["formEncType"] | undefined;
text: Submission["text"] | undefined;
formData: Submission["formData"] | undefined;
json: Submission["json"] | undefined;
data: TData | undefined;

@@ -410,10 +465,12 @@ };

state: "submitting";
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: FormData;
formMethod: Submission["formMethod"];
formAction: Submission["formAction"];
formEncType: Submission["formEncType"];
text: Submission["text"];
formData: Submission["formData"];
json: Submission["json"];
data: TData | undefined;
};
};
export declare type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
export type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
interface BlockerBlocked {

@@ -437,4 +494,4 @@ state: "blocked";

}
export declare type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;
export declare type BlockerFunction = (args: {
export type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;
export type BlockerFunction = (args: {
currentLocation: Location;

@@ -452,5 +509,18 @@ nextLocation: Location;

export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
/**
* Future flags to toggle new feature behavior
*/
export interface StaticHandlerFutureConfig {
v7_relativeSplatPath: boolean;
v7_throwAbortReason: boolean;
}
export interface CreateStaticHandlerOptions {
basename?: string;
/**
* @deprecated Use `mapRouteProperties` instead
*/
detectErrorBoundary?: DetectErrorBoundaryFunction;
unstable_dataStrategy?: DataStrategyFunction;
mapRouteProperties?: MapRoutePropertiesFunction;
future?: Partial<StaticHandlerFutureConfig>;
}

@@ -463,2 +533,3 @@ export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;

export declare function getStaticContextFromError(routes: AgnosticDataRouteObject[], context: StaticHandlerContext, error: any): StaticHandlerContext;
export declare function isDeferredData(value: any): value is DeferredData;
export {};
/**
* @remix-run/router v0.0.0-experimental-00c655af
* @remix-run/router v0.0.0-experimental-0141b5ec
*

@@ -11,3 +11,3 @@ * Copyright (c) Remix Software Inc.

*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).RemixRouter={})}(this,(function(e){"use strict";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(e[a]=r[a])}return e},t.apply(this,arguments)}var r;e.Action=void 0,(r=e.Action||(e.Action={})).Pop="POP",r.Push="PUSH",r.Replace="REPLACE";const a="popstate";function o(e,t){if(!1===e||null==e)throw new Error(t)}function n(e,t){if(!e){"undefined"!=typeof console&&console.warn(t);try{throw new Error(t)}catch(e){}}}function i(e,t){return{usr:e.state,key:e.key,idx:t}}function s(e,r,a,o){return void 0===a&&(a=null),t({pathname:"string"==typeof e?e:e.pathname,search:"",hash:""},"string"==typeof r?c(r):r,{state:a,key:r&&r.key||o||Math.random().toString(36).substr(2,8)})}function l(e){let{pathname:t="/",search:r="",hash:a=""}=e;return r&&"?"!==r&&(t+="?"===r.charAt(0)?r:"?"+r),a&&"#"!==a&&(t+="#"===a.charAt(0)?a:"#"+a),t}function c(e){let t={};if(e){let r=e.indexOf("#");r>=0&&(t.hash=e.substr(r),e=e.substr(0,r));let a=e.indexOf("?");a>=0&&(t.search=e.substr(a),e=e.substr(0,a)),e&&(t.pathname=e)}return t}function d(r,n,c,d){void 0===d&&(d={});let{window:u=document.defaultView,v5Compat:h=!1}=d,f=u.history,p=e.Action.Pop,m=null,v=y();function y(){return(f.state||{idx:null}).idx}function g(){p=e.Action.Pop;let t=y(),r=null==t?null:t-v;v=t,m&&m({action:p,location:w.location,delta:r})}function b(e){let t="null"!==u.location.origin?u.location.origin:u.location.href,r="string"==typeof e?e:l(e);return o(t,"No window.location.(origin|href) available to create URL for href: "+r),new URL(r,t)}null==v&&(v=0,f.replaceState(t({},f.state,{idx:v}),""));let w={get action(){return p},get location(){return r(u,f)},listen(e){if(m)throw new Error("A history only accepts one active listener");return u.addEventListener(a,g),m=e,()=>{u.removeEventListener(a,g),m=null}},createHref:e=>n(u,e),createURL:b,encodeLocation(e){let t=b(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(t,r){p=e.Action.Push;let a=s(w.location,t,r);c&&c(a,t),v=y()+1;let o=i(a,v),n=w.createHref(a);try{f.pushState(o,"",n)}catch(e){u.location.assign(n)}h&&m&&m({action:p,location:w.location,delta:1})},replace:function(t,r){p=e.Action.Replace;let a=s(w.location,t,r);c&&c(a,t),v=y();let o=i(a,v),n=w.createHref(a);f.replaceState(o,"",n),h&&m&&m({action:p,location:w.location,delta:0})},go:e=>f.go(e)};return w}let u;!function(e){e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error"}(u||(u={}));const h=new Set(["lazy","caseSensitive","path","id","index","children"]);function f(e,r,a,n){return void 0===a&&(a=[]),void 0===n&&(n={}),e.map(((e,i)=>{let s=[...a,i],l="string"==typeof e.id?e.id:s.join("-");if(o(!0!==e.index||!e.children,"Cannot specify children on an index route"),o(!n[l],'Found a route id collision on id "'+l+"\". Route id's must be globally unique within Data Router usages"),function(e){return!0===e.index}(e)){let a=t({},e,{hasErrorBoundary:r(e),id:l});return n[l]=a,a}{let a=t({},e,{id:l,hasErrorBoundary:r(e),children:void 0});return n[l]=a,e.children&&(a.children=f(e.children,r,s,n)),a}}))}function p(e,t,r){void 0===r&&(r="/");let a=E(("string"==typeof t?c(t):t).pathname||"/",r);if(null==a)return null;let o=m(e);!function(e){e.sort(((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){return e.length===t.length&&e.slice(0,-1).every(((e,r)=>e===t[r]))?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map((e=>e.childrenIndex)),t.routesMeta.map((e=>e.childrenIndex)))))}(o);let n=null;for(let e=0;null==n&&e<o.length;++e)n=w(o[e],R(a));return n}function m(e,t,r,a){void 0===t&&(t=[]),void 0===r&&(r=[]),void 0===a&&(a="");let n=(e,n,i)=>{let s={relativePath:void 0===i?e.path||"":i,caseSensitive:!0===e.caseSensitive,childrenIndex:n,route:e};s.relativePath.startsWith("/")&&(o(s.relativePath.startsWith(a),'Absolute route path "'+s.relativePath+'" nested under path "'+a+'" is not valid. An absolute child route path must start with the combined path of all its parent routes.'),s.relativePath=s.relativePath.slice(a.length));let l=L([a,s.relativePath]),c=r.concat(s);e.children&&e.children.length>0&&(o(!0!==e.index,'Index routes must not have child routes. Please remove all child routes from route path "'+l+'".'),m(e.children,t,c,l)),(null!=e.path||e.index)&&t.push({path:l,score:b(l,e.index),routesMeta:c})};return e.forEach(((e,t)=>{var r;if(""!==e.path&&null!=(r=e.path)&&r.includes("?"))for(let r of v(e.path))n(e,t,r);else n(e,t)})),t}function v(e){let t=e.split("/");if(0===t.length)return[];let[r,...a]=t,o=r.endsWith("?"),n=r.replace(/\?$/,"");if(0===a.length)return o?[n,""]:[n];let i=v(a.join("/")),s=[];return s.push(...i.map((e=>""===e?n:[n,e].join("/")))),o&&s.push(...i),s.map((t=>e.startsWith("/")&&""===t?"/":t))}const y=/^:\w+$/,g=e=>"*"===e;function b(e,t){let r=e.split("/"),a=r.length;return r.some(g)&&(a+=-2),t&&(a+=2),r.filter((e=>!g(e))).reduce(((e,t)=>e+(y.test(t)?3:""===t?1:10)),a)}function w(e,t){let{routesMeta:r}=e,a={},o="/",n=[];for(let e=0;e<r.length;++e){let i=r[e],s=e===r.length-1,l="/"===o?t:t.slice(o.length)||"/",c=D({path:i.relativePath,caseSensitive:i.caseSensitive,end:s},l);if(!c)return null;Object.assign(a,c.params);let d=i.route;n.push({params:a,pathname:L([o,c.pathname]),pathnameBase:k(L([o,c.pathnameBase])),route:d}),"/"!==c.pathnameBase&&(o=L([o,c.pathnameBase]))}return n}function D(e,t){"string"==typeof e&&(e={path:e,caseSensitive:!1,end:!0});let[r,a]=function(e,t,r){void 0===t&&(t=!1);void 0===r&&(r=!0);n("*"===e||!e.endsWith("*")||e.endsWith("/*"),'Route path "'+e+'" will be treated as if it were "'+e.replace(/\*$/,"/*")+'" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "'+e.replace(/\*$/,"/*")+'".');let a=[],o="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/\/:(\w+)/g,((e,t)=>(a.push(t),"/([^\\/]+)")));e.endsWith("*")?(a.push("*"),o+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):r?o+="\\/*$":""!==e&&"/"!==e&&(o+="(?:(?=\\/|$))");return[new RegExp(o,t?void 0:"i"),a]}(e.path,e.caseSensitive,e.end),o=t.match(r);if(!o)return null;let i=o[0],s=i.replace(/(.)\/+$/,"$1"),l=o.slice(1);return{params:a.reduce(((e,t,r)=>{if("*"===t){let e=l[r]||"";s=i.slice(0,i.length-e.length).replace(/(.)\/+$/,"$1")}return e[t]=function(e,t){try{return decodeURIComponent(e)}catch(r){return n(!1,'The value for the URL param "'+t+'" will not be decoded because the string "'+e+'" is a malformed URL segment. This is probably due to a bad percent encoding ('+r+")."),e}}(l[r]||"",t),e}),{}),pathname:i,pathnameBase:s,pattern:e}}function R(e){try{return decodeURI(e)}catch(t){return n(!1,'The URL path "'+e+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent encoding ('+t+")."),e}}function E(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let r=t.endsWith("/")?t.length-1:t.length,a=e.charAt(r);return a&&"/"!==a?null:e.slice(r)||"/"}function A(e,t){void 0===t&&(t="/");let{pathname:r,search:a="",hash:o=""}="string"==typeof e?c(e):e,n=r?r.startsWith("/")?r:function(e,t){let r=t.replace(/\/+$/,"").split("/");return e.split("/").forEach((e=>{".."===e?r.length>1&&r.pop():"."!==e&&r.push(e)})),r.length>1?r.join("/"):"/"}(r,t):t;return{pathname:n,search:x(a),hash:C(o)}}function P(e,t,r,a){return"Cannot include a '"+e+"' character in a manually specified `to."+t+"` field ["+JSON.stringify(a)+"]. Please separate it out to the `to."+r+'` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.'}function S(e){return e.filter(((e,t)=>0===t||e.route.path&&e.route.path.length>0))}function M(e,r,a,n){let i;void 0===n&&(n=!1),"string"==typeof e?i=c(e):(i=t({},e),o(!i.pathname||!i.pathname.includes("?"),P("?","pathname","search",i)),o(!i.pathname||!i.pathname.includes("#"),P("#","pathname","hash",i)),o(!i.search||!i.search.includes("#"),P("#","search","hash",i)));let s,l=""===e||""===i.pathname,d=l?"/":i.pathname;if(n||null==d)s=a;else{let e=r.length-1;if(d.startsWith("..")){let t=d.split("/");for(;".."===t[0];)t.shift(),e-=1;i.pathname=t.join("/")}s=e>=0?r[e]:"/"}let u=A(i,s),h=d&&"/"!==d&&d.endsWith("/"),f=(l||"."===d)&&a.endsWith("/");return u.pathname.endsWith("/")||!h&&!f||(u.pathname+="/"),u}const L=e=>e.join("/").replace(/\/\/+/g,"/"),k=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),x=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",C=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";class U extends Error{}class j{constructor(e,t){let r;this.pendingKeysSet=new Set,this.subscribers=new Set,this.deferredKeys=[],o(e&&"object"==typeof e&&!Array.isArray(e),"defer() only accepts plain objects"),this.abortPromise=new Promise(((e,t)=>r=t)),this.controller=new AbortController;let a=()=>r(new U("Deferred data aborted"));this.unlistenAbortSignal=()=>this.controller.signal.removeEventListener("abort",a),this.controller.signal.addEventListener("abort",a),this.data=Object.entries(e).reduce(((e,t)=>{let[r,a]=t;return Object.assign(e,{[r]:this.trackPromise(r,a)})}),{}),this.done&&this.unlistenAbortSignal(),this.init=t}trackPromise(e,t){if(!(t instanceof Promise))return t;this.deferredKeys.push(e),this.pendingKeysSet.add(e);let r=Promise.race([t,this.abortPromise]).then((t=>this.onSettle(r,e,null,t)),(t=>this.onSettle(r,e,t)));return r.catch((()=>{})),Object.defineProperty(r,"_tracked",{get:()=>!0}),r}onSettle(e,t,r,a){return this.controller.signal.aborted&&r instanceof U?(this.unlistenAbortSignal(),Object.defineProperty(e,"_error",{get:()=>r}),Promise.reject(r)):(this.pendingKeysSet.delete(t),this.done&&this.unlistenAbortSignal(),r?(Object.defineProperty(e,"_error",{get:()=>r}),this.emit(!1,t),Promise.reject(r)):(Object.defineProperty(e,"_data",{get:()=>a}),this.emit(!1,t),a))}emit(e,t){this.subscribers.forEach((r=>r(e,t)))}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}cancel(){this.controller.abort(),this.pendingKeysSet.forEach(((e,t)=>this.pendingKeysSet.delete(t))),this.emit(!0)}async resolveData(e){let t=!1;if(!this.done){let r=()=>this.cancel();e.addEventListener("abort",r),t=await new Promise((t=>{this.subscribe((a=>{e.removeEventListener("abort",r),(a||this.done)&&t(a)}))}))}return t}get done(){return 0===this.pendingKeysSet.size}get unwrappedData(){return o(null!==this.data&&this.done,"Can only unwrap data on initialized and settled deferreds"),Object.entries(this.data).reduce(((e,t)=>{let[r,a]=t;return Object.assign(e,{[r]:O(a)})}),{})}get pendingKeys(){return Array.from(this.pendingKeysSet)}}function O(e){if(!function(e){return e instanceof Promise&&!0===e._tracked}(e))return e;if(e._error)throw e._error;return e._data}class T{constructor(e,t,r,a){void 0===a&&(a=!1),this.status=e,this.statusText=t||"",this.internal=a,r instanceof Error?(this.data=r.toString(),this.error=r):this.data=r}}function _(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"boolean"==typeof e.internal&&"data"in e}const H=["post","put","patch","delete"],z=new Set(H),I=["get",...H],B=new Set(I),q=new Set([301,302,303,307,308]),$=new Set([307,308]),N={state:"idle",location:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},W={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},F={state:"unblocked",proceed:void 0,reset:void 0,location:void 0},K=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Y="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,J=!Y,V=e=>Boolean(e.hasErrorBoundary);const G=Symbol("deferred");function X(e,t,r,a){void 0===a&&(a=!1);let o,n="string"==typeof e?e:l(e);if(!r||!function(e){return null!=e&&"formData"in e}(r))return{path:n};if(r.formMethod&&!be(r.formMethod))return{path:n,error:ue(405,{method:r.formMethod})};if(r.formData){let e=r.formMethod||"get";if(o={formMethod:t.v7_normalizeFormMethod?e.toUpperCase():e.toLowerCase(),formAction:fe(n),formEncType:r&&r.formEncType||"application/x-www-form-urlencoded",formData:r.formData},we(o.formMethod))return{path:n,submission:o}}let i=c(n),s=ne(r.formData);return a&&i.search&&Ee(i.search)&&s.append("index",""),i.search="?"+s,{path:l(i),submission:o}}function Q(e,t){let r=e;if(t){let a=e.findIndex((e=>e.route.id===t));a>=0&&(r=e.slice(0,a))}return r}function Z(e,r,a,o,n,i,s,l,c,d,u,h,f){let m=f?Object.values(f)[0]:h?Object.values(h)[0]:void 0,v=e.createURL(r.location),y=e.createURL(n),g=i||v.toString()===y.toString()||v.search!==y.search,b=f?Object.keys(f)[0]:void 0,w=Q(a,b).filter(((e,a)=>{if(e.route.lazy)return!0;if(null==e.route.loader)return!1;if(function(e,t,r){let a=!t||r.route.id!==t.route.id,o=void 0===e[r.route.id];return a||o}(r.loaderData,r.matches[a],e)||s.some((t=>t===e.route.id)))return!0;let n=r.matches[a],i=e;return te(e,t({currentUrl:v,currentParams:n.params,nextUrl:y,nextParams:i.params},o,{actionResult:m,defaultShouldRevalidate:g||ee(n,i)}))})),D=[];return c.forEach(((e,n)=>{if(!a.some((t=>t.route.id===e.routeId)))return;let i=p(d,e.path,u);if(!i)return void D.push(t({key:n},e,{matches:null,match:null}));let s=Pe(i,e.path);(l.includes(n)||te(s,t({currentUrl:v,currentParams:r.matches[r.matches.length-1].params,nextUrl:y,nextParams:a[a.length-1].params},o,{actionResult:m,defaultShouldRevalidate:g})))&&D.push(t({key:n,matches:i,match:s},e))})),[w,D]}function ee(e,t){let r=e.route.path;return e.pathname!==t.pathname||null!=r&&r.endsWith("*")&&e.params["*"]!==t.params["*"]}function te(e,t){if(e.route.shouldRevalidate){let r=e.route.shouldRevalidate(t);if("boolean"==typeof r)return r}return t.defaultShouldRevalidate}async function re(e,r,a){if(!e.lazy)return;let i=await e.lazy();if(!e.lazy)return;let s=a[e.id];o(s,"No route found in manifest");let l={};for(let e in i){let t=void 0!==s[e]&&"hasErrorBoundary"!==e;n(!t,'Route "'+s.id+'" has a static property "'+e+'" defined but its lazy function is also returning a value for this property. The lazy route property "'+e+'" will be ignored.'),t||h.has(e)||(l[e]=i[e])}Object.assign(s,l),Object.assign(s,{hasErrorBoundary:r(t({},s)),lazy:void 0})}async function ae(e,t,r,a,n,i,s,c,d,h){let f,p,m;void 0===s&&(s="/"),void 0===c&&(c=!1),void 0===d&&(d=!1);let v=e=>{let a,o=new Promise(((e,t)=>a=t));return m=()=>a(),t.signal.addEventListener("abort",m),Promise.race([e({request:t,params:r.params,context:h}),o])};try{let a=r.route[e];if(r.route.lazy)if(a){p=(await Promise.all([v(a),re(r.route,i,n)]))[0]}else{if(await re(r.route,i,n),a=r.route[e],!a){if("action"===e)throw ue(405,{method:t.method,pathname:new URL(t.url).pathname,routeId:r.route.id});return{type:u.data,data:void 0}}p=await v(a)}else o(a,"Could not find the "+e+' to run on the "'+r.route.id+'" route'),p=await v(a);o(void 0!==p,"You defined "+("action"===e?"an action":"a loader")+' for route "'+r.route.id+"\" but didn't return anything from your `"+e+"` function. Please return a value or `null`.")}catch(e){f=u.error,p=e}finally{m&&t.signal.removeEventListener("abort",m)}if(ye(p)){let e,n=p.status;if(q.has(n)){let e=p.headers.get("Location");if(o(e,"Redirects returned/thrown from loaders/actions must have a Location header"),K.test(e)){if(!c){let r=new URL(t.url),a=e.startsWith("//")?new URL(r.protocol+e):new URL(e),o=null!=E(a.pathname,s);a.origin===r.origin&&o&&(e=a.pathname+a.search+a.hash)}}else{let n=M(e,S(a.slice(0,a.indexOf(r)+1)).map((e=>e.pathnameBase)),new URL(t.url).pathname);if(o(l(n),"Unable to resolve redirect location: "+e),s){let e=n.pathname;n.pathname="/"===e?s:L([s,e])}e=l(n)}if(c)throw p.headers.set("Location",e),p;return{type:u.redirect,status:n,location:e,revalidate:null!==p.headers.get("X-Remix-Revalidate")}}if(d)throw{type:f||u.data,response:p};let i=p.headers.get("Content-Type");return e=i&&/\bapplication\/json\b/.test(i)?await p.json():await p.text(),f===u.error?{type:f,error:new T(n,p.statusText,e),headers:p.headers}:{type:u.data,data:e,statusCode:p.status,headers:p.headers}}return f===u.error?{type:f,error:p}:p instanceof j?{type:u.deferred,deferredData:p,statusCode:null==(y=p.init)?void 0:y.status,headers:(null==(g=p.init)?void 0:g.headers)&&new Headers(p.init.headers)}:{type:u.data,data:p};var y,g}function oe(e,t,r,a){let o=e.createURL(fe(t)).toString(),n={signal:r};if(a&&we(a.formMethod)){let{formMethod:e,formEncType:t,formData:r}=a;n.method=e,n.body="application/x-www-form-urlencoded"===t?ne(r):r}return new Request(o,n)}function ne(e){let t=new URLSearchParams;for(let[r,a]of e.entries())t.append(r,a instanceof File?a.name:a);return t}function ie(e,t,r,a,n){let i,s={},l=null,c=!1,d={};return r.forEach(((r,u)=>{let h=t[u].route.id;if(o(!ve(r),"Cannot handle redirect results in processLoaderData"),me(r)){let t=ce(e,h),o=r.error;a&&(o=Object.values(a)[0],a=void 0),l=l||{},null==l[t.route.id]&&(l[t.route.id]=o),s[h]=void 0,c||(c=!0,i=_(r.error)?r.error.status:500),r.headers&&(d[h]=r.headers)}else pe(r)?(n.set(h,r.deferredData),s[h]=r.deferredData.data):s[h]=r.data,null==r.statusCode||200===r.statusCode||c||(i=r.statusCode),r.headers&&(d[h]=r.headers)})),a&&(l=a,s[Object.keys(a)[0]]=void 0),{loaderData:s,errors:l,statusCode:i||200,loaderHeaders:d}}function se(e,r,a,n,i,s,l,c){let{loaderData:d,errors:u}=ie(r,a,n,i,c);for(let r=0;r<s.length;r++){let{key:a,match:n}=s[r];o(void 0!==l&&void 0!==l[r],"Did not find corresponding fetcher result");let i=l[r];if(me(i)){let r=ce(e.matches,null==n?void 0:n.route.id);u&&u[r.route.id]||(u=t({},u,{[r.route.id]:i.error})),e.fetchers.delete(a)}else if(ve(i))o(!1,"Unhandled fetcher revalidation redirect");else if(pe(i))o(!1,"Unhandled fetcher deferred data");else{let t={state:"idle",data:i.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0};e.fetchers.set(a,t)}}return{loaderData:d,errors:u}}function le(e,r,a,o){let n=t({},r);for(let t of a){let a=t.route.id;if(r.hasOwnProperty(a)?void 0!==r[a]&&(n[a]=r[a]):void 0!==e[a]&&t.route.loader&&(n[a]=e[a]),o&&o.hasOwnProperty(a))break}return n}function ce(e,t){return(t?e.slice(0,e.findIndex((e=>e.route.id===t))+1):[...e]).reverse().find((e=>!0===e.route.hasErrorBoundary))||e[0]}function de(e){let t=e.find((e=>e.index||!e.path||"/"===e.path))||{id:"__shim-error-route__"};return{matches:[{params:{},pathname:"",pathnameBase:"",route:t}],route:t}}function ue(e,t){let{pathname:r,routeId:a,method:o,type:n}=void 0===t?{}:t,i="Unknown Server Error",s="Unknown @remix-run/router error";return 400===e?(i="Bad Request",o&&r&&a?s="You made a "+o+' request to "'+r+'" but did not provide a `loader` for route "'+a+'", so there is no way to handle the request.':"defer-action"===n&&(s="defer() is not supported in actions")):403===e?(i="Forbidden",s='Route "'+a+'" does not match URL "'+r+'"'):404===e?(i="Not Found",s='No route matches URL "'+r+'"'):405===e&&(i="Method Not Allowed",o&&r&&a?s="You made a "+o.toUpperCase()+' request to "'+r+'" but did not provide an `action` for route "'+a+'", so there is no way to handle the request.':o&&(s='Invalid request method "'+o.toUpperCase()+'"')),new T(e||500,i,new Error(s),!0)}function he(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(ve(r))return r}}function fe(e){return l(t({},"string"==typeof e?c(e):e,{hash:""}))}function pe(e){return e.type===u.deferred}function me(e){return e.type===u.error}function ve(e){return(e&&e.type)===u.redirect}function ye(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"object"==typeof e.headers&&void 0!==e.body}function ge(e){if(!ye(e))return!1;let t=e.status,r=e.headers.get("Location");return t>=300&&t<=399&&null!=r}function be(e){return B.has(e.toLowerCase())}function we(e){return z.has(e.toLowerCase())}async function De(e,t,r,a,o,n){for(let i=0;i<r.length;i++){let s=r[i],l=t[i];if(!l)continue;let c=e.find((e=>e.route.id===l.route.id)),d=null!=c&&!ee(c,l)&&void 0!==(n&&n[l.route.id]);pe(s)&&(o||d)&&await Re(s,a,o).then((e=>{e&&(r[i]=e||r[i])}))}}async function Re(e,t,r){if(void 0===r&&(r=!1),!await e.deferredData.resolveData(t)){if(r)try{return{type:u.data,data:e.deferredData.unwrappedData}}catch(e){return{type:u.error,error:e}}return{type:u.data,data:e.deferredData.data}}}function Ee(e){return new URLSearchParams(e).getAll("index").some((e=>""===e))}function Ae(e,t){let{route:r,pathname:a,params:o}=e;return{id:r.id,pathname:a,params:o,data:t[r.id],handle:r.handle}}function Pe(e,t){let r="string"==typeof t?c(t).search:t.search;if(e[e.length-1].route.index&&Ee(r||""))return e[e.length-1];let a=S(e);return a[a.length-1]}e.AbortedDeferredError=U,e.ErrorResponse=T,e.IDLE_BLOCKER=F,e.IDLE_FETCHER=W,e.IDLE_NAVIGATION=N,e.UNSAFE_DEFERRED_SYMBOL=G,e.UNSAFE_DeferredData=j,e.UNSAFE_convertRoutesToDataRoutes=f,e.UNSAFE_getPathContributingMatches=S,e.UNSAFE_invariant=o,e.UNSAFE_warning=n,e.createBrowserHistory=function(e){return void 0===e&&(e={}),d((function(e,t){let{pathname:r,search:a,hash:o}=e.location;return s("",{pathname:r,search:a,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){return"string"==typeof t?t:l(t)}),null,e)},e.createHashHistory=function(e){return void 0===e&&(e={}),d((function(e,t){let{pathname:r="/",search:a="",hash:o=""}=c(e.location.hash.substr(1));return s("",{pathname:r,search:a,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){let r=e.document.querySelector("base"),a="";if(r&&r.getAttribute("href")){let t=e.location.href,r=t.indexOf("#");a=-1===r?t:t.slice(0,r)}return a+"#"+("string"==typeof t?t:l(t))}),(function(e,t){n("/"===e.pathname.charAt(0),"relative pathnames are not supported in hash history.push("+JSON.stringify(t)+")")}),e)},e.createMemoryHistory=function(t){void 0===t&&(t={});let r,{initialEntries:a=["/"],initialIndex:o,v5Compat:i=!1}=t;r=a.map(((e,t)=>m(e,"string"==typeof e?null:e.state,0===t?"default":void 0)));let d=f(null==o?r.length-1:o),u=e.Action.Pop,h=null;function f(e){return Math.min(Math.max(e,0),r.length-1)}function p(){return r[d]}function m(e,t,a){void 0===t&&(t=null);let o=s(r?p().pathname:"/",e,t,a);return n("/"===o.pathname.charAt(0),"relative pathnames are not supported in memory history: "+JSON.stringify(e)),o}function v(e){return"string"==typeof e?e:l(e)}return{get index(){return d},get action(){return u},get location(){return p()},createHref:v,createURL:e=>new URL(v(e),"http://localhost"),encodeLocation(e){let t="string"==typeof e?c(e):e;return{pathname:t.pathname||"",search:t.search||"",hash:t.hash||""}},push(t,a){u=e.Action.Push;let o=m(t,a);d+=1,r.splice(d,r.length,o),i&&h&&h({action:u,location:o,delta:1})},replace(t,a){u=e.Action.Replace;let o=m(t,a);r[d]=o,i&&h&&h({action:u,location:o,delta:0})},go(t){u=e.Action.Pop;let a=f(d+t),o=r[a];d=a,h&&h({action:u,location:o,delta:t})},listen:e=>(h=e,()=>{h=null})}},e.createPath=l,e.createRouter=function(r){o(r.routes.length>0,"You must provide a non-empty routes array to createRouter");let a,i=r.detectErrorBoundary||V,l={},c=f(r.routes,i,void 0,l),d=t({v7_normalizeFormMethod:!1},r.future),h=null,m=new Set,v=null,y=null,g=null,b=null!=r.hydrationData,w=p(c,r.history.location,r.basename),D=null;if(null==w){let e=ue(404,{pathname:r.history.location.pathname}),{matches:t,route:a}=de(c);w=t,D={[a.id]:e}}let R,A,P=!(w.some((e=>e.route.lazy))||w.some((e=>e.route.loader))&&null==r.hydrationData),S={historyAction:r.history.action,location:r.history.location,matches:w,initialized:P,navigation:N,restoreScrollPosition:null==r.hydrationData&&null,preventScrollReset:!1,revalidation:"idle",loaderData:r.hydrationData&&r.hydrationData.loaderData||{},actionData:r.hydrationData&&r.hydrationData.actionData||null,errors:r.hydrationData&&r.hydrationData.errors||D,fetchers:new Map,blockers:new Map},M=e.Action.Pop,L=!1,k=!1,x=!1,C=[],U=[],j=new Map,O=0,T=-1,_=new Map,H=new Set,z=new Map,I=new Map,B=new Map,q=!1;function G(e){S=t({},S,e),m.forEach((e=>e(S)))}function Q(o,n){var i,s;let l,d=null!=S.actionData&&null!=S.navigation.formMethod&&we(S.navigation.formMethod)&&"loading"===S.navigation.state&&!0!==(null==(i=o.state)?void 0:i._isRedirect);l=n.actionData?Object.keys(n.actionData).length>0?n.actionData:null:d?S.actionData:null;let u=n.loaderData?le(S.loaderData,n.loaderData,n.matches||[],n.errors):S.loaderData;for(let[e]of B)Se(e);let h=!0===L||null!=S.navigation.formMethod&&we(S.navigation.formMethod)&&!0!==(null==(s=o.state)?void 0:s._isRedirect);a&&(c=a,a=void 0),G(t({},n,{actionData:l,loaderData:u,historyAction:M,location:o,initialized:!0,navigation:N,revalidation:"idle",restoreScrollPosition:xe(o,n.matches||S.matches),preventScrollReset:h,blockers:new Map(S.blockers)})),k||M===e.Action.Pop||(M===e.Action.Push?r.history.push(o,o.state):M===e.Action.Replace&&r.history.replace(o,o.state)),M=e.Action.Pop,L=!1,k=!1,x=!1,C=[],U=[]}async function ee(n,s,d){A&&A.abort(),A=null,M=n,k=!0===(d&&d.startUninterruptedRevalidation),function(e,t){if(v&&y&&g){let r=t.map((e=>Ae(e,S.loaderData))),a=y(e,r)||e.key;v[a]=g()}}(S.location,S.matches),L=!0===(d&&d.preventScrollReset);let h=a||c,f=d&&d.overrideNavigation,m=p(h,s,r.basename);if(!m){let e=ue(404,{pathname:s.pathname}),{matches:t,route:r}=de(h);return ke(),void Q(s,{matches:t,loaderData:{},errors:{[r.id]:e}})}if(!(b=S.location,w=s,b.pathname!==w.pathname||b.search!==w.search||b.hash===w.hash||d&&d.submission&&we(d.submission.formMethod)))return void Q(s,{matches:m});var b,w;A=new AbortController;let D,E,P=oe(r.history,s,A.signal,d&&d.submission);if(d&&d.pendingError)E={[ce(m).route.id]:d.pendingError};else if(d&&d.submission&&we(d.submission.formMethod)){let r=await async function(r,a,o,n,s){let c;ie(),G({navigation:t({state:"submitting",location:a},o)});let d=Pe(n,a);if(d.route.action||d.route.lazy){if(c=await ae("action",r,d,n,l,i,R.basename),r.signal.aborted)return{shortCircuited:!0}}else c={type:u.error,error:ue(405,{method:r.method,pathname:a.pathname,routeId:d.route.id})};if(ve(c)){let e;return e=s&&null!=s.replace?s.replace:c.location===S.location.pathname+S.location.search,await re(S,c,{submission:o,replace:e}),{shortCircuited:!0}}if(me(c)){let t=ce(n,d.route.id);return!0!==(s&&s.replace)&&(M=e.Action.Push),{pendingActionData:{},pendingActionError:{[t.route.id]:c.error}}}if(pe(c))throw ue(400,{type:"defer-action"});return{pendingActionData:{[d.route.id]:c.data}}}(P,s,d.submission,m,{replace:d.replace});if(r.shortCircuited)return;D=r.pendingActionData,E=r.pendingActionError,f=t({state:"loading",location:s},d.submission),P=new Request(P.url,{signal:P.signal})}let{shortCircuited:_,loaderData:B,errors:q}=await async function(e,n,i,s,l,d,u,h){let f=s;if(!f){f=t({state:"loading",location:n,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},l)}let p=l||(f.formMethod&&f.formAction&&f.formData&&f.formEncType?{formMethod:f.formMethod,formAction:f.formAction,formData:f.formData,formEncType:f.formEncType}:void 0),m=a||c,[v,y]=Z(r.history,S,i,p,n,x,C,U,z,m,r.basename,u,h);if(ke((e=>!(i&&i.some((t=>t.route.id===e)))||v&&v.some((t=>t.route.id===e)))),0===v.length&&0===y.length)return Q(n,t({matches:i,loaderData:{},errors:h||null},u?{actionData:u}:{})),{shortCircuited:!0};if(!k){y.forEach((e=>{let t=S.fetchers.get(e.key),r={state:"loading",data:t&&t.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0};S.fetchers.set(e.key,r)}));let e=u||S.actionData;G(t({navigation:f},e?0===Object.keys(e).length?{actionData:null}:{actionData:e}:{},y.length>0?{fetchers:new Map(S.fetchers)}:{}))}T=++O,y.forEach((e=>j.set(e.key,A)));let{results:g,loaderResults:b,fetcherResults:w}=await ne(S.matches,i,v,y,e);if(e.signal.aborted)return{shortCircuited:!0};y.forEach((e=>j.delete(e.key)));let D=he(g);if(D)return await re(S,D,{replace:d}),{shortCircuited:!0};let{loaderData:R,errors:E}=se(S,i,v,b,h,y,w,I);I.forEach(((e,t)=>{e.subscribe((r=>{(r||e.done)&&I.delete(t)}))})),function(){let e=[];for(let t of H){let r=S.fetchers.get(t);o(r,"Expected fetcher: "+t),"loading"===r.state&&(H.delete(t),e.push(t))}be(e)}();let P=Ee(T);return t({loaderData:R,errors:E},P||y.length>0?{fetchers:new Map(S.fetchers)}:{})}(P,s,m,f,d&&d.submission,d&&d.replace,D,E);_||(A=null,Q(s,t({matches:m},D?{actionData:D}:{},{loaderData:B,errors:q})))}function te(e){return S.fetchers.get(e)||W}async function re(a,n,i){var l;let{submission:c,replace:d}=void 0===i?{}:i;n.revalidate&&(x=!0);let u=s(a.location,n.location,{_isRedirect:!0});if(o(u,"Expected a location on the redirect navigation"),K.test(n.location)&&Y&&void 0!==(null==(l=window)?void 0:l.location)){let e=r.history.createURL(n.location),t=null==E(e.pathname,r.basename||"/");if(window.location.origin!==e.origin||t)return void(d?window.location.replace(n.location):window.location.assign(n.location))}A=null;let h=!0===d?e.Action.Replace:e.Action.Push,{formMethod:f,formAction:p,formEncType:m,formData:v}=a.navigation;!c&&f&&p&&v&&m&&(c={formMethod:f,formAction:p,formEncType:m,formData:v}),$.has(n.status)&&c&&we(c.formMethod)?await ee(h,u,{submission:t({},c,{formAction:n.location}),preventScrollReset:L}):await ee(h,u,{overrideNavigation:{state:"loading",location:u,formMethod:c?c.formMethod:void 0,formAction:c?c.formAction:void 0,formEncType:c?c.formEncType:void 0,formData:c?c.formData:void 0},preventScrollReset:L})}async function ne(e,t,a,o,n){let s=await Promise.all([...a.map((e=>ae("loader",n,e,t,l,i,R.basename))),...o.map((e=>{if(e.matches&&e.match)return ae("loader",oe(r.history,e.path,n.signal),e.match,e.matches,l,i,R.basename);return{type:u.error,error:ue(404,{pathname:e.path})}}))]),c=s.slice(0,a.length),d=s.slice(a.length);return await Promise.all([De(e,a,c,n.signal,!1,S.loaderData),De(e,o.map((e=>e.match)),d,n.signal,!0)]),{results:s,loaderResults:c,fetcherResults:d}}function ie(){x=!0,C.push(...ke()),z.forEach(((e,t)=>{j.has(t)&&(U.push(t),ge(t))}))}function fe(e,t,r){let a=ce(S.matches,t);ye(e),G({errors:{[a.route.id]:r},fetchers:new Map(S.fetchers)})}function ye(e){j.has(e)&&ge(e),z.delete(e),_.delete(e),H.delete(e),S.fetchers.delete(e)}function ge(e){let t=j.get(e);o(t,"Expected fetch controller: "+e),t.abort(),j.delete(e)}function be(e){for(let t of e){let e={state:"idle",data:te(t).data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0};S.fetchers.set(t,e)}}function Ee(e){let t=[];for(let[r,a]of _)if(a<e){let e=S.fetchers.get(r);o(e,"Expected fetcher: "+r),"loading"===e.state&&(ge(r),_.delete(r),t.push(r))}return be(t),t.length>0}function Se(e){S.blockers.delete(e),B.delete(e)}function Me(e,t){let r=S.blockers.get(e)||F;o("unblocked"===r.state&&"blocked"===t.state||"blocked"===r.state&&"blocked"===t.state||"blocked"===r.state&&"proceeding"===t.state||"blocked"===r.state&&"unblocked"===t.state||"proceeding"===r.state&&"unblocked"===t.state,"Invalid blocker state transition: "+r.state+" -> "+t.state),S.blockers.set(e,t),G({blockers:new Map(S.blockers)})}function Le(e){let{currentLocation:t,nextLocation:r,historyAction:a}=e;if(0===B.size)return;B.size>1&&n(!1,"A router only supports one blocker at a time");let o=Array.from(B.entries()),[i,s]=o[o.length-1],l=S.blockers.get(i);return l&&"proceeding"===l.state?void 0:s({currentLocation:t,nextLocation:r,historyAction:a})?i:void 0}function ke(e){let t=[];return I.forEach(((r,a)=>{e&&!e(a)||(r.cancel(),t.push(a),I.delete(a))})),t}function xe(e,t){if(v&&y&&g){let r=t.map((e=>Ae(e,S.loaderData))),a=y(e,r)||e.key,o=v[a];if("number"==typeof o)return o}return null}return R={get basename(){return r.basename},get state(){return S},get routes(){return c},initialize:function(){return h=r.history.listen((e=>{let{action:t,location:a,delta:o}=e;if(q)return void(q=!1);n(0===B.size||null!=o,"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 i=Le({currentLocation:S.location,nextLocation:a,historyAction:t});return i&&null!=o?(q=!0,r.history.go(-1*o),void Me(i,{state:"blocked",location:a,proceed(){Me(i,{state:"proceeding",proceed:void 0,reset:void 0,location:a}),r.history.go(o)},reset(){Se(i),G({blockers:new Map(R.state.blockers)})}})):ee(t,a)})),S.initialized||ee(e.Action.Pop,S.location),R},subscribe:function(e){return m.add(e),()=>m.delete(e)},enableScrollRestoration:function(e,t,r){if(v=e,g=t,y=r||(e=>e.key),!b&&S.navigation===N){b=!0;let e=xe(S.location,S.matches);null!=e&&G({restoreScrollPosition:e})}return()=>{v=null,g=null,y=null}},navigate:async function a(o,n){if("number"==typeof o)return void r.history.go(o);let{path:i,submission:l,error:c}=X(o,d,n),u=S.location,h=s(S.location,i,n&&n.state);h=t({},h,r.history.encodeLocation(h));let f=n&&null!=n.replace?n.replace:void 0,p=e.Action.Push;!0===f?p=e.Action.Replace:!1===f||null!=l&&we(l.formMethod)&&l.formAction===S.location.pathname+S.location.search&&(p=e.Action.Replace);let m=n&&"preventScrollReset"in n?!0===n.preventScrollReset:void 0,v=Le({currentLocation:u,nextLocation:h,historyAction:p});if(!v)return await ee(p,h,{submission:l,pendingError:c,preventScrollReset:m,replace:n&&n.replace});Me(v,{state:"blocked",location:h,proceed(){Me(v,{state:"proceeding",proceed:void 0,reset:void 0,location:h}),a(o,n)},reset(){Se(v),G({blockers:new Map(S.blockers)})}})},fetch:function(e,n,s,u){if(J)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.");j.has(e)&&ge(e);let h=p(a||c,s,r.basename);if(!h)return void fe(e,n,ue(404,{pathname:s}));let{path:f,submission:m}=X(s,d,u,!0),v=Pe(h,f);L=!0===(u&&u.preventScrollReset),m&&we(m.formMethod)?async function(e,n,s,d,u,h){if(ie(),z.delete(e),!d.route.action&&!d.route.lazy){let t=ue(405,{method:h.formMethod,pathname:s,routeId:n});return void fe(e,n,t)}let f=S.fetchers.get(e),m=t({state:"submitting"},h,{data:f&&f.data});S.fetchers.set(e,m),G({fetchers:new Map(S.fetchers)});let v=new AbortController,y=oe(r.history,s,v.signal,h);j.set(e,v);let g=await ae("action",y,d,u,l,i,R.basename);if(y.signal.aborted)return void(j.get(e)===v&&j.delete(e));if(ve(g)){j.delete(e),H.add(e);let r=t({state:"loading"},h,{data:void 0});return S.fetchers.set(e,r),G({fetchers:new Map(S.fetchers)}),re(S,g)}if(me(g))return void fe(e,n,g.error);if(pe(g))throw ue(400,{type:"defer-action"});let b=S.navigation.location||S.location,w=oe(r.history,b,v.signal),D=a||c,E="idle"!==S.navigation.state?p(D,S.navigation.location,r.basename):S.matches;o(E,"Didn't find any matches after fetcher action");let P=++O;_.set(e,P);let L=t({state:"loading",data:g.data},h);S.fetchers.set(e,L);let[k,B]=Z(r.history,S,E,h,b,x,C,U,z,D,r.basename,{[d.route.id]:g.data},void 0);B.filter((t=>t.key!==e)).forEach((e=>{let t=e.key,r=S.fetchers.get(t),a={state:"loading",data:r&&r.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0};S.fetchers.set(t,a),j.set(t,v)})),G({fetchers:new Map(S.fetchers)});let{results:q,loaderResults:$,fetcherResults:N}=await ne(S.matches,E,k,B,w);if(v.signal.aborted)return;_.delete(e),j.delete(e),B.forEach((e=>j.delete(e.key)));let W=he(q);if(W)return re(S,W);let{loaderData:F,errors:K}=se(S,S.matches,k,$,void 0,B,N,I),Y={state:"idle",data:g.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0};S.fetchers.set(e,Y);let J=Ee(P);"loading"===S.navigation.state&&P>T?(o(M,"Expected pending action"),A&&A.abort(),Q(S.navigation.location,{matches:E,loaderData:F,errors:K,fetchers:new Map(S.fetchers)})):(G(t({errors:K,loaderData:le(S.loaderData,F,E,K)},J?{fetchers:new Map(S.fetchers)}:{})),x=!1)}(e,n,f,v,h,m):(z.set(e,{routeId:n,path:f}),async function(e,a,n,s,c,d){let u=S.fetchers.get(e),h=t({state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},d,{data:u&&u.data});S.fetchers.set(e,h),G({fetchers:new Map(S.fetchers)});let f=new AbortController,p=oe(r.history,n,f.signal);j.set(e,f);let m=await ae("loader",p,s,c,l,i,R.basename);pe(m)&&(m=await Re(m,p.signal,!0)||m);j.get(e)===f&&j.delete(e);if(p.signal.aborted)return;if(ve(m))return void await re(S,m);if(me(m)){let t=ce(S.matches,a);return S.fetchers.delete(e),void G({fetchers:new Map(S.fetchers),errors:{[t.route.id]:m.error}})}o(!pe(m),"Unhandled fetcher deferred data");let v={state:"idle",data:m.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0};S.fetchers.set(e,v),G({fetchers:new Map(S.fetchers)})}(e,n,f,v,h,m))},revalidate:function(){ie(),G({revalidation:"loading"}),"submitting"!==S.navigation.state&&("idle"!==S.navigation.state?ee(M||S.historyAction,S.navigation.location,{overrideNavigation:S.navigation}):ee(S.historyAction,S.location,{startUninterruptedRevalidation:!0}))},createHref:e=>r.history.createHref(e),encodeLocation:e=>r.history.encodeLocation(e),getFetcher:te,deleteFetcher:ye,dispose:function(){h&&h(),m.clear(),A&&A.abort(),S.fetchers.forEach(((e,t)=>ye(t))),S.blockers.forEach(((e,t)=>Se(t)))},getBlocker:function(e,t){let r=S.blockers.get(e)||F;return B.get(e)!==t&&B.set(e,t),r},deleteBlocker:Se,_internalFetchControllers:j,_internalActiveDeferreds:I,_internalSetRoutes:function(e){a=e}},R},e.createStaticHandler=function(e,r){o(e.length>0,"You must provide a non-empty routes array to createStaticHandler");let a={},n=(null==r?void 0:r.detectErrorBoundary)||V,i=f(e,n,void 0,a),c=(r?r.basename:null)||"/";async function d(e,r,i,s,l){o(e.signal,"query()/queryRoute() requests must contain an AbortController signal");try{if(we(e.method.toLowerCase())){let o=await async function(e,r,o,i,s){let l;if(o.route.action||o.route.lazy){if(l=await ae("action",e,o,r,a,n,c,!0,s,i),e.signal.aborted){throw new Error((s?"queryRoute":"query")+"() call aborted")}}else{let t=ue(405,{method:e.method,pathname:new URL(e.url).pathname,routeId:o.route.id});if(s)throw t;l={type:u.error,error:t}}if(ve(l))throw new Response(null,{status:l.status,headers:{Location:l.location}});if(pe(l)){let e=ue(400,{type:"defer-action"});if(s)throw e;l={type:u.error,error:e}}if(s){if(me(l))throw l.error;return{matches:[o],loaderData:{},actionData:{[o.route.id]:l.data},errors:null,statusCode:200,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(me(l)){let a=ce(r,o.route.id);return t({},await h(e,r,i,void 0,{[a.route.id]:l.error}),{statusCode:_(l.error)?l.error.status:500,actionData:null,actionHeaders:t({},l.headers?{[o.route.id]:l.headers}:{})})}let d=new Request(e.url,{headers:e.headers,redirect:e.redirect,signal:e.signal});return t({},await h(d,r,i),l.statusCode?{statusCode:l.statusCode}:{},{actionData:{[o.route.id]:l.data},actionHeaders:t({},l.headers?{[o.route.id]:l.headers}:{})})}(e,i,l||Pe(i,r),s,null!=l);return o}let o=await h(e,i,s,l);return ye(o)?o:t({},o,{actionData:null,actionHeaders:{}})}catch(e){if((d=e)&&ye(d.response)&&(d.type===u.data||u.error)){if(e.type===u.error&&!ge(e.response))throw e.response;return e.response}if(ge(e))return e;throw e}var d}async function h(e,r,o,i,s){let l=null!=i;if(l&&(null==i||!i.route.loader)&&(null==i||!i.route.lazy))throw ue(400,{method:e.method,pathname:new URL(e.url).pathname,routeId:null==i?void 0:i.route.id});let d=(i?[i]:Q(r,Object.keys(s||{})[0])).filter((e=>e.route.loader||e.route.lazy));if(0===d.length)return{matches:r,loaderData:r.reduce(((e,t)=>Object.assign(e,{[t.route.id]:null})),{}),errors:s||null,statusCode:200,loaderHeaders:{},activeDeferreds:null};let u=await Promise.all([...d.map((t=>ae("loader",e,t,r,a,n,c,!0,l,o)))]);if(e.signal.aborted){throw new Error((l?"queryRoute":"query")+"() call aborted")}let h=new Map,f=ie(r,d,u,s,h),p=new Set(d.map((e=>e.route.id)));return r.forEach((e=>{p.has(e.route.id)||(f.loaderData[e.route.id]=null)})),t({},f,{matches:r,activeDeferreds:h.size>0?Object.fromEntries(h.entries()):null})}return{dataRoutes:i,query:async function(e,r){let{requestContext:a}=void 0===r?{}:r,o=new URL(e.url),n=e.method,u=s("",l(o),null,"default"),h=p(i,u,c);if(!be(n)&&"HEAD"!==n){let e=ue(405,{method:n}),{matches:t,route:r}=de(i);return{basename:c,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(!h){let e=ue(404,{pathname:u.pathname}),{matches:t,route:r}=de(i);return{basename:c,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}let f=await d(e,u,h,a);return ye(f)?f:t({location:u,basename:c},f)},queryRoute:async function(e,t){let{routeId:r,requestContext:a}=void 0===t?{}:t,o=new URL(e.url),n=e.method,u=s("",l(o),null,"default"),h=p(i,u,c);if(!be(n)&&"HEAD"!==n&&"OPTIONS"!==n)throw ue(405,{method:n});if(!h)throw ue(404,{pathname:u.pathname});let f=r?h.find((e=>e.route.id===r)):Pe(h,u);if(r&&!f)throw ue(403,{pathname:u.pathname,routeId:r});if(!f)throw ue(404,{pathname:u.pathname});let m=await d(e,u,h,a,f);if(ye(m))return m;let v=m.errors?Object.values(m.errors)[0]:void 0;if(void 0!==v)throw v;if(m.actionData)return Object.values(m.actionData)[0];if(m.loaderData){var y;let e=Object.values(m.loaderData)[0];return null!=(y=m.activeDeferreds)&&y[f.route.id]&&(e[G]=m.activeDeferreds[f.route.id]),e}}}},e.defer=function(e,t){return void 0===t&&(t={}),new j(e,"number"==typeof t?{status:t}:t)},e.generatePath=function(e,t){void 0===t&&(t={});let r=e;return r.endsWith("*")&&"*"!==r&&!r.endsWith("/*")&&(n(!1,'Route path "'+r+'" will be treated as if it were "'+r.replace(/\*$/,"/*")+'" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "'+r.replace(/\*$/,"/*")+'".'),r=r.replace(/\*$/,"/*")),(r.startsWith("/")?"/":"")+r.split(/\/+/).map(((e,r,a)=>{if(r===a.length-1&&"*"===e){return t["*"]}const n=e.match(/^:(\w+)(\??)$/);if(n){const[,e,r]=n;let a=t[e];return"?"===r?null==a?"":a:(null==a&&o(!1,'Missing ":'+e+'" param'),a)}return e.replace(/\?$/g,"")})).filter((e=>!!e)).join("/")},e.getStaticContextFromError=function(e,r,a){return t({},r,{statusCode:500,errors:{[r._deepestRenderedBoundaryId||e[0].id]:a}})},e.getToPathname=function(e){return""===e||""===e.pathname?"/":"string"==typeof e?c(e).pathname:e.pathname},e.isRouteErrorResponse=_,e.joinPaths=L,e.json=function(e,r){void 0===r&&(r={});let a="number"==typeof r?{status:r}:r,o=new Headers(a.headers);return o.has("Content-Type")||o.set("Content-Type","application/json; charset=utf-8"),new Response(JSON.stringify(e),t({},a,{headers:o}))},e.matchPath=D,e.matchRoutes=p,e.normalizePathname=k,e.parsePath=c,e.redirect=function(e,r){void 0===r&&(r=302);let a=r;"number"==typeof a?a={status:a}:void 0===a.status&&(a.status=302);let o=new Headers(a.headers);return o.set("Location",e),new Response(null,t({},a,{headers:o}))},e.resolvePath=A,e.resolveTo=M,e.stripBasename=E,Object.defineProperty(e,"__esModule",{value:!0})}));
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).RemixRouter={})}(this,(function(e){"use strict";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(e[a]=r[a])}return e},t.apply(this,arguments)}let r=function(e){return e.Pop="POP",e.Push="PUSH",e.Replace="REPLACE",e}({});const a="popstate";function o(e,t){if(!1===e||null==e)throw new Error(t)}function n(e,t){if(!e){"undefined"!=typeof console&&console.warn(t);try{throw new Error(t)}catch(e){}}}function i(e,t){return{usr:e.state,key:e.key,idx:t}}function s(e,r,a,o){return void 0===a&&(a=null),t({pathname:"string"==typeof e?e:e.pathname,search:"",hash:""},"string"==typeof r?d(r):r,{state:a,key:r&&r.key||o||Math.random().toString(36).substr(2,8)})}function l(e){let{pathname:t="/",search:r="",hash:a=""}=e;return r&&"?"!==r&&(t+="?"===r.charAt(0)?r:"?"+r),a&&"#"!==a&&(t+="#"===a.charAt(0)?a:"#"+a),t}function d(e){let t={};if(e){let r=e.indexOf("#");r>=0&&(t.hash=e.substr(r),e=e.substr(0,r));let a=e.indexOf("?");a>=0&&(t.search=e.substr(a),e=e.substr(0,a)),e&&(t.pathname=e)}return t}function u(e,n,d,u){void 0===u&&(u={});let{window:c=document.defaultView,v5Compat:h=!1}=u,f=c.history,p=r.Pop,m=null,y=v();function v(){return(f.state||{idx:null}).idx}function g(){p=r.Pop;let e=v(),t=null==e?null:e-y;y=e,m&&m({action:p,location:w.location,delta:t})}function b(e){let t="null"!==c.location.origin?c.location.origin:c.location.href,r="string"==typeof e?e:l(e);return r=r.replace(/ $/,"%20"),o(t,"No window.location.(origin|href) available to create URL for href: "+r),new URL(r,t)}null==y&&(y=0,f.replaceState(t({},f.state,{idx:y}),""));let w={get action(){return p},get location(){return e(c,f)},listen(e){if(m)throw new Error("A history only accepts one active listener");return c.addEventListener(a,g),m=e,()=>{c.removeEventListener(a,g),m=null}},createHref:e=>n(c,e),createURL:b,encodeLocation(e){let t=b(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(e,t){p=r.Push;let a=s(w.location,e,t);d&&d(a,e),y=v()+1;let o=i(a,y),n=w.createHref(a);try{f.pushState(o,"",n)}catch(e){if(e instanceof DOMException&&"DataCloneError"===e.name)throw e;c.location.assign(n)}h&&m&&m({action:p,location:w.location,delta:1})},replace:function(e,t){p=r.Replace;let a=s(w.location,e,t);d&&d(a,e),y=v();let o=i(a,y),n=w.createHref(a);f.replaceState(o,"",n),h&&m&&m({action:p,location:w.location,delta:0})},go:e=>f.go(e)};return w}let c=function(e){return e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error",e}({});const h=new Set(["lazy","caseSensitive","path","id","index","children"]);function f(e,r,a,n){return void 0===a&&(a=[]),void 0===n&&(n={}),e.map(((e,i)=>{let s=[...a,i],l="string"==typeof e.id?e.id:s.join("-");if(o(!0!==e.index||!e.children,"Cannot specify children on an index route"),o(!n[l],'Found a route id collision on id "'+l+"\". Route id's must be globally unique within Data Router usages"),function(e){return!0===e.index}(e)){let a=t({},e,r(e),{id:l});return n[l]=a,a}{let a=t({},e,r(e),{id:l,children:void 0});return n[l]=a,e.children&&(a.children=f(e.children,r,s,n)),a}}))}function p(e,t,r){void 0===r&&(r="/");let a=R(("string"==typeof t?d(t):t).pathname||"/",r);if(null==a)return null;let o=y(e);!function(e){e.sort(((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){return e.length===t.length&&e.slice(0,-1).every(((e,r)=>e===t[r]))?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map((e=>e.childrenIndex)),t.routesMeta.map((e=>e.childrenIndex)))))}(o);let n=null;for(let e=0;null==n&&e<o.length;++e){let t=E(a);n=D(o[e],t)}return n}function m(e,t){let{route:r,pathname:a,params:o}=e;return{id:r.id,pathname:a,params:o,data:t[r.id],handle:r.handle}}function y(e,t,r,a){void 0===t&&(t=[]),void 0===r&&(r=[]),void 0===a&&(a="");let n=(e,n,i)=>{let s={relativePath:void 0===i?e.path||"":i,caseSensitive:!0===e.caseSensitive,childrenIndex:n,route:e};s.relativePath.startsWith("/")&&(o(s.relativePath.startsWith(a),'Absolute route path "'+s.relativePath+'" nested under path "'+a+'" is not valid. An absolute child route path must start with the combined path of all its parent routes.'),s.relativePath=s.relativePath.slice(a.length));let l=j([a,s.relativePath]),d=r.concat(s);e.children&&e.children.length>0&&(o(!0!==e.index,'Index routes must not have child routes. Please remove all child routes from route path "'+l+'".'),y(e.children,t,d,l)),(null!=e.path||e.index)&&t.push({path:l,score:w(l,e.index),routesMeta:d})};return e.forEach(((e,t)=>{var r;if(""!==e.path&&null!=(r=e.path)&&r.includes("?"))for(let r of v(e.path))n(e,t,r);else n(e,t)})),t}function v(e){let t=e.split("/");if(0===t.length)return[];let[r,...a]=t,o=r.endsWith("?"),n=r.replace(/\?$/,"");if(0===a.length)return o?[n,""]:[n];let i=v(a.join("/")),s=[];return s.push(...i.map((e=>""===e?n:[n,e].join("/")))),o&&s.push(...i),s.map((t=>e.startsWith("/")&&""===t?"/":t))}const g=/^:[\w-]+$/,b=e=>"*"===e;function w(e,t){let r=e.split("/"),a=r.length;return r.some(b)&&(a+=-2),t&&(a+=2),r.filter((e=>!b(e))).reduce(((e,t)=>e+(g.test(t)?3:""===t?1:10)),a)}function D(e,t){let{routesMeta:r}=e,a={},o="/",n=[];for(let e=0;e<r.length;++e){let i=r[e],s=e===r.length-1,l="/"===o?t:t.slice(o.length)||"/",d=S({path:i.relativePath,caseSensitive:i.caseSensitive,end:s},l);if(!d)return null;Object.assign(a,d.params);let u=i.route;n.push({params:a,pathname:j([o,d.pathname]),pathnameBase:_(j([o,d.pathnameBase])),route:u}),"/"!==d.pathnameBase&&(o=j([o,d.pathnameBase]))}return n}function S(e,t){"string"==typeof e&&(e={path:e,caseSensitive:!1,end:!0});let[r,a]=function(e,t,r){void 0===t&&(t=!1);void 0===r&&(r=!0);n("*"===e||!e.endsWith("*")||e.endsWith("/*"),'Route path "'+e+'" will be treated as if it were "'+e.replace(/\*$/,"/*")+'" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "'+e.replace(/\*$/,"/*")+'".');let a=[],o="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,((e,t,r)=>(a.push({paramName:t,isOptional:null!=r}),r?"/?([^\\/]+)?":"/([^\\/]+)")));e.endsWith("*")?(a.push({paramName:"*"}),o+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):r?o+="\\/*$":""!==e&&"/"!==e&&(o+="(?:(?=\\/|$))");return[new RegExp(o,t?void 0:"i"),a]}(e.path,e.caseSensitive,e.end),o=t.match(r);if(!o)return null;let i=o[0],s=i.replace(/(.)\/+$/,"$1"),l=o.slice(1);return{params:a.reduce(((e,t,r)=>{let{paramName:a,isOptional:o}=t;if("*"===a){let e=l[r]||"";s=i.slice(0,i.length-e.length).replace(/(.)\/+$/,"$1")}const n=l[r];return e[a]=o&&!n?void 0:(n||"").replace(/%2F/g,"/"),e}),{}),pathname:i,pathnameBase:s,pattern:e}}function E(e){try{return e.split("/").map((e=>decodeURIComponent(e).replace(/\//g,"%2F"))).join("/")}catch(t){return n(!1,'The URL path "'+e+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent encoding ('+t+")."),e}}function R(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let r=t.endsWith("/")?t.length-1:t.length,a=e.charAt(r);return a&&"/"!==a?null:e.slice(r)||"/"}function P(e,t){void 0===t&&(t="/");let{pathname:r,search:a="",hash:o=""}="string"==typeof e?d(e):e,n=r?r.startsWith("/")?r:function(e,t){let r=t.replace(/\/+$/,"").split("/");return e.split("/").forEach((e=>{".."===e?r.length>1&&r.pop():"."!==e&&r.push(e)})),r.length>1?r.join("/"):"/"}(r,t):t;return{pathname:n,search:k(a),hash:C(o)}}function x(e,t,r,a){return"Cannot include a '"+e+"' character in a manually specified `to."+t+"` field ["+JSON.stringify(a)+"]. Please separate it out to the `to."+r+'` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.'}function L(e){return e.filter(((e,t)=>0===t||e.route.path&&e.route.path.length>0))}function A(e,t){let r=L(e);return t?r.map(((t,r)=>r===e.length-1?t.pathname:t.pathnameBase)):r.map((e=>e.pathnameBase))}function M(e,r,a,n){let i;void 0===n&&(n=!1),"string"==typeof e?i=d(e):(i=t({},e),o(!i.pathname||!i.pathname.includes("?"),x("?","pathname","search",i)),o(!i.pathname||!i.pathname.includes("#"),x("#","pathname","hash",i)),o(!i.search||!i.search.includes("#"),x("#","search","hash",i)));let s,l=""===e||""===i.pathname,u=l?"/":i.pathname;if(null==u)s=a;else{let e=r.length-1;if(!n&&u.startsWith("..")){let t=u.split("/");for(;".."===t[0];)t.shift(),e-=1;i.pathname=t.join("/")}s=e>=0?r[e]:"/"}let c=P(i,s),h=u&&"/"!==u&&u.endsWith("/"),f=(l||"."===u)&&a.endsWith("/");return c.pathname.endsWith("/")||!h&&!f||(c.pathname+="/"),c}const j=e=>e.join("/").replace(/\/\/+/g,"/"),_=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),k=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",C=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";class T extends Error{}class U{constructor(e,t){let r;this.pendingKeysSet=new Set,this.subscribers=new Set,this.deferredKeys=[],o(e&&"object"==typeof e&&!Array.isArray(e),"defer() only accepts plain objects"),this.abortPromise=new Promise(((e,t)=>r=t)),this.controller=new AbortController;let a=()=>r(new T("Deferred data aborted"));this.unlistenAbortSignal=()=>this.controller.signal.removeEventListener("abort",a),this.controller.signal.addEventListener("abort",a),this.data=Object.entries(e).reduce(((e,t)=>{let[r,a]=t;return Object.assign(e,{[r]:this.trackPromise(r,a)})}),{}),this.done&&this.unlistenAbortSignal(),this.init=t}trackPromise(e,t){if(!(t instanceof Promise))return t;this.deferredKeys.push(e),this.pendingKeysSet.add(e);let r=Promise.race([t,this.abortPromise]).then((t=>this.onSettle(r,e,void 0,t)),(t=>this.onSettle(r,e,t)));return r.catch((()=>{})),Object.defineProperty(r,"_tracked",{get:()=>!0}),r}onSettle(e,t,r,a){if(this.controller.signal.aborted&&r instanceof T)return this.unlistenAbortSignal(),Object.defineProperty(e,"_error",{get:()=>r}),Promise.reject(r);if(this.pendingKeysSet.delete(t),this.done&&this.unlistenAbortSignal(),void 0===r&&void 0===a){let r=new Error('Deferred data for key "'+t+'" resolved/rejected with `undefined`, you must resolve/reject with a value or `null`.');return Object.defineProperty(e,"_error",{get:()=>r}),this.emit(!1,t),Promise.reject(r)}return void 0===a?(Object.defineProperty(e,"_error",{get:()=>r}),this.emit(!1,t),Promise.reject(r)):(Object.defineProperty(e,"_data",{get:()=>a}),this.emit(!1,t),a)}emit(e,t){this.subscribers.forEach((r=>r(e,t)))}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}cancel(){this.controller.abort(),this.pendingKeysSet.forEach(((e,t)=>this.pendingKeysSet.delete(t))),this.emit(!0)}async resolveData(e){let t=!1;if(!this.done){let r=()=>this.cancel();e.addEventListener("abort",r),t=await new Promise((t=>{this.subscribe((a=>{e.removeEventListener("abort",r),(a||this.done)&&t(a)}))}))}return t}get done(){return 0===this.pendingKeysSet.size}get unwrappedData(){return o(null!==this.data&&this.done,"Can only unwrap data on initialized and settled deferreds"),Object.entries(this.data).reduce(((e,t)=>{let[r,a]=t;return Object.assign(e,{[r]:O(a)})}),{})}get pendingKeys(){return Array.from(this.pendingKeysSet)}}function O(e){if(!function(e){return e instanceof Promise&&!0===e._tracked}(e))return e;if(e._error)throw e._error;return e._data}const H=function(e,r){void 0===r&&(r=302);let a=r;"number"==typeof a?a={status:a}:void 0===a.status&&(a.status=302);let o=new Headers(a.headers);return o.set("Location",e),new Response(null,t({},a,{headers:o}))};class I{constructor(e,t,r,a){void 0===a&&(a=!1),this.status=e,this.statusText=t||"",this.internal=a,r instanceof Error?(this.data=r.toString(),this.error=r):this.data=r}}function z(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"boolean"==typeof e.internal&&"data"in e}function F(e){return null!=e&&!0===e._isDecodedResponse&&"number"==typeof e.status&&"string"==typeof e.statusText&&null!=e.headers&&"data"in e}const B=["post","put","patch","delete"],N=new Set(B),W=["get",...B],$=new Set(W),q=new Set([301,302,303,307,308]),K=new Set([307,308]),Y={state:"idle",location:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},J={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},V={state:"unblocked",proceed:void 0,reset:void 0,location:void 0},X=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,G=e=>({hasErrorBoundary:Boolean(e.hasErrorBoundary)}),Q="remix-router-transitions";const Z=Symbol("deferred");function ee(e,t,r){if(r.v7_throwAbortReason&&void 0!==e.signal.reason)throw e.signal.reason;throw new Error((t?"queryRoute":"query")+"() call aborted: "+e.method+" "+e.url)}function te(e,t,r,a,o,n,i,s){let d,u;if(i){d=[];for(let e of t)if(d.push(e),e.route.id===i){u=e;break}}else d=t,u=t[t.length-1];let c=M(o||".",A(d,n),R(e.pathname,r)||e.pathname,"path"===s);return null==o&&(c.search=e.search,c.hash=e.hash),null!=o&&""!==o&&"."!==o||!u||!u.route.index||Te(c.search)||(c.search=c.search?c.search.replace(/^\?/,"?index&"):"?index"),a&&"/"!==r&&(c.pathname="/"===c.pathname?r:j([r,c.pathname])),l(c)}function re(e,t,r,a){if(!a||!function(e){return null!=e&&("formData"in e&&null!=e.formData||"body"in e&&void 0!==e.body)}(a))return{path:r};if(a.formMethod&&!je(a.formMethod))return{path:r,error:De(405,{method:a.formMethod})};let n,i,s=()=>({path:r,error:De(400,{type:"invalid-body"})}),u=a.formMethod||"get",c=e?u.toUpperCase():u.toLowerCase(),h=Ee(r);if(void 0!==a.body){if("text/plain"===a.formEncType){if(!_e(c))return s();let e="string"==typeof a.body?a.body:a.body instanceof FormData||a.body instanceof URLSearchParams?Array.from(a.body.entries()).reduce(((e,t)=>{let[r,a]=t;return""+e+r+"="+a+"\n"}),""):String(a.body);return{path:r,submission:{formMethod:c,formAction:h,formEncType:a.formEncType,formData:void 0,json:void 0,text:e}}}if("application/json"===a.formEncType){if(!_e(c))return s();try{let e="string"==typeof a.body?JSON.parse(a.body):a.body;return{path:r,submission:{formMethod:c,formAction:h,formEncType:a.formEncType,formData:void 0,json:e,text:void 0}}}catch(e){return s()}}}if(o("function"==typeof FormData,"FormData is not available in this environment"),a.formData)n=fe(a.formData),i=a.formData;else if(a.body instanceof FormData)n=fe(a.body),i=a.body;else if(a.body instanceof URLSearchParams)n=a.body,i=pe(n);else if(null==a.body)n=new URLSearchParams,i=new FormData;else try{n=new URLSearchParams(a.body),i=pe(n)}catch(e){return s()}let f={formMethod:c,formAction:h,formEncType:a&&a.formEncType||"application/x-www-form-urlencoded",formData:i,json:void 0,text:void 0};if(_e(f.formMethod))return{path:r,submission:f};let p=d(r);return t&&p.search&&Te(p.search)&&n.append("index",""),p.search="?"+n,{path:l(p),submission:f}}function ae(e,t){let r=e;if(t){let a=e.findIndex((e=>e.route.id===t));a>=0&&(r=e.slice(0,a))}return r}function oe(e,r,a,o,n,i,s,l,d,u,c,h,f,m,y,v){let g=v?xe(v[1])?v[1].error:v[1].data:void 0,b=e.createURL(r.location),w=e.createURL(n),D=v&&xe(v[1])?v[0]:void 0,S=D?ae(a,D):a,E=s&&v&&"number"==typeof v[1].statusCode&&v[1].statusCode>=400,R=S.filter(((e,a)=>{let{route:n}=e;if(n.lazy)return!0;if(null==n.loader)return!1;if(i)return!("function"==typeof n.loader&&!n.loader.hydrate)||void 0===r.loaderData[n.id]&&(!r.errors||void 0===r.errors[n.id]);if(function(e,t,r){let a=!t||r.route.id!==t.route.id,o=void 0===e[r.route.id];return a||o}(r.loaderData,r.matches[a],e)||d.some((t=>t===e.route.id)))return!0;let s=r.matches[a],u=e;return ie(e,t({currentUrl:b,currentParams:s.params,nextUrl:w,nextParams:u.params},o,{actionResult:g,defaultShouldRevalidate:!E&&(l||b.pathname+b.search===w.pathname+w.search||b.search!==w.search||ne(s,u))}))})),P=[];return h.forEach(((e,n)=>{if(i||!a.some((t=>t.route.id===e.routeId))||c.has(n))return;let s=p(m,e.path,y);if(!s)return void P.push({key:n,routeId:e.routeId,path:e.path,matches:null,match:null,controller:null});let d=r.fetchers.get(n),h=Ue(s,e.path),v=!1;v=!f.has(n)&&(!!u.includes(n)||(d&&"idle"!==d.state&&void 0===d.data?l:ie(h,t({currentUrl:b,currentParams:r.matches[r.matches.length-1].params,nextUrl:w,nextParams:a[a.length-1].params},o,{actionResult:g,defaultShouldRevalidate:!E&&l})))),v&&P.push({key:n,routeId:e.routeId,path:e.path,matches:s,match:h,controller:new AbortController})})),[R,P]}function ne(e,t){let r=e.route.path;return e.pathname!==t.pathname||null!=r&&r.endsWith("*")&&e.params["*"]!==t.params["*"]}function ie(e,t){if(e.route.shouldRevalidate){let r=e.route.shouldRevalidate(t);if("boolean"==typeof r)return r}return t.defaultShouldRevalidate}async function se(e,r,a){if(!e.lazy)return;let i=await e.lazy();if(!e.lazy)return;let s=a[e.id];o(s,"No route found in manifest");let l={};for(let e in i){let t=void 0!==s[e]&&"hasErrorBoundary"!==e;n(!t,'Route "'+s.id+'" has a static property "'+e+'" defined but its lazy function is also returning a value for this property. The lazy route property "'+e+'" will be ignored.'),t||h.has(e)||(l[e]=i[e])}Object.assign(s,l),Object.assign(s,t({},r(s),{lazy:void 0}))}function le(e){return Promise.all(e.matches.map((e=>e.resolve())))}async function de(e,r,a,n,i,s,l,d){let u=n.reduce(((e,t)=>e.add(t.route.id)),new Set),h=new Set,f=await e({matches:i.map((e=>{let n=u.has(e.route.id);return t({},e,{shouldLoad:n,resolve:t=>(h.add(e.route.id),n?async function(e,t,r,a,n,i,s){let l,d,u=a=>{let o,n=new Promise(((e,t)=>o=t));d=()=>o(),t.signal.addEventListener("abort",d);let l=o=>"function"!=typeof a?Promise.reject(new Error('You cannot call the handler for a route which defines a boolean "'+e+'" [routeId: '+r.route.id+"]")):a({request:t,params:r.params,context:s},...void 0!==o?[o]:[]),u=i?i((async e=>l(e))):l();return Promise.race([u,n])};try{let i=r.route[e];if(r.route.lazy)if(i){let e,[t]=await Promise.all([u(i).catch((t=>{e=t})),se(r.route,n,a)]);if(void 0!==e)throw e;l=t}else{if(await se(r.route,n,a),i=r.route[e],!i){if("action"===e){let e=new URL(t.url),a=e.pathname+e.search;throw De(405,{method:t.method,pathname:a,routeId:r.route.id})}return{type:c.data,result:void 0}}l=await u(i)}else{if(!i){let e=new URL(t.url);throw De(404,{pathname:e.pathname+e.search})}l=await u(i)}o(void 0!==l,"You defined "+("action"===e?"an action":"a loader")+' for route "'+r.route.id+"\" but didn't return anything from your `"+e+"` function. Please return a value or `null`.")}catch(e){return{type:c.error,result:e}}finally{d&&t.signal.removeEventListener("abort",d)}return{type:c.data,result:l}}(r,a,e,s,l,t,d):Promise.resolve({type:c.data,result:void 0}))})})),request:a,params:i[0].params});return i.forEach((e=>o(h.has(e.route.id),'`match.resolve()` was not called for route id "'+e.route.id+'". You must call `match.resolve()` on every match passed to `dataStrategy` to ensure all routes are properly loaded.'))),f.filter(((e,t)=>u.has(i[t].route.id)))}async function ue(e){let{result:t,type:r}=e;if(Me(t)){let e;try{let r=t.headers.get("Content-Type");e=r&&/\bapplication\/json\b/.test(r)?null==t.body?null:await t.json():await t.text()}catch(e){return{type:c.error,error:e}}return r===c.error?{type:r,error:new I(t.status,t.statusText,e),statusCode:t.status,headers:t.headers}:{type:c.data,data:e,statusCode:t.status,headers:t.headers}}return F(t)?r===c.error?{type:r,error:new I(t.status,t.statusText,t.data),statusCode:t.status,headers:t.headers}:{type:c.data,data:t.data,statusCode:t.status,headers:t.headers}:r===c.error?{type:r,error:t,statusCode:z(t)?t.status:void 0}:Ae(t)?{type:c.deferred,deferredData:t,statusCode:null==(a=t.init)?void 0:a.status,headers:(null==(o=t.init)?void 0:o.headers)&&new Headers(t.init.headers)}:{type:c.data,data:t};var a,o}function ce(e,t,r,a,n,i){let s=e.headers.get("Location");if(o(s,"Redirects returned/thrown from loaders/actions must have a Location header"),!X.test(s)){let o=a.slice(0,a.findIndex((e=>e.route.id===r))+1);s=te(new URL(t.url),o,n,!0,s,i),e.headers.set("Location",s)}return e}function he(e,t,r,a){let o=e.createURL(Ee(t)).toString(),n={signal:r};if(a&&_e(a.formMethod)){let{formMethod:e,formEncType:t}=a;n.method=e.toUpperCase(),"application/json"===t?(n.headers=new Headers({"Content-Type":t}),n.body=JSON.stringify(a.json)):"text/plain"===t?n.body=a.text:"application/x-www-form-urlencoded"===t&&a.formData?n.body=fe(a.formData):n.body=a.formData}return new Request(o,n)}function fe(e){let t=new URLSearchParams;for(let[r,a]of e.entries())t.append(r,"string"==typeof a?a:a.name);return t}function pe(e){let t=new FormData;for(let[r,a]of e.entries())t.append(r,a);return t}function me(e,t,r,a,n){let i,s={},l=null,d=!1,u={},c=a&&xe(a[1])?a[1].error:void 0;return r.forEach(((r,a)=>{let h=t[a].route.id;if(o(!Le(r),"Cannot handle redirect results in processLoaderData"),xe(r)){let t=be(e,h),a=r.error;void 0!==c&&(a=c,c=void 0),l=l||{},null==l[t.route.id]&&(l[t.route.id]=a),s[h]=void 0,d||(d=!0,i=z(r.error)?r.error.status:500),r.headers&&(u[h]=r.headers)}else Pe(r)?(n.set(h,r.deferredData),s[h]=r.deferredData.data,null==r.statusCode||200===r.statusCode||d||(i=r.statusCode),r.headers&&(u[h]=r.headers)):(s[h]=r.data,r.statusCode&&200!==r.statusCode&&!d&&(i=r.statusCode),r.headers&&(u[h]=r.headers))})),void 0!==c&&a&&(l={[a[0]]:c},s[a[0]]=void 0),{loaderData:s,errors:l,statusCode:i||200,loaderHeaders:u}}function ye(e,r,a,n,i,s,l,d){let{loaderData:u,errors:c}=me(r,a,n,i,d);for(let r=0;r<s.length;r++){let{key:a,match:n,controller:i}=s[r];o(void 0!==l&&void 0!==l[r],"Did not find corresponding fetcher result");let d=l[r];if(!i||!i.signal.aborted)if(xe(d)){let r=be(e.matches,null==n?void 0:n.route.id);c&&c[r.route.id]||(c=t({},c,{[r.route.id]:d.error})),e.fetchers.delete(a)}else if(Le(d))o(!1,"Unhandled fetcher revalidation redirect");else if(Pe(d))o(!1,"Unhandled fetcher deferred data");else{let t=Fe(d.data);e.fetchers.set(a,t)}}return{loaderData:u,errors:c}}function ve(e,r,a,o){let n=t({},r);for(let t of a){let a=t.route.id;if(r.hasOwnProperty(a)?void 0!==r[a]&&(n[a]=r[a]):void 0!==e[a]&&t.route.loader&&(n[a]=e[a]),o&&o.hasOwnProperty(a))break}return n}function ge(e){return e?xe(e[1])?{actionData:{}}:{actionData:{[e[0]]:e[1].data}}:{}}function be(e,t){return(t?e.slice(0,e.findIndex((e=>e.route.id===t))+1):[...e]).reverse().find((e=>!0===e.route.hasErrorBoundary))||e[0]}function we(e){let t=1===e.length?e[0]:e.find((e=>e.index||!e.path||"/"===e.path))||{id:"__shim-error-route__"};return{matches:[{params:{},pathname:"",pathnameBase:"",route:t}],route:t}}function De(e,t){let{pathname:r,routeId:a,method:o,type:n}=void 0===t?{}:t,i="Unknown Server Error",s="Unknown @remix-run/router error";return 400===e?(i="Bad Request",o&&r&&a?s="You made a "+o+' request to "'+r+'" but did not provide a `loader` for route "'+a+'", so there is no way to handle the request.':"defer-action"===n?s="defer() is not supported in actions":"invalid-body"===n&&(s="Unable to encode submission body")):403===e?(i="Forbidden",s='Route "'+a+'" does not match URL "'+r+'"'):404===e?(i="Not Found",s='No route matches URL "'+r+'"'):405===e&&(i="Method Not Allowed",o&&r&&a?s="You made a "+o.toUpperCase()+' request to "'+r+'" but did not provide an `action` for route "'+a+'", so there is no way to handle the request.':o&&(s='Invalid request method "'+o.toUpperCase()+'"')),new I(e||500,i,new Error(s),!0)}function Se(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(Le(r))return{result:r,idx:t}}}function Ee(e){return l(t({},"string"==typeof e?d(e):e,{hash:""}))}function Re(e){return Me(e.result)&&q.has(e.result.status)}function Pe(e){return e.type===c.deferred}function xe(e){return e.type===c.error}function Le(e){return(e&&e.type)===c.redirect}function Ae(e){let t=e;return t&&"object"==typeof t&&"object"==typeof t.data&&"function"==typeof t.subscribe&&"function"==typeof t.cancel&&"function"==typeof t.resolveData}function Me(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"object"==typeof e.headers&&void 0!==e.body}function je(e){return $.has(e.toLowerCase())}function _e(e){return N.has(e.toLowerCase())}async function ke(e,t,r,a,n,i){for(let s=0;s<r.length;s++){let l=r[s],d=t[s];if(!d)continue;let u=e.find((e=>e.route.id===d.route.id)),c=null!=u&&!ne(u,d)&&void 0!==(i&&i[d.route.id]);if(Pe(l)&&(n||c)){let e=a[s];o(e,"Expected an AbortSignal for revalidating fetcher deferred result"),await Ce(l,e,n).then((e=>{e&&(r[s]=e||r[s])}))}}}async function Ce(e,t,r){if(void 0===r&&(r=!1),!await e.deferredData.resolveData(t)){if(r)try{return{type:c.data,data:e.deferredData.unwrappedData}}catch(e){return{type:c.error,error:e}}return{type:c.data,data:e.deferredData.data}}}function Te(e){return new URLSearchParams(e).getAll("index").some((e=>""===e))}function Ue(e,t){let r="string"==typeof t?d(t).search:t.search;if(e[e.length-1].route.index&&Te(r||""))return e[e.length-1];let a=L(e);return a[a.length-1]}function Oe(e){let{formMethod:t,formAction:r,formEncType:a,text:o,formData:n,json:i}=e;if(t&&r&&a)return null!=o?{formMethod:t,formAction:r,formEncType:a,formData:void 0,json:void 0,text:o}:null!=n?{formMethod:t,formAction:r,formEncType:a,formData:n,json:void 0,text:void 0}:void 0!==i?{formMethod:t,formAction:r,formEncType:a,formData:void 0,json:i,text:void 0}:void 0}function He(e,t){if(t){return{state:"loading",location:e,formMethod:t.formMethod,formAction:t.formAction,formEncType:t.formEncType,formData:t.formData,json:t.json,text:t.text}}return{state:"loading",location:e,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0}}function Ie(e,t){return{state:"submitting",location:e,formMethod:t.formMethod,formAction:t.formAction,formEncType:t.formEncType,formData:t.formData,json:t.json,text:t.text}}function ze(e,t){if(e){return{state:"loading",formMethod:e.formMethod,formAction:e.formAction,formEncType:e.formEncType,formData:e.formData,json:e.json,text:e.text,data:t}}return{state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0,data:t}}function Fe(e){return{state:"idle",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0,data:e}}e.AbortedDeferredError=T,e.Action=r,e.IDLE_BLOCKER=V,e.IDLE_FETCHER=J,e.IDLE_NAVIGATION=Y,e.UNSAFE_DEFERRED_SYMBOL=Z,e.UNSAFE_DeferredData=U,e.UNSAFE_ErrorResponseImpl=I,e.UNSAFE_convertRouteMatchToUiMatch=m,e.UNSAFE_convertRoutesToDataRoutes=f,e.UNSAFE_getResolveToMatches=A,e.UNSAFE_invariant=o,e.UNSAFE_warning=n,e.createBrowserHistory=function(e){return void 0===e&&(e={}),u((function(e,t){let{pathname:r,search:a,hash:o}=e.location;return s("",{pathname:r,search:a,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){return"string"==typeof t?t:l(t)}),null,e)},e.createHashHistory=function(e){return void 0===e&&(e={}),u((function(e,t){let{pathname:r="/",search:a="",hash:o=""}=d(e.location.hash.substr(1));return r.startsWith("/")||r.startsWith(".")||(r="/"+r),s("",{pathname:r,search:a,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){let r=e.document.querySelector("base"),a="";if(r&&r.getAttribute("href")){let t=e.location.href,r=t.indexOf("#");a=-1===r?t:t.slice(0,r)}return a+"#"+("string"==typeof t?t:l(t))}),(function(e,t){n("/"===e.pathname.charAt(0),"relative pathnames are not supported in hash history.push("+JSON.stringify(t)+")")}),e)},e.createMemoryHistory=function(e){void 0===e&&(e={});let t,{initialEntries:a=["/"],initialIndex:o,v5Compat:i=!1}=e;t=a.map(((e,t)=>m(e,"string"==typeof e?null:e.state,0===t?"default":void 0)));let u=f(null==o?t.length-1:o),c=r.Pop,h=null;function f(e){return Math.min(Math.max(e,0),t.length-1)}function p(){return t[u]}function m(e,r,a){void 0===r&&(r=null);let o=s(t?p().pathname:"/",e,r,a);return n("/"===o.pathname.charAt(0),"relative pathnames are not supported in memory history: "+JSON.stringify(e)),o}function y(e){return"string"==typeof e?e:l(e)}return{get index(){return u},get action(){return c},get location(){return p()},createHref:y,createURL:e=>new URL(y(e),"http://localhost"),encodeLocation(e){let t="string"==typeof e?d(e):e;return{pathname:t.pathname||"",search:t.search||"",hash:t.hash||""}},push(e,a){c=r.Push;let o=m(e,a);u+=1,t.splice(u,t.length,o),i&&h&&h({action:c,location:o,delta:1})},replace(e,a){c=r.Replace;let o=m(e,a);t[u]=o,i&&h&&h({action:c,location:o,delta:0})},go(e){c=r.Pop;let a=f(u+e),o=t[a];u=a,h&&h({action:c,location:o,delta:e})},listen:e=>(h=e,()=>{h=null})}},e.createPath=l,e.createRouter=function(e){const a=e.window?e.window:"undefined"!=typeof window?window:void 0,i=void 0!==a&&void 0!==a.document&&void 0!==a.document.createElement,l=!i;let d;if(o(e.routes.length>0,"You must provide a non-empty routes array to createRouter"),e.mapRouteProperties)d=e.mapRouteProperties;else if(e.detectErrorBoundary){let t=e.detectErrorBoundary;d=e=>({hasErrorBoundary:t(e)})}else d=G;let u,h,y={},v=f(e.routes,d,void 0,y),g=e.basename||"/",b=e.unstable_dataStrategy||le,w=t({v7_fetcherPersist:!1,v7_normalizeFormMethod:!1,v7_partialHydration:!1,v7_prependBasename:!1,v7_relativeSplatPath:!1,unstable_skipActionErrorRevalidation:!0},e.future),D=null,S=new Set,E=null,P=null,x=null,L=null!=e.hydrationData,A=p(v,e.history.location,g),M=null;if(null==A){let t=De(404,{pathname:e.history.location.pathname}),{matches:r,route:a}=we(v);A=r,M={[a.id]:t}}let j,_=A.some((e=>e.route.lazy)),k=A.some((e=>e.route.loader));if(_)h=!1;else if(k)if(w.v7_partialHydration){let t=e.hydrationData?e.hydrationData.loaderData:null,r=e.hydrationData?e.hydrationData.errors:null;h=A.every((e=>e.route.loader&&("function"!=typeof e.route.loader||!0!==e.route.loader.hydrate)&&(t&&void 0!==t[e.route.id]||r&&void 0!==r[e.route.id])))}else h=null!=e.hydrationData;else h=!0;let C,T={historyAction:e.history.action,location:e.history.location,matches:A,initialized:h,navigation:Y,restoreScrollPosition:null==e.hydrationData&&null,preventScrollReset:!1,revalidation:"idle",loaderData:e.hydrationData&&e.hydrationData.loaderData||{},actionData:e.hydrationData&&e.hydrationData.actionData||null,errors:e.hydrationData&&e.hydrationData.errors||M,fetchers:new Map,blockers:new Map},U=r.Pop,O=!1,H=!1,I=new Map,z=null,F=!1,B=!1,N=[],W=[],$=new Map,q=0,Z=-1,ee=new Map,ae=new Set,ne=new Map,ie=new Map,se=new Set,fe=new Map,pe=new Map,me=!1;function Ee(e,r){void 0===r&&(r={}),T=t({},T,e);let a=[],o=[];w.v7_fetcherPersist&&T.fetchers.forEach(((e,t)=>{"idle"===e.state&&(se.has(t)?o.push(t):a.push(t))})),[...S].forEach((e=>e(T,{deletedFetchers:o,unstable_viewTransitionOpts:r.viewTransitionOpts,unstable_flushSync:!0===r.flushSync}))),w.v7_fetcherPersist&&(a.forEach((e=>T.fetchers.delete(e))),o.forEach((e=>Ke(e))))}function Ae(a,o,n){var i,s;let l,{flushSync:d}=void 0===n?{}:n,c=null!=T.actionData&&null!=T.navigation.formMethod&&_e(T.navigation.formMethod)&&"loading"===T.navigation.state&&!0!==(null==(i=a.state)?void 0:i._isRedirect);l=o.actionData?Object.keys(o.actionData).length>0?o.actionData:null:c?T.actionData:null;let h=o.loaderData?ve(T.loaderData,o.loaderData,o.matches||[],o.errors):T.loaderData,f=T.blockers;f.size>0&&(f=new Map(f),f.forEach(((e,t)=>f.set(t,V))));let p,m=!0===O||null!=T.navigation.formMethod&&_e(T.navigation.formMethod)&&!0!==(null==(s=a.state)?void 0:s._isRedirect);if(u&&(v=u,u=void 0),F||U===r.Pop||(U===r.Push?e.history.push(a,a.state):U===r.Replace&&e.history.replace(a,a.state)),U===r.Pop){let e=I.get(T.location.pathname);e&&e.has(a.pathname)?p={currentLocation:T.location,nextLocation:a}:I.has(a.pathname)&&(p={currentLocation:a,nextLocation:T.location})}else if(H){let e=I.get(T.location.pathname);e?e.add(a.pathname):(e=new Set([a.pathname]),I.set(T.location.pathname,e)),p={currentLocation:T.location,nextLocation:a}}Ee(t({},o,{actionData:l,loaderData:h,historyAction:U,location:a,initialized:!0,navigation:Y,revalidation:"idle",restoreScrollPosition:rt(a,o.matches||T.matches),preventScrollReset:m,blockers:f}),{viewTransitionOpts:p,flushSync:!0===d}),U=r.Pop,O=!1,H=!1,F=!1,B=!1,N=[],W=[]}async function Me(a,o,n){C&&C.abort(),C=null,U=a,F=!0===(n&&n.startUninterruptedRevalidation),function(e,t){if(E&&x){let r=tt(e,t);E[r]=x()}}(T.location,T.matches),O=!0===(n&&n.preventScrollReset),H=!0===(n&&n.enableViewTransition);let i=u||v,s=n&&n.overrideNavigation,l=p(i,o,g),d=!0===(n&&n.flushSync);if(!l){let e=De(404,{pathname:o.pathname}),{matches:t,route:r}=we(i);return et(),void Ae(o,{matches:t,loaderData:{},errors:{[r.id]:e}},{flushSync:d})}if(T.initialized&&!B&&function(e,t){if(e.pathname!==t.pathname||e.search!==t.search)return!1;if(""===e.hash)return""!==t.hash;if(e.hash===t.hash)return!0;if(""!==t.hash)return!0;return!1}(T.location,o)&&!(n&&n.submission&&_e(n.submission.formMethod)))return void Ae(o,{matches:l},{flushSync:d});C=new AbortController;let h,f=he(e.history,o,C.signal,n&&n.submission);if(n&&n.pendingError)h=[be(l).route.id,{type:c.error,error:n.pendingError}];else if(n&&n.submission&&_e(n.submission.formMethod)){let t=await async function(e,t,a,o,n){void 0===n&&(n={});let i;Ne(),Ee({navigation:Ie(t,a)},{flushSync:!0===n.flushSync});let s=Ue(o,t);if(s.route.action||s.route.lazy){if(i=(await Te("action",e,[s],o))[0],e.signal.aborted)return{shortCircuited:!0}}else i={type:c.error,error:De(405,{method:e.method,pathname:t.pathname,routeId:s.route.id})};if(Le(i)){let t;return t=n&&null!=n.replace?n.replace:i.response.headers.get("Location")===T.location.pathname+T.location.search,await je(e,i,{submission:a,replace:t}),{shortCircuited:!0}}if(Pe(i))throw De(400,{type:"defer-action"});if(xe(i)){let e=be(o,s.route.id);return!0!==(n&&n.replace)&&(U=r.Push),{pendingActionResult:[e.route.id,i]}}return{pendingActionResult:[s.route.id,i]}}(f,o,n.submission,l,{replace:n.replace,flushSync:d});if(t.shortCircuited)return;h=t.pendingActionResult,s=He(o,n.submission),d=!1,f=he(e.history,f.url,f.signal)}let{shortCircuited:m,loaderData:y,errors:b}=await async function(r,a,o,n,i,s,l,d,c,h){let f=n||He(a,i),p=i||s||Oe(f),m=u||v,[y,b]=oe(e.history,T,o,p,a,w.v7_partialHydration&&!0===d,w.unstable_skipActionErrorRevalidation,B,N,W,se,ne,ae,m,g,h);if(et((e=>!(o&&o.some((t=>t.route.id===e)))||y&&y.some((t=>t.route.id===e)))),Z=++q,0===y.length&&0===b.length){let e=Ve();return Ae(a,t({matches:o,loaderData:{},errors:h&&xe(h[1])?{[h[0]]:h[1].error}:null},ge(h),e?{fetchers:new Map(T.fetchers)}:{}),{flushSync:c}),{shortCircuited:!0}}if(!(F||w.v7_partialHydration&&d)){let e;b.forEach((e=>{let t=T.fetchers.get(e.key),r=ze(void 0,t?t.data:void 0);T.fetchers.set(e.key,r)})),h&&!xe(h[1])?e={[h[0]]:h[1].data}:T.actionData&&(e=0===Object.keys(T.actionData).length?null:T.actionData),Ee(t({navigation:f},void 0!==e?{actionData:e}:{},b.length>0?{fetchers:new Map(T.fetchers)}:{}),{flushSync:c})}b.forEach((e=>{$.has(e.key)&&Ye(e.key),e.controller&&$.set(e.key,e.controller)}));let D=()=>b.forEach((e=>Ye(e.key)));C&&C.signal.addEventListener("abort",D);let{loaderResults:S,fetcherResults:E}=await Be(T.matches,o,y,b,r);if(r.signal.aborted)return{shortCircuited:!0};C&&C.signal.removeEventListener("abort",D);b.forEach((e=>$.delete(e.key)));let R=Se([...S,...E]);if(R){if(R.idx>=y.length){let e=b[R.idx-y.length].key;ae.add(e)}return await je(r,R.result,{replace:l}),{shortCircuited:!0}}let{loaderData:P,errors:x}=ye(T,o,y,S,h,b,E,fe);fe.forEach(((e,t)=>{e.subscribe((r=>{(r||e.done)&&fe.delete(t)}))})),w.v7_partialHydration&&d&&T.errors&&Object.entries(T.errors).filter((e=>{let[t]=e;return!y.some((e=>e.route.id===t))})).forEach((e=>{let[t,r]=e;x=Object.assign(x||{},{[t]:r})}));let L=Ve(),A=Xe(Z),M=L||A||b.length>0;return t({loaderData:P,errors:x},M?{fetchers:new Map(T.fetchers)}:{})}(f,o,l,s,n&&n.submission,n&&n.fetcherSubmission,n&&n.replace,n&&!0===n.initialHydration,d,h);m||(C=null,Ae(o,t({matches:l},ge(h),{loaderData:y,errors:b})))}async function je(n,l,d){let{submission:u,fetcherSubmission:c,replace:h}=void 0===d?{}:d;l.response.headers.has("X-Remix-Revalidate")&&(B=!0);let f=l.response.headers.get("Location");o(f,"Expected a Location header on the redirect Response");let p=s(T.location,f,{_isRedirect:!0});if(X.test(f)){let e=f,t=new URL(n.url),r=e.startsWith("//")?new URL(t.protocol+e):new URL(e),a=null!=R(r.pathname,g);r.origin===t.origin&&a&&(e=r.pathname+r.search+r.hash,p=s(T.location,e,{_isRedirect:!0}))}if(i){let t=!1;if(l.response.headers.has("X-Remix-Reload-Document"))t=!0;else if(X.test(f)){const r=e.history.createURL(f);t=r.origin!==a.location.origin||null==R(r.pathname,g)}if(t)return void(h?a.location.replace(f):a.location.assign(f))}C=null;let m=!0===h?r.Replace:r.Push,{formMethod:y,formAction:v,formEncType:b}=T.navigation;!u&&!c&&y&&v&&b&&(u=Oe(T.navigation));let w=u||c;if(K.has(l.response.status)&&w&&_e(w.formMethod))await Me(m,p,{submission:t({},w,{formAction:f}),preventScrollReset:O});else{let e=He(p,u);await Me(m,p,{overrideNavigation:e,fetcherSubmission:c,preventScrollReset:O})}}async function Te(e,t,r,a){try{let o=await de(b,e,t,r,a,y,d);return await Promise.all(o.map(((e,o)=>Re(e)?{type:c.redirect,response:ce(e.result,t,r[o].route.id,a,g,w.v7_relativeSplatPath)}:ue(e))))}catch(e){return r.map((()=>({type:c.error,error:e})))}}async function Be(t,r,a,o,n){let[i,...s]=await Promise.all([a.length?Te("loader",n,a,r):[],...o.map((t=>{if(t.matches&&t.match&&t.controller){return Te("loader",he(e.history,t.path,t.controller.signal),[t.match],t.matches).then((e=>e[0]))}return Promise.resolve({type:c.error,error:De(404,{pathname:t.path})})}))]);return await Promise.all([ke(t,a,i,i.map((()=>n.signal)),!1,T.loaderData),ke(t,o.map((e=>e.match)),s,o.map((e=>e.controller?e.controller.signal:null)),!0)]),{loaderResults:i,fetcherResults:s}}function Ne(){B=!0,N.push(...et()),ne.forEach(((e,t)=>{$.has(t)&&(W.push(t),Ye(t))}))}function We(e,t,r){void 0===r&&(r={}),T.fetchers.set(e,t),Ee({fetchers:new Map(T.fetchers)},{flushSync:!0===(r&&r.flushSync)})}function $e(e,t,r,a){void 0===a&&(a={});let o=be(T.matches,t);Ke(e),Ee({errors:{[o.route.id]:r},fetchers:new Map(T.fetchers)},{flushSync:!0===(a&&a.flushSync)})}function qe(e){return w.v7_fetcherPersist&&(ie.set(e,(ie.get(e)||0)+1),se.has(e)&&se.delete(e)),T.fetchers.get(e)||J}function Ke(e){let t=T.fetchers.get(e);!$.has(e)||t&&"loading"===t.state&&ee.has(e)||Ye(e),ne.delete(e),ee.delete(e),ae.delete(e),se.delete(e),T.fetchers.delete(e)}function Ye(e){let t=$.get(e);o(t,"Expected fetch controller: "+e),t.abort(),$.delete(e)}function Je(e){for(let t of e){let e=Fe(qe(t).data);T.fetchers.set(t,e)}}function Ve(){let e=[],t=!1;for(let r of ae){let a=T.fetchers.get(r);o(a,"Expected fetcher: "+r),"loading"===a.state&&(ae.delete(r),e.push(r),t=!0)}return Je(e),t}function Xe(e){let t=[];for(let[r,a]of ee)if(a<e){let e=T.fetchers.get(r);o(e,"Expected fetcher: "+r),"loading"===e.state&&(Ye(r),ee.delete(r),t.push(r))}return Je(t),t.length>0}function Ge(e){T.blockers.delete(e),pe.delete(e)}function Qe(e,t){let r=T.blockers.get(e)||V;o("unblocked"===r.state&&"blocked"===t.state||"blocked"===r.state&&"blocked"===t.state||"blocked"===r.state&&"proceeding"===t.state||"blocked"===r.state&&"unblocked"===t.state||"proceeding"===r.state&&"unblocked"===t.state,"Invalid blocker state transition: "+r.state+" -> "+t.state);let a=new Map(T.blockers);a.set(e,t),Ee({blockers:a})}function Ze(e){let{currentLocation:t,nextLocation:r,historyAction:a}=e;if(0===pe.size)return;pe.size>1&&n(!1,"A router only supports one blocker at a time");let o=Array.from(pe.entries()),[i,s]=o[o.length-1],l=T.blockers.get(i);return l&&"proceeding"===l.state?void 0:s({currentLocation:t,nextLocation:r,historyAction:a})?i:void 0}function et(e){let t=[];return fe.forEach(((r,a)=>{e&&!e(a)||(r.cancel(),t.push(a),fe.delete(a))})),t}function tt(e,t){if(P){return P(e,t.map((e=>m(e,T.loaderData))))||e.key}return e.key}function rt(e,t){if(E){let r=tt(e,t),a=E[r];if("number"==typeof a)return a}return null}return j={get basename(){return g},get future(){return w},get state(){return T},get routes(){return v},get window(){return a},initialize:function(){if(D=e.history.listen((t=>{let{action:r,location:a,delta:o}=t;if(me)return void(me=!1);n(0===pe.size||null!=o,"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 i=Ze({currentLocation:T.location,nextLocation:a,historyAction:r});return i&&null!=o?(me=!0,e.history.go(-1*o),void Qe(i,{state:"blocked",location:a,proceed(){Qe(i,{state:"proceeding",proceed:void 0,reset:void 0,location:a}),e.history.go(o)},reset(){let e=new Map(T.blockers);e.set(i,V),Ee({blockers:e})}})):Me(r,a)})),i){!function(e,t){try{let r=e.sessionStorage.getItem(Q);if(r){let e=JSON.parse(r);for(let[r,a]of Object.entries(e||{}))a&&Array.isArray(a)&&t.set(r,new Set(a||[]))}}catch(e){}}(a,I);let e=()=>function(e,t){if(t.size>0){let r={};for(let[e,a]of t)r[e]=[...a];try{e.sessionStorage.setItem(Q,JSON.stringify(r))}catch(e){n(!1,"Failed to save applied view transitions in sessionStorage ("+e+").")}}}(a,I);a.addEventListener("pagehide",e),z=()=>a.removeEventListener("pagehide",e)}return T.initialized||Me(r.Pop,T.location,{initialHydration:!0}),j},subscribe:function(e){return S.add(e),()=>S.delete(e)},enableScrollRestoration:function(e,t,r){if(E=e,x=t,P=r||null,!L&&T.navigation===Y){L=!0;let e=rt(T.location,T.matches);null!=e&&Ee({restoreScrollPosition:e})}return()=>{E=null,x=null,P=null}},navigate:async function a(o,n){if("number"==typeof o)return void e.history.go(o);let i=te(T.location,T.matches,g,w.v7_prependBasename,o,w.v7_relativeSplatPath,null==n?void 0:n.fromRouteId,null==n?void 0:n.relative),{path:l,submission:d,error:u}=re(w.v7_normalizeFormMethod,!1,i,n),c=T.location,h=s(T.location,l,n&&n.state);h=t({},h,e.history.encodeLocation(h));let f=n&&null!=n.replace?n.replace:void 0,p=r.Push;!0===f?p=r.Replace:!1===f||null!=d&&_e(d.formMethod)&&d.formAction===T.location.pathname+T.location.search&&(p=r.Replace);let m=n&&"preventScrollReset"in n?!0===n.preventScrollReset:void 0,y=!0===(n&&n.unstable_flushSync),v=Ze({currentLocation:c,nextLocation:h,historyAction:p});if(!v)return await Me(p,h,{submission:d,pendingError:u,preventScrollReset:m,replace:n&&n.replace,enableViewTransition:n&&n.unstable_viewTransition,flushSync:y});Qe(v,{state:"blocked",location:h,proceed(){Qe(v,{state:"proceeding",proceed:void 0,reset:void 0,location:h}),a(o,n)},reset(){let e=new Map(T.blockers);e.set(v,V),Ee({blockers:e})}})},fetch:function(t,r,a,n){if(l)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.");$.has(t)&&Ye(t);let i=!0===(n&&n.unstable_flushSync),s=u||v,d=te(T.location,T.matches,g,w.v7_prependBasename,a,w.v7_relativeSplatPath,r,null==n?void 0:n.relative),c=p(s,d,g);if(!c)return void $e(t,r,De(404,{pathname:d}),{flushSync:i});let{path:h,submission:f,error:m}=re(w.v7_normalizeFormMethod,!0,d,n);if(m)return void $e(t,r,m,{flushSync:i});let y=Ue(c,h);O=!0===(n&&n.preventScrollReset),f&&_e(f.formMethod)?async function(t,r,a,n,i,s,l){if(Ne(),ne.delete(t),!n.route.action&&!n.route.lazy){let e=De(405,{method:l.formMethod,pathname:a,routeId:r});return void $e(t,r,e,{flushSync:s})}let d=T.fetchers.get(t);We(t,function(e,t){return{state:"submitting",formMethod:e.formMethod,formAction:e.formAction,formEncType:e.formEncType,formData:e.formData,json:e.json,text:e.text,data:t?t.data:void 0}}(l,d),{flushSync:s});let c=new AbortController,h=he(e.history,a,c.signal,l);$.set(t,c);let f=q,m=(await Te("action",h,[n],i))[0];if(h.signal.aborted)return void($.get(t)===c&&$.delete(t));if(w.v7_fetcherPersist&&se.has(t)){if(Le(m)||xe(m))return void We(t,Fe(void 0))}else{if(Le(m))return $.delete(t),Z>f?void We(t,Fe(void 0)):(ae.add(t),We(t,ze(l)),je(h,m,{fetcherSubmission:l}));if(xe(m))return void $e(t,r,m.error)}if(Pe(m))throw De(400,{type:"defer-action"});let y=T.navigation.location||T.location,b=he(e.history,y,c.signal),D=u||v,S="idle"!==T.navigation.state?p(D,T.navigation.location,g):T.matches;o(S,"Didn't find any matches after fetcher action");let E=++q;ee.set(t,E);let R=ze(l,m.data);T.fetchers.set(t,R);let[P,x]=oe(e.history,T,S,l,y,!1,w.unstable_skipActionErrorRevalidation,B,N,W,se,ne,ae,D,g,[n.route.id,m]);x.filter((e=>e.key!==t)).forEach((e=>{let t=e.key,r=T.fetchers.get(t),a=ze(void 0,r?r.data:void 0);T.fetchers.set(t,a),$.has(t)&&Ye(t),e.controller&&$.set(t,e.controller)})),Ee({fetchers:new Map(T.fetchers)});let L=()=>x.forEach((e=>Ye(e.key)));c.signal.addEventListener("abort",L);let{loaderResults:A,fetcherResults:M}=await Be(T.matches,S,P,x,b);if(c.signal.aborted)return;c.signal.removeEventListener("abort",L),ee.delete(t),$.delete(t),x.forEach((e=>$.delete(e.key)));let j=Se([...A,...M]);if(j){if(j.idx>=P.length){let e=x[j.idx-P.length].key;ae.add(e)}return je(b,j.result)}let{loaderData:_,errors:k}=ye(T,T.matches,P,A,void 0,x,M,fe);if(T.fetchers.has(t)){let e=Fe(m.data);T.fetchers.set(t,e)}Xe(E),"loading"===T.navigation.state&&E>Z?(o(U,"Expected pending action"),C&&C.abort(),Ae(T.navigation.location,{matches:S,loaderData:_,errors:k,fetchers:new Map(T.fetchers)})):(Ee({errors:k,loaderData:ve(T.loaderData,_,S,k),fetchers:new Map(T.fetchers)}),B=!1)}(t,r,h,y,c,i,f):(ne.set(t,{routeId:r,path:h}),async function(t,r,a,n,i,s,l){let d=T.fetchers.get(t);We(t,ze(l,d?d.data:void 0),{flushSync:s});let u=new AbortController,c=he(e.history,a,u.signal);$.set(t,u);let h=q,f=(await Te("loader",c,[n],i))[0];Pe(f)&&(f=await Ce(f,c.signal,!0)||f);$.get(t)===u&&$.delete(t);if(c.signal.aborted)return;if(se.has(t))return void We(t,Fe(void 0));if(Le(f))return Z>h?void We(t,Fe(void 0)):(ae.add(t),void await je(c,f));if(xe(f))return void $e(t,r,f.error);o(!Pe(f),"Unhandled fetcher deferred data"),We(t,Fe(f.data))}(t,r,h,y,c,i,f))},revalidate:function(){Ne(),Ee({revalidation:"loading"}),"submitting"!==T.navigation.state&&("idle"!==T.navigation.state?Me(U||T.historyAction,T.navigation.location,{overrideNavigation:T.navigation}):Me(T.historyAction,T.location,{startUninterruptedRevalidation:!0}))},createHref:t=>e.history.createHref(t),encodeLocation:t=>e.history.encodeLocation(t),getFetcher:qe,deleteFetcher:function(e){if(w.v7_fetcherPersist){let t=(ie.get(e)||0)-1;t<=0?(ie.delete(e),se.add(e)):ie.set(e,t)}else Ke(e);Ee({fetchers:new Map(T.fetchers)})},dispose:function(){D&&D(),z&&z(),S.clear(),C&&C.abort(),T.fetchers.forEach(((e,t)=>Ke(t))),T.blockers.forEach(((e,t)=>Ge(t)))},getBlocker:function(e,t){let r=T.blockers.get(e)||V;return pe.get(e)!==t&&pe.set(e,t),r},deleteBlocker:Ge,_internalFetchControllers:$,_internalActiveDeferreds:fe,_internalSetRoutes:function(e){y={},u=f(e,d,void 0,y)}},j},e.createStaticHandler=function(e,r){o(e.length>0,"You must provide a non-empty routes array to createStaticHandler");let a,n={},i=(r?r.basename:null)||"/",d=(null==r?void 0:r.unstable_dataStrategy)||le;if(null!=r&&r.mapRouteProperties)a=r.mapRouteProperties;else if(null!=r&&r.detectErrorBoundary){let e=r.detectErrorBoundary;a=t=>({hasErrorBoundary:e(t)})}else a=G;let u=t({v7_relativeSplatPath:!1,v7_throwAbortReason:!1},r?r.future:null),h=f(e,a,void 0,n);async function m(e,r,a,n,i,s){o(e.signal,"query()/queryRoute() requests must contain an AbortController signal");try{if(_e(e.method.toLowerCase())){let o=await async function(e,r,a,o,n,i){let s;if(a.route.action||a.route.lazy){s=(await v("action",e,[a],r,i,o))[0],e.signal.aborted&&ee(e,i,u)}else{let t=De(405,{method:e.method,pathname:new URL(e.url).pathname,routeId:a.route.id});if(i)throw t;s={type:c.error,error:t}}if(Le(s))throw new Response(null,{status:s.response.status,headers:{Location:s.response.headers.get("Location")}});if(Pe(s)){let e=De(400,{type:"defer-action"});if(i)throw e;s={type:c.error,error:e}}if(i){if(xe(s))throw s.error;return{matches:[a],loaderData:{},actionData:{[a.route.id]:s.data},errors:null,statusCode:200,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}let l=new Request(e.url,{headers:e.headers,redirect:e.redirect,signal:e.signal});if(xe(s)){let e=be(r,a.route.id);return t({},await y(l,r,o,n,null,[e.route.id,s]),{statusCode:z(s.error)?s.error.status:500,actionData:null,actionHeaders:t({},s.headers?{[a.route.id]:s.headers}:{})})}return t({},await y(l,r,o,n,null),{actionData:{[a.route.id]:s.data}},s.statusCode?{statusCode:s.statusCode}:{},{actionHeaders:s.headers?{[a.route.id]:s.headers}:{}})}(e,a,s||Ue(a,r),n,i,null!=s);return o}let o=await y(e,a,n,i,s);return Me(o)?o:t({},o,{actionData:null,actionHeaders:{}})}catch(e){if(function(e){return null!=e&&"object"==typeof e&&"type"in e&&"result"in e&&(e.type===c.data||e.type===c.error)}(e)&&Me(e.result)){if(e.type===c.error)throw e.result;return e.result}if(function(e){if(!Me(e))return!1;let t=e.status,r=e.headers.get("Location");return t>=300&&t<=399&&null!=r}(e))return e;throw e}}async function y(e,r,a,o,n,i){let s=null!=n;if(s&&(null==n||!n.route.loader)&&(null==n||!n.route.lazy))throw De(400,{method:e.method,pathname:new URL(e.url).pathname,routeId:null==n?void 0:n.route.id});let l=(n?[n]:i&&xe(i[1])?ae(r,i[0]):r).filter((e=>e.route.loader||e.route.lazy));if(o&&(l=l.filter((e=>o.includes(e.route.id)))),0===l.length)return{matches:r,loaderData:r.reduce(((e,t)=>Object.assign(e,{[t.route.id]:null})),{}),errors:i&&xe(i[1])?{[i[0]]:i[1].error}:null,statusCode:200,loaderHeaders:{},activeDeferreds:null};let d=await v("loader",e,l,r,s,a);e.signal.aborted&&ee(e,s,u);let c=new Map,h=me(r,l,d,i,c),f=new Set(l.map((e=>e.route.id)));return r.forEach((e=>{f.has(e.route.id)||(h.loaderData[e.route.id]=null)})),t({},h,{matches:r,activeDeferreds:c.size>0?Object.fromEntries(c.entries()):null})}async function v(e,t,r,o,s,l){let c=await de(d,e,t,r,o,n,a,l);return await Promise.all(c.map(((e,a)=>{if(Re(e))throw ce(e.result,t,r[a].route.id,o,i,u.v7_relativeSplatPath);if(Me(e.result)&&s)throw e;return ue(e)})))}return{dataRoutes:h,query:async function(e,r){let{loadRouteIds:a,requestContext:o}=void 0===r?{}:r,n=new URL(e.url),d=e.method,u=s("",l(n),null,"default"),c=p(h,u,i);if(!je(d)&&"HEAD"!==d){let e=De(405,{method:d}),{matches:t,route:r}=we(h);return{basename:i,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(!c){let e=De(404,{pathname:u.pathname}),{matches:t,route:r}=we(h);return{basename:i,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}let f=await m(e,u,c,o,a||null,null);return Me(f)?f:t({location:u,basename:i},f)},queryRoute:async function(e,t){let{routeId:r,requestContext:a}=void 0===t?{}:t,o=new URL(e.url),n=e.method,d=s("",l(o),null,"default"),u=p(h,d,i);if(!je(n)&&"HEAD"!==n&&"OPTIONS"!==n)throw De(405,{method:n});if(!u)throw De(404,{pathname:d.pathname});let c=r?u.find((e=>e.route.id===r)):Ue(u,d);if(r&&!c)throw De(403,{pathname:d.pathname,routeId:r});if(!c)throw De(404,{pathname:d.pathname});let f=await m(e,d,u,a,null,c);if(Me(f))return f;let y=f.errors?Object.values(f.errors)[0]:void 0;if(void 0!==y)throw y;if(f.actionData)return Object.values(f.actionData)[0];if(f.loaderData){var v;let e=Object.values(f.loaderData)[0];return null!=(v=f.activeDeferreds)&&v[c.route.id]&&(e[Z]=f.activeDeferreds[c.route.id]),e}}}},e.defer=function(e,t){return void 0===t&&(t={}),new U(e,"number"==typeof t?{status:t}:t)},e.generatePath=function(e,t){void 0===t&&(t={});let r=e;r.endsWith("*")&&"*"!==r&&!r.endsWith("/*")&&(n(!1,'Route path "'+r+'" will be treated as if it were "'+r.replace(/\*$/,"/*")+'" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "'+r.replace(/\*$/,"/*")+'".'),r=r.replace(/\*$/,"/*"));const a=r.startsWith("/")?"/":"",i=e=>null==e?"":"string"==typeof e?e:String(e);return a+r.split(/\/+/).map(((e,r,a)=>{if(r===a.length-1&&"*"===e){return i(t["*"])}const n=e.match(/^:([\w-]+)(\??)$/);if(n){const[,e,r]=n;let a=t[e];return o("?"===r||null!=a,'Missing ":'+e+'" param'),i(a)}return e.replace(/\?$/g,"")})).filter((e=>!!e)).join("/")},e.getStaticContextFromError=function(e,r,a){return t({},r,{statusCode:z(a)?a.status:500,errors:{[r._deepestRenderedBoundaryId||e[0].id]:a}})},e.getToPathname=function(e){return""===e||""===e.pathname?"/":"string"==typeof e?d(e).pathname:e.pathname},e.isDeferredData=Ae,e.isRouteErrorResponse=z,e.joinPaths=j,e.json=function(e,r){void 0===r&&(r={});let a="number"==typeof r?{status:r}:r,o=new Headers(a.headers);return o.has("Content-Type")||o.set("Content-Type","application/json; charset=utf-8"),new Response(JSON.stringify(e),t({},a,{headers:o}))},e.matchPath=S,e.matchRoutes=p,e.normalizePathname=_,e.parsePath=d,e.redirect=H,e.redirectDocument=(e,t)=>{let r=H(e,t);return r.headers.set("X-Remix-Reload-Document","true"),r},e.resolvePath=P,e.resolveTo=M,e.stripBasename=R,e.unstable_DecodedResponse=class{constructor(e,t,r,a){this._isDecodedResponse=!0,this.status=e,this.statusText=t,this.headers=r,this.data=a}},e.unstable_isDecodedResponse=F,Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=router.umd.min.js.map

@@ -19,3 +19,3 @@ import type { Location, Path, To } from "./history";

type: ResultType.data;
data: any;
data: unknown;
statusCode?: number;

@@ -38,5 +38,3 @@ headers?: Headers;

type: ResultType.redirect;
status: number;
location: string;
revalidate: boolean;
response: Response;
}

@@ -48,3 +46,4 @@ /**

type: ResultType.error;
error: any;
error: unknown;
statusCode?: number;
headers?: Headers;

@@ -55,16 +54,23 @@ }

*/
export declare type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
declare type LowerCaseFormMethod = "get" | "post" | "put" | "patch" | "delete";
declare type UpperCaseFormMethod = Uppercase<LowerCaseFormMethod>;
export type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
/**
* Users can specify either lowercase or uppercase form methods on <Form>,
* useSubmit(), <fetcher.Form>, etc.
* Result from a loader or action called via dataStrategy
*/
export declare type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;
export interface HandlerResult {
type: ResultType.data | ResultType.error;
result: any;
}
type LowerCaseFormMethod = "get" | "post" | "put" | "patch" | "delete";
type UpperCaseFormMethod = Uppercase<LowerCaseFormMethod>;
/**
* Users can specify either lowercase or uppercase form methods on `<Form>`,
* useSubmit(), `<fetcher.Form>`, etc.
*/
export type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;
/**
* Active navigation/fetcher form methods are exposed in lowercase on the
* RouterState
*/
export declare type FormMethod = LowerCaseFormMethod;
export declare type MutationFormMethod = Exclude<FormMethod, "get">;
export type FormMethod = LowerCaseFormMethod;
export type MutationFormMethod = Exclude<FormMethod, "get">;
/**

@@ -74,5 +80,13 @@ * In v7, active navigation/fetcher form methods are exposed in uppercase on the

*/
export declare type V7_FormMethod = UpperCaseFormMethod;
export declare type V7_MutationFormMethod = Exclude<V7_FormMethod, "GET">;
export declare type FormEncType = "application/x-www-form-urlencoded" | "multipart/form-data";
export type V7_FormMethod = UpperCaseFormMethod;
export type V7_MutationFormMethod = Exclude<V7_FormMethod, "GET">;
export type FormEncType = "application/x-www-form-urlencoded" | "multipart/form-data" | "application/json" | "text/plain";
type JsonObject = {
[Key in string]: JsonValue;
} & {
[Key in string]?: JsonValue | undefined;
};
type JsonArray = JsonValue[] | readonly JsonValue[];
type JsonPrimitive = string | number | boolean | null;
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
/**

@@ -83,3 +97,3 @@ * @private

*/
export interface Submission {
export type Submission = {
formMethod: FormMethod | V7_FormMethod;

@@ -89,3 +103,19 @@ formAction: string;

formData: FormData;
}
json: undefined;
text: undefined;
} | {
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: undefined;
json: JsonValue;
text: undefined;
} | {
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: undefined;
json: undefined;
text: string;
};
/**

@@ -96,6 +126,6 @@ * @private

*/
interface DataFunctionArgs {
interface DataFunctionArgs<Context> {
request: Request;
params: Params;
context?: any;
context?: Context;
}

@@ -105,3 +135,3 @@ /**

*/
export interface LoaderFunctionArgs extends DataFunctionArgs {
export interface LoaderFunctionArgs<Context = any> extends DataFunctionArgs<Context> {
}

@@ -111,17 +141,43 @@ /**

*/
export interface ActionFunctionArgs extends DataFunctionArgs {
export interface ActionFunctionArgs<Context = any> extends DataFunctionArgs<Context> {
}
/**
* Loaders and actions can return anything except `undefined` (`null` is a
* valid return value if there is no data to return). Responses are preferred
* and will ease any future migration to Remix
*/
type DataFunctionValue = Response | NonNullable<unknown> | null;
type DataFunctionReturnValue = Promise<DataFunctionValue> | DataFunctionValue;
/**
* Route loader function signature
*/
export interface LoaderFunction {
(args: LoaderFunctionArgs): Promise<Response> | Response | Promise<any> | any;
}
export type LoaderFunction<Context = any> = {
(args: LoaderFunctionArgs<Context>, handlerCtx?: unknown): DataFunctionReturnValue;
} & {
hydrate?: boolean;
};
/**
* Route action function signature
*/
export interface ActionFunction {
(args: ActionFunctionArgs): Promise<Response> | Response | Promise<any> | any;
export interface ActionFunction<Context = any> {
(args: ActionFunctionArgs<Context>, handlerCtx?: unknown): DataFunctionReturnValue;
}
/**
* Arguments passed to shouldRevalidate function
*/
export interface ShouldRevalidateFunctionArgs {
currentUrl: URL;
currentParams: AgnosticDataRouteMatch["params"];
nextUrl: URL;
nextParams: AgnosticDataRouteMatch["params"];
formMethod?: Submission["formMethod"];
formAction?: Submission["formAction"];
formEncType?: Submission["formEncType"];
text?: Submission["text"];
formData?: Submission["formData"];
json?: Submission["json"];
actionResult?: any;
defaultShouldRevalidate: boolean;
}
/**
* Route shouldRevalidate function signature. This runs after any submission

@@ -134,14 +190,3 @@ * (navigation or fetcher), so we flatten the navigation/fetcher submission

export interface ShouldRevalidateFunction {
(args: {
currentUrl: URL;
currentParams: AgnosticDataRouteMatch["params"];
nextUrl: URL;
nextParams: AgnosticDataRouteMatch["params"];
formMethod?: Submission["formMethod"];
formAction?: Submission["formAction"];
formEncType?: Submission["formEncType"];
formData?: Submission["formData"];
actionResult?: DataResult;
defaultShouldRevalidate: boolean;
}): boolean;
(args: ShouldRevalidateFunctionArgs): boolean;
}

@@ -151,2 +196,4 @@ /**

* from the framework-aware `errorElement` prop
*
* @deprecated Use `mapRouteProperties` instead
*/

@@ -156,3 +203,22 @@ export interface DetectErrorBoundaryFunction {

}
export interface DataStrategyMatch extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
shouldLoad: boolean;
resolve: (handlerOverride?: (handler: (ctx?: unknown) => DataFunctionReturnValue) => DataFunctionReturnValue) => Promise<HandlerResult>;
}
export interface DataStrategyFunctionArgs<Context = any> extends DataFunctionArgs<Context> {
matches: DataStrategyMatch[];
}
export interface DataStrategyFunction {
(args: DataStrategyFunctionArgs): Promise<HandlerResult[]>;
}
/**
* Function provided by the framework-aware layers to set any framework-specific
* properties from framework-agnostic properties
*/
export interface MapRoutePropertiesFunction {
(route: AgnosticRouteObject): {
hasErrorBoundary: boolean;
} & Record<string, any>;
}
/**
* Keys we cannot change from within a lazy() function. We spread all other keys

@@ -162,4 +228,7 @@ * onto the route. Either they're meaningful to the router, or they'll get

*/
export declare type ImmutableRouteKey = "lazy" | "caseSensitive" | "path" | "id" | "index" | "children";
export type ImmutableRouteKey = "lazy" | "caseSensitive" | "path" | "id" | "index" | "children";
export declare const immutableRouteKeys: Set<ImmutableRouteKey>;
type RequireOne<T, Key = keyof T> = Exclude<{
[K in keyof T]: K extends Key ? Omit<T, K> & Required<Pick<T, K>> : never;
}[keyof T], undefined>;
/**

@@ -170,3 +239,3 @@ * lazy() function to load a route definition, which can add non-matching

export interface LazyRouteFunction<R extends AgnosticRouteObject> {
(): Promise<Omit<R, ImmutableRouteKey>>;
(): Promise<RequireOne<Omit<R, ImmutableRouteKey>>>;
}

@@ -176,8 +245,8 @@ /**

*/
declare type AgnosticBaseRouteObject = {
type AgnosticBaseRouteObject = {
caseSensitive?: boolean;
path?: string;
id?: string;
loader?: LoaderFunction;
action?: ActionFunction;
loader?: LoaderFunction | boolean;
action?: ActionFunction | boolean;
hasErrorBoundary?: boolean;

@@ -191,3 +260,3 @@ shouldRevalidate?: ShouldRevalidateFunction;

*/
export declare type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {
export type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {
children?: undefined;

@@ -199,3 +268,3 @@ index: true;

*/
export declare type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {
export type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {
children?: AgnosticRouteObject[];

@@ -208,7 +277,7 @@ index?: false;

*/
export declare type AgnosticRouteObject = AgnosticIndexRouteObject | AgnosticNonIndexRouteObject;
export declare type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {
export type AgnosticRouteObject = AgnosticIndexRouteObject | AgnosticNonIndexRouteObject;
export type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {
id: string;
};
export declare type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {
export type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {
children?: AgnosticDataRouteObject[];

@@ -220,5 +289,5 @@ id: string;

*/
export declare type AgnosticDataRouteObject = AgnosticDataIndexRouteObject | AgnosticDataNonIndexRouteObject;
export declare type RouteManifest = Record<string, AgnosticDataRouteObject | undefined>;
declare type _PathParam<Path extends string> = Path extends `${infer L}/${infer R}` ? _PathParam<L> | _PathParam<R> : Path extends `:${infer Param}` ? Param extends `${infer Optional}?` ? Optional : Param : never;
export type AgnosticDataRouteObject = AgnosticDataIndexRouteObject | AgnosticDataNonIndexRouteObject;
export type RouteManifest = Record<string, AgnosticDataRouteObject | undefined>;
type _PathParam<Path extends string> = Path extends `${infer L}/${infer R}` ? _PathParam<L> | _PathParam<R> : Path extends `:${infer Param}` ? Param extends `${infer Optional}?` ? Optional : Param : never;
/**

@@ -233,4 +302,4 @@ * Examples:

*/
declare type PathParam<Path extends string> = Path extends "*" | "/*" ? "*" : Path extends `${infer Rest}/*` ? "*" | _PathParam<Rest> : _PathParam<Path>;
export declare type ParamParseKey<Segment extends string> = [
export type PathParam<Path extends string> = Path extends "*" | "/*" ? "*" : Path extends `${infer Rest}/*` ? "*" | _PathParam<Rest> : _PathParam<Path>;
export type ParamParseKey<Segment extends string> = [
PathParam<Segment>

@@ -241,3 +310,3 @@ ] extends [never] ? string : PathParam<Segment>;

*/
export declare type Params<Key extends string = string> = {
export type Params<Key extends string = string> = {
readonly [key in Key]: string | undefined;

@@ -268,3 +337,3 @@ };

}
export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], detectErrorBoundary: DetectErrorBoundaryFunction, parentPath?: number[], manifest?: RouteManifest): AgnosticDataRouteObject[];
export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], mapRouteProperties: MapRoutePropertiesFunction, parentPath?: number[], manifest?: RouteManifest): AgnosticDataRouteObject[];
/**

@@ -276,2 +345,10 @@ * Matches the given routes to a location and returns the match data.

export declare function matchRoutes<RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject>(routes: RouteObjectType[], locationArg: Partial<Location> | string, basename?: string): AgnosticRouteMatch<string, RouteObjectType>[] | null;
export interface UIMatch<Data = unknown, Handle = unknown> {
id: string;
pathname: string;
params: AgnosticRouteMatch["params"];
data: Data;
handle: Handle;
}
export declare function convertRouteMatchToUiMatch(match: AgnosticDataRouteMatch, loaderData: RouteData): UIMatch;
/**

@@ -367,2 +444,3 @@ * Returns a path with params interpolated.

export declare function getPathContributingMatches<T extends AgnosticRouteMatch = AgnosticRouteMatch>(matches: T[]): T[];
export declare function getResolveToMatches<T extends AgnosticRouteMatch = AgnosticRouteMatch>(matches: T[], v7_relativeSplatPath: boolean): string[];
/**

@@ -392,3 +470,3 @@ * @private

export declare const normalizeHash: (hash: string) => string;
export declare type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response;
export type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response;
/**

@@ -426,5 +504,5 @@ * This is a shortcut for creating `application/json` responses. Converts `data`

}
export declare type DeferFunction = (data: Record<string, unknown>, init?: number | ResponseInit) => DeferredData;
export type DeferFunction = (data: Record<string, unknown>, init?: number | ResponseInit) => DeferredData;
export declare const defer: DeferFunction;
export declare type RedirectFunction = (url: string, init?: number | ResponseInit) => Response;
export type RedirectFunction = (url: string, init?: number | ResponseInit) => Response;
/**

@@ -436,14 +514,43 @@ * A redirect response. Sets the status code and the `Location` header.

/**
* 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".
*/
export declare const redirectDocument: RedirectFunction;
export type ErrorResponse = {
status: number;
statusText: string;
data: any;
};
/**
* @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()
*/
export declare class ErrorResponse {
export declare class ErrorResponseImpl implements ErrorResponse {
status: number;
statusText: string;
data: any;
error?: Error;
internal: boolean;
private error?;
private internal;
constructor(status: number, statusText: string | undefined, data: any, internal?: boolean);
}
/**
* Utility class we use to hold unwrapped Responses while preserving status
* codes and headers. This is most useful for dataStrategy implementations
* where implementors want to use a custom decoding mechanism and return
* pre-decoded data while also preserving response meta information
*/
export declare class DecodedResponse {
status: number;
statusText: string;
headers: Headers;
data: unknown;
private _isDecodedResponse;
constructor(status: number, statusText: string, headers: Headers, data: unknown);
}
/**
* Check if the given error is an ErrorResponse generated from a 4xx/5xx

@@ -453,2 +560,6 @@ * Response thrown from an action/loader

export declare function isRouteErrorResponse(error: any): error is ErrorResponse;
/**
* Check if the given error is an DecodedResponse
*/
export declare function isDecodedResponse(value: any): value is DecodedResponse;
export {};

@@ -52,2 +52,5 @@ ////////////////////////////////////////////////////////////////////////////////

// TODO: (v7) Change the Location generic default from `any` to `unknown` and
// remove Remix `useLocation` wrapper.
/**

@@ -57,7 +60,7 @@ * An entry in a history stack. A location contains information about the

*/
export interface Location extends Path {
export interface Location<State = any> extends Path {
/**
* A value of arbitrary data associated with this location.
*/
state: any;
state: State;

@@ -102,4 +105,4 @@ /**

* Describes a location that is the destination of some navigation, either via
* `history.push` or `history.replace`. May be either a URL or the pieces of a
* URL path.
* `history.push` or `history.replace`. This may be either a URL or the pieces
* of a URL path.
*/

@@ -429,2 +432,13 @@ export type To = string | Partial<Path>;

} = 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(

@@ -496,3 +510,3 @@ "",

//
// This error is thrown as a convenience so you can more easily
// This error is thrown as a convenience, so you can more easily
// find the source for a warning that appears in the console by

@@ -642,2 +656,9 @@ // enabling "pause on exceptions" in your JavaScript debugger.

} 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

@@ -678,2 +699,6 @@ // way to warn them about it since the page will refresh...

let href = typeof to === "string" ? to : createPath(to);
// Treating this as a full URL will strip any trailing spaces so we need to
// pre-encode them since they might be part of a matching splat param from
// an ancestor route
href = href.replace(/ $/, "%20");
invariant(

@@ -680,0 +705,0 @@ base,

@@ -12,4 +12,6 @@ export type {

AgnosticRouteObject,
LazyRouteFunction,
TrackedPromise,
DataStrategyFunction,
DataStrategyFunctionArgs,
DataStrategyMatch,
ErrorResponse,
FormEncType,

@@ -19,2 +21,3 @@ FormMethod,

JsonFunction,
LazyRouteFunction,
LoaderFunction,

@@ -25,5 +28,9 @@ LoaderFunctionArgs,

PathMatch,
PathParam,
PathPattern,
RedirectFunction,
ShouldRevalidateFunction,
ShouldRevalidateFunctionArgs,
TrackedPromise,
UIMatch,
V7_FormMethod,

@@ -34,6 +41,7 @@ } from "./utils";

AbortedDeferredError,
ErrorResponse,
DecodedResponse as unstable_DecodedResponse,
defer,
generatePath,
getToPathname,
isDecodedResponse as unstable_isDecodedResponse,
isRouteErrorResponse,

@@ -46,2 +54,3 @@ joinPaths,

redirect,
redirectDocument,
resolvePath,

@@ -69,5 +78,5 @@ resolveTo,

createBrowserHistory,
createPath,
createHashHistory,
createMemoryHistory,
createPath,
parsePath,

@@ -89,4 +98,6 @@ } from "./history";

DeferredData as UNSAFE_DeferredData,
ErrorResponseImpl as UNSAFE_ErrorResponseImpl,
convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes,
getPathContributingMatches as UNSAFE_getPathContributingMatches,
convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch,
getResolveToMatches as UNSAFE_getResolveToMatches,
} from "./utils";

@@ -93,0 +104,0 @@

MIT License
Copyright (c) React Training 2015-2019
Copyright (c) Remix Software 2020-2022
Copyright (c) React Training LLC 2015-2019
Copyright (c) Remix Software Inc. 2020-2021
Copyright (c) Shopify Inc. 2022-2023

@@ -6,0 +7,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

{
"name": "@remix-run/router",
"version": "0.0.0-experimental-00c655af",
"version": "0.0.0-experimental-0141b5ec",
"description": "Nested/Data-driven/Framework-agnostic Routing",

@@ -28,3 +28,3 @@ "keywords": [

"engines": {
"node": ">=14"
"node": ">=14.0.0"
},

@@ -31,0 +31,0 @@ "publishConfig": {

@@ -5,5 +5,5 @@ # Remix Router

If you're using React Router, you should never `import` anything directly from the `@remix-run/router` or `react-router` packages, but you should have everything you need in either `react-router-dom` or `react-router-native`. Both of those packages re-export everything from `@remix-run/router` and `react-router`.
If you're using React Router, you should never `import` anything directly from the `@remix-run/router` - you should have everything you need in `react-router-dom` (or `react-router`/`react-router-native` if you're not rendering in the browser). All of those packages should re-export everything you would otherwise need from `@remix-run/router`.
> **Warning**
> [!WARNING]
>

@@ -20,7 +20,19 @@ > This router is a low-level package intended to be consumed by UI layer routing libraries. You should very likely not be using this package directly unless you are authoring a routing library such as [`react-router-dom`][react-router-repo] or one of it's other [UI ports][remix-routers-repo].

let router = createRouter({
// Routes array
routes: ,
// History instance
history,
}).initialize()
// Required properties
routes: [{
path: '/',
loader: ({ request, params }) => { /* ... */ },
children: [{
path: 'home',
loader: ({ request, params }) => { /* ... */ },
}]
},
history: createBrowserHistory(),
// Optional properties
basename, // Base path
mapRouteProperties, // Map framework-agnostic routes to framework-aware routes
future, // Future flags
hydrationData, // Hydration data if using server-side-rendering
}).initialize();
```

@@ -83,2 +95,7 @@

});
// Relative routing from a source routeId
router.navigate("../../somewhere", {
fromRouteId: "active-route-id",
});
```

@@ -107,2 +124,11 @@

### Future Flags
We use _Future Flags_ in the router to help us introduce breaking changes in an opt-in fashion ahead of major releases. Please check out the [blog post][future-flags-post] and [React Router Docs][api-development-strategy] for more information on this process. The currently available future flags in `@remix-run/router` are:
| Flag | Description |
| ------------------------ | ------------------------------------------------------------------------- |
| `v7_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
| `v7_prependBasename` | Prepend the `basename` to incoming `router.navigate`/`router.fetch` paths |
[react-router]: https://reactrouter.com

@@ -112,1 +138,3 @@ [remix]: https://remix.run

[remix-routers-repo]: https://github.com/brophdawg11/remix-routers
[api-development-strategy]: https://reactrouter.com/en/main/guides/api-development-strategy
[future-flags-post]: https://remix.run/blog/future-flags
import type { Location, Path, To } from "./history";
import { warning, invariant, parsePath } from "./history";
import { invariant, parsePath, warning } from "./history";

@@ -23,3 +23,3 @@ /**

type: ResultType.data;
data: any;
data: unknown;
statusCode?: number;

@@ -44,5 +44,4 @@ headers?: Headers;

type: ResultType.redirect;
status: number;
location: string;
revalidate: boolean;
// We keep the raw Response for redirects so we can return it verbatim
response: Response;
}

@@ -55,3 +54,4 @@

type: ResultType.error;
error: any;
error: unknown;
statusCode?: number;
headers?: Headers;

@@ -69,2 +69,10 @@ }

/**
* Result from a loader or action called via dataStrategy
*/
export interface HandlerResult {
type: ResultType.data | ResultType.error;
result: any; // data, Error, Response, DeferredData
}
type LowerCaseFormMethod = "get" | "post" | "put" | "patch" | "delete";

@@ -74,4 +82,4 @@ type UpperCaseFormMethod = Uppercase<LowerCaseFormMethod>;

/**
* Users can specify either lowercase or uppercase form methods on <Form>,
* useSubmit(), <fetcher.Form>, etc.
* Users can specify either lowercase or uppercase form methods on `<Form>`,
* useSubmit(), `<fetcher.Form>`, etc.
*/

@@ -96,4 +104,14 @@ export type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;

| "application/x-www-form-urlencoded"
| "multipart/form-data";
| "multipart/form-data"
| "application/json"
| "text/plain";
// Thanks https://github.com/sindresorhus/type-fest!
type JsonObject = { [Key in string]: JsonValue } & {
[Key in string]?: JsonValue | undefined;
};
type JsonArray = JsonValue[] | readonly JsonValue[];
type JsonPrimitive = string | number | boolean | null;
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
/**

@@ -104,8 +122,27 @@ * @private

*/
export interface Submission {
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: FormData;
}
export type Submission =
| {
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: FormData;
json: undefined;
text: undefined;
}
| {
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: undefined;
json: JsonValue;
text: undefined;
}
| {
formMethod: FormMethod | V7_FormMethod;
formAction: string;
formEncType: FormEncType;
formData: undefined;
json: undefined;
text: string;
};

@@ -117,12 +154,17 @@ /**

*/
interface DataFunctionArgs {
interface DataFunctionArgs<Context> {
request: Request;
params: Params;
context?: any;
context?: Context;
}
// TODO: (v7) Change the defaults from any to unknown in and remove Remix wrappers:
// ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs
// Also, make them a type alias instead of an interface
/**
* Arguments passed to loader functions
*/
export interface LoaderFunctionArgs extends DataFunctionArgs {}
export interface LoaderFunctionArgs<Context = any>
extends DataFunctionArgs<Context> {}

@@ -132,10 +174,23 @@ /**

*/
export interface ActionFunctionArgs extends DataFunctionArgs {}
export interface ActionFunctionArgs<Context = any>
extends DataFunctionArgs<Context> {}
/**
* Loaders and actions can return anything except `undefined` (`null` is a
* valid return value if there is no data to return). Responses are preferred
* and will ease any future migration to Remix
*/
type DataFunctionValue = Response | NonNullable<unknown> | null;
type DataFunctionReturnValue = Promise<DataFunctionValue> | DataFunctionValue;
/**
* Route loader function signature
*/
export interface LoaderFunction {
(args: LoaderFunctionArgs): Promise<Response> | Response | Promise<any> | any;
}
export type LoaderFunction<Context = any> = {
(
args: LoaderFunctionArgs<Context>,
handlerCtx?: unknown
): DataFunctionReturnValue;
} & { hydrate?: boolean };

@@ -145,7 +200,28 @@ /**

*/
export interface ActionFunction {
(args: ActionFunctionArgs): Promise<Response> | Response | Promise<any> | any;
export interface ActionFunction<Context = any> {
(
args: ActionFunctionArgs<Context>,
handlerCtx?: unknown
): DataFunctionReturnValue;
}
/**
* Arguments passed to shouldRevalidate function
*/
export interface ShouldRevalidateFunctionArgs {
currentUrl: URL;
currentParams: AgnosticDataRouteMatch["params"];
nextUrl: URL;
nextParams: AgnosticDataRouteMatch["params"];
formMethod?: Submission["formMethod"];
formAction?: Submission["formAction"];
formEncType?: Submission["formEncType"];
text?: Submission["text"];
formData?: Submission["formData"];
json?: Submission["json"];
actionResult?: any;
defaultShouldRevalidate: boolean;
}
/**
* Route shouldRevalidate function signature. This runs after any submission

@@ -158,14 +234,3 @@ * (navigation or fetcher), so we flatten the navigation/fetcher submission

export interface ShouldRevalidateFunction {
(args: {
currentUrl: URL;
currentParams: AgnosticDataRouteMatch["params"];
nextUrl: URL;
nextParams: AgnosticDataRouteMatch["params"];
formMethod?: Submission["formMethod"];
formAction?: Submission["formAction"];
formEncType?: Submission["formEncType"];
formData?: Submission["formData"];
actionResult?: DataResult;
defaultShouldRevalidate: boolean;
}): boolean;
(args: ShouldRevalidateFunctionArgs): boolean;
}

@@ -176,2 +241,4 @@

* from the framework-aware `errorElement` prop
*
* @deprecated Use `mapRouteProperties` instead
*/

@@ -182,3 +249,32 @@ export interface DetectErrorBoundaryFunction {

export interface DataStrategyMatch
extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
shouldLoad: boolean;
resolve: (
handlerOverride?: (
handler: (ctx?: unknown) => DataFunctionReturnValue
) => DataFunctionReturnValue
) => Promise<HandlerResult>;
}
export interface DataStrategyFunctionArgs<Context = any>
extends DataFunctionArgs<Context> {
matches: DataStrategyMatch[];
}
export interface DataStrategyFunction {
(args: DataStrategyFunctionArgs): Promise<HandlerResult[]>;
}
/**
* Function provided by the framework-aware layers to set any framework-specific
* properties from framework-agnostic properties
*/
export interface MapRoutePropertiesFunction {
(route: AgnosticRouteObject): {
hasErrorBoundary: boolean;
} & Record<string, any>;
}
/**
* Keys we cannot change from within a lazy() function. We spread all other keys

@@ -205,2 +301,9 @@ * onto the route. Either they're meaningful to the router, or they'll get

type RequireOne<T, Key = keyof T> = Exclude<
{
[K in keyof T]: K extends Key ? Omit<T, K> & Required<Pick<T, K>> : never;
}[keyof T],
undefined
>;
/**

@@ -211,3 +314,3 @@ * lazy() function to load a route definition, which can add non-matching

export interface LazyRouteFunction<R extends AgnosticRouteObject> {
(): Promise<Omit<R, ImmutableRouteKey>>;
(): Promise<RequireOne<Omit<R, ImmutableRouteKey>>>;
}

@@ -222,4 +325,4 @@

id?: string;
loader?: LoaderFunction;
action?: ActionFunction;
loader?: LoaderFunction | boolean;
action?: ActionFunction | boolean;
hasErrorBoundary?: boolean;

@@ -295,3 +398,3 @@ shouldRevalidate?: ShouldRevalidateFunction;

*/
type PathParam<Path extends string> =
export type PathParam<Path extends string> =
// check if path is just a wildcard

@@ -307,6 +410,6 @@ Path extends "*" | "/*"

// Attempt to parse the given string segment. If it fails, then just return the
// plain string type as a default fallback. Otherwise return the union of the
// plain string type as a default fallback. Otherwise, return the union of the
// parsed string literals that were referenced as dynamic segments in the route.
export type ParamParseKey<Segment extends string> =
// if could not find path params, fallback to `string`
// if you could not find path params, fallback to `string`
[PathParam<Segment>] extends [never] ? string : PathParam<Segment>;

@@ -355,7 +458,7 @@

// Walk the route tree generating unique IDs where necessary so we are working
// Walk the route tree generating unique IDs where necessary, so we are working
// solely with AgnosticDataRouteObject's within the Router
export function convertRoutesToDataRoutes(
routes: AgnosticRouteObject[],
detectErrorBoundary: DetectErrorBoundaryFunction,
mapRouteProperties: MapRoutePropertiesFunction,
parentPath: number[] = [],

@@ -380,3 +483,3 @@ manifest: RouteManifest = {}

...route,
hasErrorBoundary: detectErrorBoundary(route),
...mapRouteProperties(route),
id,

@@ -389,4 +492,4 @@ };

...route,
...mapRouteProperties(route),
id,
hasErrorBoundary: detectErrorBoundary(route),
children: undefined,

@@ -399,3 +502,3 @@ };

route.children,
detectErrorBoundary,
mapRouteProperties,
treePath,

@@ -437,12 +540,10 @@ manifest

for (let i = 0; matches == null && i < branches.length; ++i) {
matches = matchRouteBranch<string, RouteObjectType>(
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)
);
// 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.
let decoded = decodePath(pathname);
matches = matchRouteBranch<string, RouteObjectType>(branches[i], decoded);
}

@@ -453,2 +554,24 @@

export interface UIMatch<Data = unknown, Handle = unknown> {
id: string;
pathname: string;
params: AgnosticRouteMatch["params"];
data: Data;
handle: Handle;
}
export function convertRouteMatchToUiMatch(
match: AgnosticDataRouteMatch,
loaderData: RouteData
): UIMatch {
let { route, pathname, params } = match;
return {
id: route.id,
pathname,
params,
data: loaderData[route.id],
handle: route.handle,
};
}
interface RouteMeta<

@@ -506,3 +629,3 @@ RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject

// Add the children before adding this route to the array so we traverse the
// 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

@@ -584,6 +707,6 @@ // the "flattened" version.

// 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
// optional version for all children, so we get consistent ordering where the
// parent optional aspect is preferred as required. Otherwise, we can get
// child sections interspersed where deeper optional segments are higher than
// parent optional segments, where for example, /:two would explodes _earlier_
// parent optional segments, where for example, /:two would explode _earlier_
// then /:one. By always including the parent as required _for all children_

@@ -597,3 +720,3 @@ // first, we avoid this issue

// Then if this is an optional value, add all child versions without
// Then, if this is an optional value, add all child versions without
if (isOptional) {

@@ -620,3 +743,3 @@ result.push(...restExploded);

const paramRe = /^:\w+$/;
const paramRe = /^:[\w-]+$/;
const dynamicSegmentValue = 3;

@@ -743,2 +866,5 @@ const indexRouteValue = 2;

const stringify = (p: any) =>
p == null ? "" : typeof p === "string" ? p : String(p);
const segments = path

@@ -752,22 +878,12 @@ .split(/\/+/)

const star = "*" as PathParam<Path>;
const starParam = params[star];
// Apply the splat
return starParam;
return stringify(params[star]);
}
const keyMatch = segment.match(/^:(\w+)(\??)$/);
const keyMatch = segment.match(/^:([\w-]+)(\??)$/);
if (keyMatch) {
const [, key, optional] = keyMatch;
let param = params[key as PathParam<Path>];
if (optional === "?") {
return param == null ? "" : param;
}
if (param == null) {
invariant(false, `Missing ":${key}" param`);
}
return param;
invariant(optional === "?" || param != null, `Missing ":${key}" param`);
return stringify(param);
}

@@ -848,3 +964,3 @@

let [matcher, paramNames] = compilePath(
let [matcher, compiledParams] = compilePath(
pattern.path,

@@ -861,4 +977,4 @@ pattern.caseSensitive,

let captureGroups = match.slice(1);
let params: Params = paramNames.reduce<Mutable<Params>>(
(memo, paramName, index) => {
let params: Params = compiledParams.reduce<Mutable<Params>>(
(memo, { paramName, isOptional }, index) => {
// We need to compute the pathnameBase here using the raw splat value

@@ -873,6 +989,8 @@ // instead of using params["*"] later because it will be decoded then

memo[paramName] = safelyDecodeURIComponent(
captureGroups[index] || "",
paramName
);
const value = captureGroups[index];
if (isOptional && !value) {
memo[paramName] = undefined;
} else {
memo[paramName] = (value || "").replace(/%2F/g, "/");
}
return memo;

@@ -891,2 +1009,4 @@ },

type CompiledPathParam = { paramName: string; isOptional?: boolean };
function compilePath(

@@ -896,3 +1016,3 @@ path: string,

end = true
): [RegExp, string[]] {
): [RegExp, CompiledPathParam[]] {
warning(

@@ -906,3 +1026,3 @@ path === "*" || !path.endsWith("*") || path.endsWith("/*"),

let paramNames: string[] = [];
let params: CompiledPathParam[] = [];
let regexpSource =

@@ -913,10 +1033,13 @@ "^" +

.replace(/^\/*/, "/") // Make sure it has a leading /
.replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars
.replace(/\/:(\w+)/g, (_: string, paramName: string) => {
paramNames.push(paramName);
return "/([^\\/]+)";
});
.replace(/[\\.*+^${}|()[\]]/g, "\\$&") // Escape special regex chars
.replace(
/\/:([\w-]+)(\?)?/g,
(_: string, paramName: string, isOptional) => {
params.push({ paramName, isOptional: isOptional != null });
return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
}
);
if (path.endsWith("*")) {
paramNames.push("*");
params.push({ paramName: "*" });
regexpSource +=

@@ -931,3 +1054,3 @@ 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
// 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

@@ -945,8 +1068,11 @@ // non-captured trailing slash (to match a portion of the URL) or the end

return [matcher, paramNames];
return [matcher, params];
}
function safelyDecodeURI(value: string) {
function decodePath(value: string) {
try {
return decodeURI(value);
return value
.split("/")
.map((v) => decodeURIComponent(v).replace(/\//g, "%2F"))
.join("/");
} catch (error) {

@@ -964,17 +1090,2 @@ warning(

function safelyDecodeURIComponent(value: string, paramName: string) {
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;
}
}
/**

@@ -1096,2 +1207,21 @@ * @private

// Return the array of pathnames for the current route matches - used to
// generate the routePathnames input for resolveTo()
export function getResolveToMatches<
T extends AgnosticRouteMatch = AgnosticRouteMatch
>(matches: T[], v7_relativeSplatPath: boolean) {
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);
}
/**

@@ -1140,3 +1270,3 @@ * @private

// to the current location's pathname and *not* the route pathname.
if (isPathRelative || toPathname == null) {
if (toPathname == null) {
from = locationPathname;

@@ -1146,8 +1276,9 @@ } else {

if (toPathname.startsWith("..")) {
// 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("/");
// Each leading .. segment means "go up one route" instead of "go up one
// URL segment". This is a key difference from how <a href> works and a
// major reason we call this a "to" value instead of a "href".
while (toSegments[0] === "..") {

@@ -1161,4 +1292,2 @@ toSegments.shift();

// If there are more ".." segments than parent routes, resolve relative to
// the root / URL.
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";

@@ -1314,3 +1443,3 @@ }

let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(
(data) => this.onSettle(promise, key, null, data as unknown),
(data) => this.onSettle(promise, key, undefined, data as unknown),
(error) => this.onSettle(promise, key, error as unknown)

@@ -1349,3 +1478,15 @@ );

if (error) {
// 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 });

@@ -1472,11 +1613,32 @@ this.emit(false, key);

/**
* 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".
*/
export const redirectDocument: RedirectFunction = (url, init) => {
let response = redirect(url, init);
response.headers.set("X-Remix-Reload-Document", "true");
return response;
};
export type ErrorResponse = {
status: number;
statusText: string;
data: any;
};
/**
* @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()
*/
export class ErrorResponse {
export class ErrorResponseImpl implements ErrorResponse {
status: number;
statusText: string;
data: any;
error?: Error;
internal: boolean;
private error?: Error;
private internal: boolean;

@@ -1502,2 +1664,28 @@ constructor(

/**
* Utility class we use to hold unwrapped Responses while preserving status
* codes and headers. This is most useful for dataStrategy implementations
* where implementors want to use a custom decoding mechanism and return
* pre-decoded data while also preserving response meta information
*/
export class DecodedResponse {
status: number;
statusText: string;
headers: Headers;
data: unknown;
private _isDecodedResponse: boolean = true;
constructor(
status: number,
statusText: string,
headers: Headers,
data: unknown
) {
this.status = status;
this.statusText = statusText;
this.headers = headers;
this.data = data;
}
}
/**
* Check if the given error is an ErrorResponse generated from a 4xx/5xx

@@ -1515,1 +1703,15 @@ * Response thrown from an action/loader

}
/**
* Check if the given error is an DecodedResponse
*/
export function isDecodedResponse(value: any): value is DecodedResponse {
return (
value != null &&
value._isDecodedResponse === true &&
typeof value.status === "number" &&
typeof value.statusText === "string" &&
value.headers != null &&
"data" in value
);
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc