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-ba938b84 to 0.0.0-experimental-bc2c864b

516

CHANGELOG.md
# `@remix-run/router`
## 1.3.3-pre.1
## 1.14.2
### Patch Changes
- Correctly perform a "hard" redirect for same-origin absolute URLs outside of the router basename ([#10076](https://github.com/remix-run/react-router/pull/10076))
- 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.3.3-pre.0
## 1.14.1
### Patch Changes
- Change `invariant` to an `UNSAFE_` export since it's only intended for internal use ([#10066](https://github.com/remix-run/react-router/pull/10066))
- 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
### Minor Changes
- **Introducing Lazy Route Modules!** ([#10045](https://github.com/remix-run/react-router/pull/10045))
In order to keep your application bundles small and support code-splitting of your routes, we've introduced a new `lazy()` route property. This is an async function that resolves the non-route-matching portions of your route definition (`loader`, `action`, `element`/`Component`, `errorElement`/`ErrorBoundary`, `shouldRevalidate`, `handle`).
Lazy routes are resolved on initial load and during the `loading` or `submitting` phase of a navigation or fetcher call. You cannot lazily define route-matching properties (`path`, `index`, `children`) since we only execute your lazy route functions after we've matched known routes.
Your `lazy` functions will typically return the result of a dynamic import.
```jsx
// In this example, we assume most folks land on the homepage so we include that
// in our critical-path bundle, but then we lazily load modules for /a and /b so
// they don't load until the user navigates to those routes
let routes = createRoutesFromElements(
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="a" lazy={() => import("./a")} />
<Route path="b" lazy={() => import("./b")} />
</Route>
);
```
Then in your lazy route modules, export the properties you want defined for the route:
```jsx
export async function loader({ request }) {
let data = await fetchData(request);
return json(data);
}
// Export a `Component` directly instead of needing to create a React Element from it
export function Component() {
let data = useLoaderData();
return (
<>
<h1>You made it!</h1>
<p>{data}</p>
</>
);
}
// Export an `ErrorBoundary` directly instead of needing to create a React Element from it
export function ErrorBoundary() {
let error = useRouteError();
return isRouteErrorResponse(error) ? (
<h1>
{error.status} {error.statusText}
</h1>
) : (
<h1>{error.message || error}</h1>
);
}
```
An example of this in action can be found in the [`examples/lazy-loading-router-provider`](https://github.com/remix-run/react-router/tree/main/examples/lazy-loading-router-provider) directory of the repository.
🙌 Huge thanks to @rossipedia for the [Initial Proposal](https://github.com/remix-run/react-router/discussions/9826) and [POC Implementation](https://github.com/remix-run/react-router/pull/9830).
### Patch Changes
- Fix `generatePath` incorrectly applying parameters in some cases ([#10078](https://github.com/remix-run/react-router/pull/10078))
## 1.3.3
### Patch Changes
- Correctly perform a hard redirect for same-origin absolute URLs outside of the router `basename` ([#10076](https://github.com/remix-run/react-router/pull/10076))
- Ensure status code and headers are maintained for `defer` loader responses in `createStaticHandler`'s `query()` method ([#10077](https://github.com/remix-run/react-router/pull/10077))
- Change `invariant` to an `UNSAFE_invariant` export since it's only intended for internal use ([#10066](https://github.com/remix-run/react-router/pull/10066))
- Add internal API for custom HMR implementations ([#9996](https://github.com/remix-run/react-router/pull/9996))

@@ -184,9 +683,4 @@

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).

21

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;
/**

@@ -237,2 +237,3 @@ * Hash history stores the location in window.location.hash. This makes it ideal

export declare function invariant<T>(value: T | null | undefined, message?: string): asserts value is T;
export declare function warning(cond: any, message: string): void;
/**

@@ -252,5 +253,5 @@ * Creates a Location object with a unique key from the given Path

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

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

export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, TrackedPromise, FormEncType, FormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, Submission, } from "./utils";
export { AbortedDeferredError, ErrorResponse, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, warning, } 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, defer, generatePath, getToPathname, 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 { DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, } from "./utils";
export { invariant as UNSAFE_invariant } from "./history";
export type { RouteManifest as UNSAFE_RouteManifest } 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, RouteData, AgnosticRouteObject, AgnosticRouteMatch } 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,11 +257,29 @@ * @internal

*/
export declare type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">>;
export type HydrationState = Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">>;
/**
* 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;
}
/**
* Initialization options for createRouter
*/
export interface RouterInit {
basename?: string;
routes: AgnosticRouteObject[];
history: History;
basename?: string;
/**
* @deprecated Use `mapRouteProperties` instead
*/
detectErrorBoundary?: DetectErrorBoundaryFunction;
mapRouteProperties?: MapRoutePropertiesFunction;
future?: Partial<FutureConfig>;
hydrationData?: HydrationState;
window?: Window;
unstable_dataStrategy?: DataStrategyFunction;
}

@@ -284,2 +315,6 @@ /**

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

@@ -289,11 +324,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;
}
/**

@@ -304,3 +336,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;
}

@@ -313,33 +345,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;
formMethod?: FormMethod;
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: {

@@ -352,2 +403,4 @@ state: "idle";

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

@@ -357,6 +410,8 @@ Loading: {

location: Location;
formMethod: 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;
};

@@ -366,14 +421,16 @@ Submitting: {

location: Location;
formMethod: 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: {

@@ -384,26 +441,29 @@ state: "idle";

formEncType: undefined;
text: undefined;
formData: undefined;
json: undefined;
data: TData | undefined;
" _hasFetcherDoneAnything "?: boolean;
};
Loading: {
state: "loading";
formMethod: 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;
" _hasFetcherDoneAnything "?: boolean;
};
Submitting: {
state: "submitting";
formMethod: 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;
" _hasFetcherDoneAnything "?: boolean;
};
};
export declare type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
export type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
interface BlockerBlocked {

@@ -427,4 +487,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;

@@ -442,5 +502,20 @@ nextLocation: Location;

export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: {
/**
* Future flags to toggle new feature behavior
*/
export interface StaticHandlerFutureConfig {
v7_relativeSplatPath: boolean;
v7_throwAbortReason: boolean;
}
export interface CreateStaticHandlerOptions {
basename?: string;
}): StaticHandler;
/**
* @deprecated Use `mapRouteProperties` instead
*/
detectErrorBoundary?: DetectErrorBoundaryFunction;
unstable_dataStrategy?: DataStrategyFunction;
mapRouteProperties?: MapRoutePropertiesFunction;
future?: Partial<StaticHandlerFutureConfig>;
}
export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;
/**

@@ -451,2 +526,3 @@ * Given an existing StaticHandlerContext and an error thrown at render time,

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-ba938b84
* @remix-run/router v0.0.0-experimental-bc2c864b
*

@@ -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 n(e,t){if(!1===e||null==e)throw new Error(t)}function o(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,n){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||n||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,o,c,d){void 0===d&&(d={});let{window:u=document.defaultView,v5Compat:h=!1}=d,f=u.history,p=e.Action.Pop,m=null,g=v();function v(){return(f.state||{idx:null}).idx}function y(){p=e.Action.Pop;let t=v(),r=null==t?null:t-g;g=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 n(t,"No window.location.(origin|href) available to create URL for href: "+r),new URL(r,t)}null==g&&(g=0,f.replaceState(t({},f.state,{idx:g}),""));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,y),m=e,()=>{u.removeEventListener(a,y),m=null}},createHref:e=>o(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),g=v()+1;let n=i(a,g),o=w.createHref(a);try{f.pushState(n,"",o)}catch(e){u.location.assign(o)}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),g=v();let n=i(a,g),o=w.createHref(a);f.replaceState(n,"",o),h&&m&&m({action:p,location:w.location,delta:0})},go:e=>f.go(e)};return w}let u;function h(e,r,a){return void 0===r&&(r=[]),void 0===a&&(a=new Set),e.map(((e,o)=>{let i=[...r,o],s="string"==typeof e.id?e.id:i.join("-");if(n(!0!==e.index||!e.children,"Cannot specify children on an index route"),n(!a.has(s),'Found a route id collision on id "'+s+"\". Route id's must be globally unique within Data Router usages"),a.add(s),function(e){return!0===e.index}(e)){return t({},e,{id:s})}return t({},e,{id:s,children:e.children?h(e.children,i,a):void 0})}))}function f(e,t,r){void 0===r&&(r="/");let a=A(("string"==typeof t?c(t):t).pathname||"/",r);if(null==a)return null;let n=p(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)))))}(n);let o=null;for(let e=0;null==o&&e<n.length;++e)o=b(n[e],D(a));return o}function p(e,t,r,a){void 0===t&&(t=[]),void 0===r&&(r=[]),void 0===a&&(a="");let o=(e,o,i)=>{let s={relativePath:void 0===i?e.path||"":i,caseSensitive:!0===e.caseSensitive,childrenIndex:o,route:e};s.relativePath.startsWith("/")&&(n(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&&(n(!0!==e.index,'Index routes must not have child routes. Please remove all child routes from route path "'+l+'".'),p(e.children,t,c,l)),(null!=e.path||e.index)&&t.push({path:l,score:y(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 m(e.path))o(e,t,r);else o(e,t)})),t}function m(e){let t=e.split("/");if(0===t.length)return[];let[r,...a]=t,n=r.endsWith("?"),o=r.replace(/\?$/,"");if(0===a.length)return n?[o,""]:[o];let i=m(a.join("/")),s=[];return s.push(...i.map((e=>""===e?o:[o,e].join("/")))),n&&s.push(...i),s.map((t=>e.startsWith("/")&&""===t?"/":t))}!function(e){e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error"}(u||(u={}));const g=/^:\w+$/,v=e=>"*"===e;function y(e,t){let r=e.split("/"),a=r.length;return r.some(v)&&(a+=-2),t&&(a+=2),r.filter((e=>!v(e))).reduce(((e,t)=>e+(g.test(t)?3:""===t?1:10)),a)}function b(e,t){let{routesMeta:r}=e,a={},n="/",o=[];for(let e=0;e<r.length;++e){let i=r[e],s=e===r.length-1,l="/"===n?t:t.slice(n.length)||"/",c=w({path:i.relativePath,caseSensitive:i.caseSensitive,end:s},l);if(!c)return null;Object.assign(a,c.params);let d=i.route;o.push({params:a,pathname:L([n,c.pathname]),pathnameBase:k(L([n,c.pathnameBase])),route:d}),"/"!==c.pathnameBase&&(n=L([n,c.pathnameBase]))}return o}function w(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);R("*"===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=[],n="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/\/:(\w+)/g,((e,t)=>(a.push(t),"/([^\\/]+)")));e.endsWith("*")?(a.push("*"),n+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):r?n+="\\/*$":""!==e&&"/"!==e&&(n+="(?:(?=\\/|$))");return[new RegExp(n,t?void 0:"i"),a]}(e.path,e.caseSensitive,e.end),n=t.match(r);if(!n)return null;let o=n[0],i=o.replace(/(.)\/+$/,"$1"),s=n.slice(1);return{params:a.reduce(((e,t,r)=>{if("*"===t){let e=s[r]||"";i=o.slice(0,o.length-e.length).replace(/(.)\/+$/,"$1")}return e[t]=function(e,t){try{return decodeURIComponent(e)}catch(r){return R(!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}}(s[r]||"",t),e}),{}),pathname:o,pathnameBase:i,pattern:e}}function D(e){try{return decodeURI(e)}catch(t){return R(!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 A(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 R(e,t){if(!e){"undefined"!=typeof console&&console.warn(t);try{throw new Error(t)}catch(e){}}}function E(e,t){void 0===t&&(t="/");let{pathname:r,search:a="",hash:n=""}="string"==typeof e?c(e):e,o=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:o,search:x(a),hash:C(n)}}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,o){let i;void 0===o&&(o=!1),"string"==typeof e?i=c(e):(i=t({},e),n(!i.pathname||!i.pathname.includes("?"),P("?","pathname","search",i)),n(!i.pathname||!i.pathname.includes("#"),P("#","pathname","hash",i)),n(!i.search||!i.search.includes("#"),P("#","search","hash",i)));let s,l=""===e||""===i.pathname,d=l?"/":i.pathname;if(o||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=E(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 T{constructor(e,t){let r;this.pendingKeysSet=new Set,this.subscribers=new Set,this.deferredKeys=[],n(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 n(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]:j(a)})}),{})}get pendingKeys(){return Array.from(this.pendingKeysSet)}}function j(e){if(!function(e){return e instanceof Promise&&!0===e._tracked}(e))return e;if(e._error)throw e._error;return e._data}class O{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 F=["post","put","patch","delete"],H=new Set(F),I=["get",...F],q=new Set(I),W=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},B={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},z={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;const V=Symbol("deferred");function G(e,t,r){void 0===r&&(r=!1);let a,n="string"==typeof e?e:l(e);if(!t||!function(e){return null!=e&&"formData"in e}(t))return{path:n};if(t.formMethod&&!ve(t.formMethod))return{path:n,error:ce(405,{method:t.formMethod})};if(t.formData&&(a={formMethod:t.formMethod||"get",formAction:ue(n),formEncType:t&&t.formEncType||"application/x-www-form-urlencoded",formData:t.formData},ye(a.formMethod)))return{path:n,submission:a};let o=c(n),i=ae(t.formData);return r&&o.search&&De(o.search)&&i.append("index",""),o.search="?"+i,{path:l(o),submission:a}}function X(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 Q(e,r,a,n,o,i,s,l,c,d,u,h,p){let m=p?Object.values(p)[0]:h?Object.values(h)[0]:void 0,g=e.createURL(r.location),v=e.createURL(o),y=i||g.toString()===v.toString()||g.search!==v.search,b=p?Object.keys(p)[0]:void 0,w=X(a,b).filter(((e,a)=>{if(null==e.route.loader)return!1;if(function(e,t,r){let a=!t||r.route.id!==t.route.id,n=void 0===e[r.route.id];return a||n}(r.loaderData,r.matches[a],e)||s.some((t=>t===e.route.id)))return!0;let o=r.matches[a],i=e;return ee(e,t({currentUrl:g,currentParams:o.params,nextUrl:v,nextParams:i.params},n,{actionResult:m,defaultShouldRevalidate:y||Z(o,i)}))})),D=[];return c.forEach(((e,o)=>{if(!a.some((t=>t.route.id===e.routeId)))return;let i=f(d,e.path,u);if(!i)return void D.push(t({key:o},e,{matches:null,match:null}));let s=Re(i,e.path);(l.includes(o)||ee(s,t({currentUrl:g,currentParams:r.matches[r.matches.length-1].params,nextUrl:v,nextParams:a[a.length-1].params},n,{actionResult:m,defaultShouldRevalidate:y})))&&D.push(t({key:o,matches:i,match:s},e))})),[w,D]}function Z(e,t){let r=e.route.path;return e.pathname!==t.pathname||null!=r&&r.endsWith("*")&&e.params["*"]!==t.params["*"]}function ee(e,t){if(e.route.shouldRevalidate){let r=e.route.shouldRevalidate(t);if("boolean"==typeof r)return r}return t.defaultShouldRevalidate}async function te(e,t,r,a,o,i,s,c){let d,h,f;void 0===o&&(o="/"),void 0===i&&(i=!1),void 0===s&&(s=!1);let p=new Promise(((e,t)=>f=t)),m=()=>f();t.signal.addEventListener("abort",m);try{let a=r.route[e];n(a,"Could not find the "+e+' to run on the "'+r.route.id+'" route'),h=await Promise.race([a({request:t,params:r.params,context:c}),p]),n(void 0!==h,"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){d=u.error,h=e}finally{t.signal.removeEventListener("abort",m)}if(me(h)){let e,c=h.status;if(W.has(c)){let e=h.headers.get("Location");if(n(e,"Redirects returned/thrown from loaders/actions must have a Location header"),K.test(e)){if(!i){let r=new URL(t.url),a=e.startsWith("//")?new URL(r.protocol+e):new URL(e),n=null!=A(a.pathname,o);a.origin===r.origin&&n&&(e=a.pathname+a.search+a.hash)}}else{let i=M(e,S(a.slice(0,a.indexOf(r)+1)).map((e=>e.pathnameBase)),new URL(t.url).pathname);if(n(l(i),"Unable to resolve redirect location: "+e),o){let e=i.pathname;i.pathname="/"===e?o:L([o,e])}e=l(i)}if(i)throw h.headers.set("Location",e),h;return{type:u.redirect,status:c,location:e,revalidate:null!==h.headers.get("X-Remix-Revalidate")}}if(s)throw{type:d||u.data,response:h};let f=h.headers.get("Content-Type");return e=f&&/\bapplication\/json\b/.test(f)?await h.json():await h.text(),d===u.error?{type:d,error:new O(c,h.statusText,e),headers:h.headers}:{type:u.data,data:e,statusCode:h.status,headers:h.headers}}return d===u.error?{type:d,error:h}:h instanceof T?{type:u.deferred,deferredData:h,statusCode:null==(g=h.init)?void 0:g.status,headers:(null==(v=h.init)?void 0:v.headers)&&new Headers(h.init.headers)}:{type:u.data,data:h};var g,v}function re(e,t,r,a){let n=e.createURL(ue(t)).toString(),o={signal:r};if(a&&ye(a.formMethod)){let{formMethod:e,formEncType:t,formData:r}=a;o.method=e.toUpperCase(),o.body="application/x-www-form-urlencoded"===t?ae(r):r}return new Request(n,o)}function ae(e){let t=new URLSearchParams;for(let[r,a]of e.entries())t.append(r,a instanceof File?a.name:a);return t}function ne(e,t,r,a,o){let i,s={},l=null,c=!1,d={};return r.forEach(((r,u)=>{let h=t[u].route.id;if(n(!pe(r),"Cannot handle redirect results in processLoaderData"),fe(r)){let t=se(e,h),n=r.error;a&&(n=Object.values(a)[0],a=void 0),l=l||{},null==l[t.route.id]&&(l[t.route.id]=n),s[h]=void 0,c||(c=!0,i=_(r.error)?r.error.status:500),r.headers&&(d[h]=r.headers)}else he(r)?(o.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 oe(e,r,a,o,i,s,l,c){let{loaderData:d,errors:u}=ne(r,a,o,i,c);for(let r=0;r<s.length;r++){let{key:a,match:o}=s[r];n(void 0!==l&&void 0!==l[r],"Did not find corresponding fetcher result");let i=l[r];if(fe(i)){let r=se(e.matches,null==o?void 0:o.route.id);u&&u[r.route.id]||(u=t({},u,{[r.route.id]:i.error})),e.fetchers.delete(a)}else if(pe(i))n(!1,"Unhandled fetcher revalidation redirect");else if(he(i))n(!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," _hasFetcherDoneAnything ":!0};e.fetchers.set(a,t)}}return{loaderData:d,errors:u}}function ie(e,r,a,n){let o=t({},r);for(let t of a){let a=t.route.id;if(r.hasOwnProperty(a)?void 0!==r[a]&&(o[a]=r[a]):void 0!==e[a]&&t.route.loader&&(o[a]=e[a]),n&&n.hasOwnProperty(a))break}return o}function se(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 le(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 ce(e,t){let{pathname:r,routeId:a,method:n,type:o}=void 0===t?{}:t,i="Unknown Server Error",s="Unknown @remix-run/router error";return 400===e?(i="Bad Request",n&&r&&a?s="You made a "+n+' request to "'+r+'" but did not provide a `loader` for route "'+a+'", so there is no way to handle the request.':"defer-action"===o&&(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",n&&r&&a?s="You made a "+n.toUpperCase()+' request to "'+r+'" but did not provide an `action` for route "'+a+'", so there is no way to handle the request.':n&&(s='Invalid request method "'+n.toUpperCase()+'"')),new O(e||500,i,new Error(s),!0)}function de(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(pe(r))return r}}function ue(e){return l(t({},"string"==typeof e?c(e):e,{hash:""}))}function he(e){return e.type===u.deferred}function fe(e){return e.type===u.error}function pe(e){return(e&&e.type)===u.redirect}function me(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"object"==typeof e.headers&&void 0!==e.body}function ge(e){if(!me(e))return!1;let t=e.status,r=e.headers.get("Location");return t>=300&&t<=399&&null!=r}function ve(e){return q.has(e)}function ye(e){return H.has(e)}async function be(e,t,r,a,n,o){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&&!Z(c,l)&&void 0!==(o&&o[l.route.id]);he(s)&&(n||d)&&await we(s,a,n).then((e=>{e&&(r[i]=e||r[i])}))}}async function we(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 De(e){return new URLSearchParams(e).getAll("index").some((e=>""===e))}function Ae(e,t){let{route:r,pathname:a,params:n}=e;return{id:r.id,pathname:a,params:n,data:t[r.id],handle:r.handle}}function Re(e,t){let r="string"==typeof t?c(t).search:t.search;if(e[e.length-1].route.index&&De(r||""))return e[e.length-1];let a=S(e);return a[a.length-1]}e.AbortedDeferredError=U,e.ErrorResponse=O,e.IDLE_BLOCKER=z,e.IDLE_FETCHER=B,e.IDLE_NAVIGATION=N,e.UNSAFE_DEFERRED_SYMBOL=V,e.UNSAFE_DeferredData=T,e.UNSAFE_convertRoutesToDataRoutes=h,e.UNSAFE_getPathContributingMatches=S,e.UNSAFE_invariant=n,e.createBrowserHistory=function(e){return void 0===e&&(e={}),d((function(e,t){let{pathname:r,search:a,hash:n}=e.location;return s("",{pathname:r,search:a,hash:n},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:n=""}=c(e.location.hash.substr(1));return s("",{pathname:r,search:a,hash:n},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){o("/"===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:n,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==n?r.length-1:n),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 n=s(r?p().pathname:"/",e,t,a);return o("/"===n.pathname.charAt(0),"relative pathnames are not supported in memory history: "+JSON.stringify(e)),n}function g(e){return"string"==typeof e?e:l(e)}return{get index(){return d},get action(){return u},get location(){return p()},createHref:g,createURL:e=>new URL(g(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 n=m(t,a);d+=1,r.splice(d,r.length,n),i&&h&&h({action:u,location:n,delta:1})},replace(t,a){u=e.Action.Replace;let n=m(t,a);r[d]=n,i&&h&&h({action:u,location:n,delta:0})},go(t){u=e.Action.Pop;let a=f(d+t),n=r[a];d=a,h&&h({action:u,location:n,delta:t})},listen:e=>(h=e,()=>{h=null})}},e.createPath=l,e.createRouter=function(r){n(r.routes.length>0,"You must provide a non-empty routes array to createRouter");let a,o=h(r.routes),i=null,l=new Set,c=null,d=null,p=null,m=null!=r.hydrationData,g=f(o,r.history.location,r.basename),v=null;if(null==g){let e=ce(404,{pathname:r.history.location.pathname}),{matches:t,route:a}=le(o);g=t,v={[a.id]:e}}let y,b,w=!g.some((e=>e.route.loader))||null!=r.hydrationData,D={historyAction:r.history.action,location:r.history.location,matches:g,initialized:w,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||v,fetchers:new Map,blockers:new Map},E=e.Action.Pop,P=!1,S=!1,M=!1,L=[],k=[],x=new Map,C=0,U=-1,T=new Map,j=new Set,O=new Map,_=new Map,F=new Map,H=!1;function I(e){D=t({},D,e),l.forEach((e=>e(D)))}function q(n,i){var s,l;let c,d=null!=D.actionData&&null!=D.navigation.formMethod&&ye(D.navigation.formMethod)&&"loading"===D.navigation.state&&!0!==(null==(s=n.state)?void 0:s._isRedirect);c=i.actionData?Object.keys(i.actionData).length>0?i.actionData:null:d?D.actionData:null;let u=i.loaderData?ie(D.loaderData,i.loaderData,i.matches||[],i.errors):D.loaderData;for(let[e]of F)ve(e);let h=!0===P||null!=D.navigation.formMethod&&ye(D.navigation.formMethod)&&!0!==(null==(l=n.state)?void 0:l._isRedirect);a&&(o=a,a=void 0),I(t({},i,{actionData:c,loaderData:u,historyAction:E,location:n,initialized:!0,navigation:N,revalidation:"idle",restoreScrollPosition:Se(n,i.matches||D.matches),preventScrollReset:h,blockers:new Map(D.blockers)})),S||E===e.Action.Pop||(E===e.Action.Push?r.history.push(n,n.state):E===e.Action.Replace&&r.history.replace(n,n.state)),E=e.Action.Pop,P=!1,S=!1,M=!1,L=[],k=[]}async function W(i,s,l){b&&b.abort(),b=null,E=i,S=!0===(l&&l.startUninterruptedRevalidation),function(e,t){if(c&&d&&p){let r=t.map((e=>Ae(e,D.loaderData))),a=d(e,r)||e.key;c[a]=p()}}(D.location,D.matches),P=!0===(l&&l.preventScrollReset);let h=a||o,m=l&&l.overrideNavigation,g=f(h,s,r.basename);if(!g){let e=ce(404,{pathname:s.pathname}),{matches:t,route:r}=le(h);return Pe(),void q(s,{matches:t,loaderData:{},errors:{[r.id]:e}})}if(!(v=D.location,w=s,v.pathname!==w.pathname||v.search!==w.search||v.hash===w.hash||l&&l.submission&&ye(l.submission.formMethod)))return void q(s,{matches:g});var v,w;b=new AbortController;let A,R,T=re(r.history,s,b.signal,l&&l.submission);if(l&&l.pendingError)R={[se(g).route.id]:l.pendingError};else if(l&&l.submission&&ye(l.submission.formMethod)){let r=await async function(r,a,n,o,i){let s;ee(),I({navigation:t({state:"submitting",location:a},n)});let l=Re(o,a);if(l.route.action){if(s=await te("action",r,l,o,y.basename),r.signal.aborted)return{shortCircuited:!0}}else s={type:u.error,error:ce(405,{method:r.method,pathname:a.pathname,routeId:l.route.id})};if(pe(s)){let e;return e=i&&null!=i.replace?i.replace:s.location===D.location.pathname+D.location.search,await X(D,s,{submission:n,replace:e}),{shortCircuited:!0}}if(fe(s)){let t=se(o,l.route.id);return!0!==(i&&i.replace)&&(E=e.Action.Push),{pendingActionData:{},pendingActionError:{[t.route.id]:s.error}}}if(he(s))throw ce(400,{type:"defer-action"});return{pendingActionData:{[l.route.id]:s.data}}}(T,s,l.submission,g,{replace:l.replace});if(r.shortCircuited)return;A=r.pendingActionData,R=r.pendingActionError,m=t({state:"loading",location:s},l.submission),T=new Request(T.url,{signal:T.signal})}let{shortCircuited:F,loaderData:H,errors:W}=await async function(e,i,s,l,c,d,u,h){let f=l;if(!f){f=t({state:"loading",location:i,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},c)}let p=c||(f.formMethod&&f.formAction&&f.formData&&f.formEncType?{formMethod:f.formMethod,formAction:f.formAction,formData:f.formData,formEncType:f.formEncType}:void 0),m=a||o,[g,v]=Q(r.history,D,s,p,i,M,L,k,O,m,r.basename,u,h);if(Pe((e=>!(s&&s.some((t=>t.route.id===e)))||g&&g.some((t=>t.route.id===e)))),0===g.length&&0===v.length)return q(i,t({matches:s,loaderData:{},errors:h||null},u?{actionData:u}:{})),{shortCircuited:!0};if(!S){v.forEach((e=>{let t=D.fetchers.get(e.key),r={state:"loading",data:t&&t.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};D.fetchers.set(e.key,r)}));let e=u||D.actionData;I(t({navigation:f},e?0===Object.keys(e).length?{actionData:null}:{actionData:e}:{},v.length>0?{fetchers:new Map(D.fetchers)}:{}))}U=++C,v.forEach((e=>x.set(e.key,b)));let{results:y,loaderResults:w,fetcherResults:A}=await Z(D.matches,s,g,v,e);if(e.signal.aborted)return{shortCircuited:!0};v.forEach((e=>x.delete(e.key)));let R=de(y);if(R)return await X(D,R,{replace:d}),{shortCircuited:!0};let{loaderData:E,errors:P}=oe(D,s,g,w,h,v,A,_);_.forEach(((e,t)=>{e.subscribe((r=>{(r||e.done)&&_.delete(t)}))})),function(){let e=[];for(let t of j){let r=D.fetchers.get(t);n(r,"Expected fetcher: "+t),"loading"===r.state&&(j.delete(t),e.push(t))}me(e)}();let T=ge(U);return t({loaderData:E,errors:P},T||v.length>0?{fetchers:new Map(D.fetchers)}:{})}(T,s,g,m,l&&l.submission,l&&l.replace,A,R);F||(b=null,q(s,t({matches:g},A?{actionData:A}:{},{loaderData:H,errors:W})))}function V(e){return D.fetchers.get(e)||B}async function X(a,o,i){var l;let{submission:c,replace:d,isFetchActionRedirect:u}=void 0===i?{}:i;o.revalidate&&(M=!0);let h=s(a.location,o.location,t({_isRedirect:!0},u?{_isFetchActionRedirect:!0}:{}));if(n(h,"Expected a location on the redirect navigation"),K.test(o.location)&&Y&&void 0!==(null==(l=window)?void 0:l.location)){let e=r.history.createURL(o.location),t=null==A(e.pathname,r.basename||"/");if(window.location.origin!==e.origin||t)return void(d?window.location.replace(o.location):window.location.assign(o.location))}b=null;let f=!0===d?e.Action.Replace:e.Action.Push,{formMethod:p,formAction:m,formEncType:g,formData:v}=a.navigation;!c&&p&&m&&v&&g&&(c={formMethod:p,formAction:m,formEncType:g,formData:v}),$.has(o.status)&&c&&ye(c.formMethod)?await W(f,h,{submission:t({},c,{formAction:o.location}),preventScrollReset:P}):await W(f,h,{overrideNavigation:{state:"loading",location:h,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:P})}async function Z(e,t,a,n,o){let i=await Promise.all([...a.map((e=>te("loader",o,e,t,y.basename))),...n.map((e=>{if(e.matches&&e.match)return te("loader",re(r.history,e.path,o.signal),e.match,e.matches,y.basename);return{type:u.error,error:ce(404,{pathname:e.path})}}))]),s=i.slice(0,a.length),l=i.slice(a.length);return await Promise.all([be(e,a,s,o.signal,!1,D.loaderData),be(e,n.map((e=>e.match)),l,o.signal,!0)]),{results:i,loaderResults:s,fetcherResults:l}}function ee(){M=!0,L.push(...Pe()),O.forEach(((e,t)=>{x.has(t)&&(k.push(t),ue(t))}))}function ae(e,t,r){let a=se(D.matches,t);ne(e),I({errors:{[a.route.id]:r},fetchers:new Map(D.fetchers)})}function ne(e){x.has(e)&&ue(e),O.delete(e),T.delete(e),j.delete(e),D.fetchers.delete(e)}function ue(e){let t=x.get(e);n(t,"Expected fetch controller: "+e),t.abort(),x.delete(e)}function me(e){for(let t of e){let e={state:"idle",data:V(t).data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};D.fetchers.set(t,e)}}function ge(e){let t=[];for(let[r,a]of T)if(a<e){let e=D.fetchers.get(r);n(e,"Expected fetcher: "+r),"loading"===e.state&&(ue(r),T.delete(r),t.push(r))}return me(t),t.length>0}function ve(e){D.blockers.delete(e),F.delete(e)}function De(e,t){let r=D.blockers.get(e)||z;n("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),D.blockers.set(e,t),I({blockers:new Map(D.blockers)})}function Ee(e){let{currentLocation:t,nextLocation:r,historyAction:a}=e;if(0===F.size)return;F.size>1&&R(!1,"A router only supports one blocker at a time");let n=Array.from(F.entries()),[o,i]=n[n.length-1],s=D.blockers.get(o);return s&&"proceeding"===s.state?void 0:i({currentLocation:t,nextLocation:r,historyAction:a})?o:void 0}function Pe(e){let t=[];return _.forEach(((r,a)=>{e&&!e(a)||(r.cancel(),t.push(a),_.delete(a))})),t}function Se(e,t){if(c&&d&&p){let r=t.map((e=>Ae(e,D.loaderData))),a=d(e,r)||e.key,n=c[a];if("number"==typeof n)return n}return null}return y={get basename(){return r.basename},get state(){return D},get routes(){return o},initialize:function(){return i=r.history.listen((e=>{let{action:t,location:a,delta:n}=e;if(H)return void(H=!1);R(0===F.size||null!=n,"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 o=Ee({currentLocation:D.location,nextLocation:a,historyAction:t});return o&&null!=n?(H=!0,r.history.go(-1*n),void De(o,{state:"blocked",location:a,proceed(){De(o,{state:"proceeding",proceed:void 0,reset:void 0,location:a}),r.history.go(n)},reset(){ve(o),I({blockers:new Map(y.state.blockers)})}})):W(t,a)})),D.initialized||W(e.Action.Pop,D.location),y},subscribe:function(e){return l.add(e),()=>l.delete(e)},enableScrollRestoration:function(e,t,r){if(c=e,p=t,d=r||(e=>e.key),!m&&D.navigation===N){m=!0;let e=Se(D.location,D.matches);null!=e&&I({restoreScrollPosition:e})}return()=>{c=null,p=null,d=null}},navigate:async function a(n,o){if("number"==typeof n)return void r.history.go(n);let{path:i,submission:l,error:c}=G(n,o),d=D.location,u=s(D.location,i,o&&o.state);u=t({},u,r.history.encodeLocation(u));let h=o&&null!=o.replace?o.replace:void 0,f=e.Action.Push;!0===h?f=e.Action.Replace:!1===h||null!=l&&ye(l.formMethod)&&l.formAction===D.location.pathname+D.location.search&&(f=e.Action.Replace);let p=o&&"preventScrollReset"in o?!0===o.preventScrollReset:void 0,m=Ee({currentLocation:d,nextLocation:u,historyAction:f});if(!m)return await W(f,u,{submission:l,pendingError:c,preventScrollReset:p,replace:o&&o.replace});De(m,{state:"blocked",location:u,proceed(){De(m,{state:"proceeding",proceed:void 0,reset:void 0,location:u}),a(n,o)},reset(){ve(m),I({blockers:new Map(D.blockers)})}})},fetch:function(e,i,s,l){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.");x.has(e)&&ue(e);let c=f(a||o,s,r.basename);if(!c)return void ae(e,i,ce(404,{pathname:s}));let{path:d,submission:u}=G(s,l,!0),h=Re(c,d);P=!0===(l&&l.preventScrollReset),u&&ye(u.formMethod)?async function(e,i,s,l,c,d){if(ee(),O.delete(e),!l.route.action){let t=ce(405,{method:d.formMethod,pathname:s,routeId:i});return void ae(e,i,t)}let u=D.fetchers.get(e),h=t({state:"submitting"},d,{data:u&&u.data," _hasFetcherDoneAnything ":!0});D.fetchers.set(e,h),I({fetchers:new Map(D.fetchers)});let p=new AbortController,m=re(r.history,s,p.signal,d);x.set(e,p);let g=await te("action",m,l,c,y.basename);if(m.signal.aborted)return void(x.get(e)===p&&x.delete(e));if(pe(g)){x.delete(e),j.add(e);let r=t({state:"loading"},d,{data:void 0," _hasFetcherDoneAnything ":!0});return D.fetchers.set(e,r),I({fetchers:new Map(D.fetchers)}),X(D,g,{isFetchActionRedirect:!0})}if(fe(g))return void ae(e,i,g.error);if(he(g))throw ce(400,{type:"defer-action"});let v=D.navigation.location||D.location,w=re(r.history,v,p.signal),A=a||o,R="idle"!==D.navigation.state?f(A,D.navigation.location,r.basename):D.matches;n(R,"Didn't find any matches after fetcher action");let P=++C;T.set(e,P);let S=t({state:"loading",data:g.data},d,{" _hasFetcherDoneAnything ":!0});D.fetchers.set(e,S);let[F,H]=Q(r.history,D,R,d,v,M,L,k,O,A,r.basename,{[l.route.id]:g.data},void 0);H.filter((t=>t.key!==e)).forEach((e=>{let t=e.key,r=D.fetchers.get(t),a={state:"loading",data:r&&r.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};D.fetchers.set(t,a),x.set(t,p)})),I({fetchers:new Map(D.fetchers)});let{results:W,loaderResults:$,fetcherResults:N}=await Z(D.matches,R,F,H,w);if(p.signal.aborted)return;T.delete(e),x.delete(e),H.forEach((e=>x.delete(e.key)));let B=de(W);if(B)return X(D,B);let{loaderData:z,errors:K}=oe(D,D.matches,F,$,void 0,H,N,_),Y={state:"idle",data:g.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};D.fetchers.set(e,Y);let J=ge(P);"loading"===D.navigation.state&&P>U?(n(E,"Expected pending action"),b&&b.abort(),q(D.navigation.location,{matches:R,loaderData:z,errors:K,fetchers:new Map(D.fetchers)})):(I(t({errors:K,loaderData:ie(D.loaderData,z,R,K)},J?{fetchers:new Map(D.fetchers)}:{})),M=!1)}(e,i,d,h,c,u):(O.set(e,{routeId:i,path:d}),async function(e,a,o,i,s,l){let c=D.fetchers.get(e),d=t({state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},l,{data:c&&c.data," _hasFetcherDoneAnything ":!0});D.fetchers.set(e,d),I({fetchers:new Map(D.fetchers)});let u=new AbortController,h=re(r.history,o,u.signal);x.set(e,u);let f=await te("loader",h,i,s,y.basename);he(f)&&(f=await we(f,h.signal,!0)||f);x.get(e)===u&&x.delete(e);if(h.signal.aborted)return;if(pe(f))return void await X(D,f);if(fe(f)){let t=se(D.matches,a);return D.fetchers.delete(e),void I({fetchers:new Map(D.fetchers),errors:{[t.route.id]:f.error}})}n(!he(f),"Unhandled fetcher deferred data");let p={state:"idle",data:f.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};D.fetchers.set(e,p),I({fetchers:new Map(D.fetchers)})}(e,i,d,h,c,u))},revalidate:function(){ee(),I({revalidation:"loading"}),"submitting"!==D.navigation.state&&("idle"!==D.navigation.state?W(E||D.historyAction,D.navigation.location,{overrideNavigation:D.navigation}):W(D.historyAction,D.location,{startUninterruptedRevalidation:!0}))},createHref:e=>r.history.createHref(e),encodeLocation:e=>r.history.encodeLocation(e),getFetcher:V,deleteFetcher:ne,dispose:function(){i&&i(),l.clear(),b&&b.abort(),D.fetchers.forEach(((e,t)=>ne(t))),D.blockers.forEach(((e,t)=>ve(t)))},getBlocker:function(e,t){let r=D.blockers.get(e)||z;return F.get(e)!==t&&F.set(e,t),r},deleteBlocker:ve,_internalFetchControllers:x,_internalActiveDeferreds:_,_internalSetRoutes:function(e){a=e}},y},e.createStaticHandler=function(e,r){n(e.length>0,"You must provide a non-empty routes array to createStaticHandler");let a=h(e),o=(r?r.basename:null)||"/";async function i(e,r,a,i,s){n(e.signal,"query()/queryRoute() requests must contain an AbortController signal");try{if(ye(e.method.toLowerCase())){let n=await async function(e,r,a,n,i){let s;if(a.route.action){if(s=await te("action",e,a,r,o,!0,i,n),e.signal.aborted){throw new Error((i?"queryRoute":"query")+"() call aborted")}}else{let t=ce(405,{method:e.method,pathname:new URL(e.url).pathname,routeId:a.route.id});if(i)throw t;s={type:u.error,error:t}}if(pe(s))throw new Response(null,{status:s.status,headers:{Location:s.location}});if(he(s)){let e=ce(400,{type:"defer-action"});if(i)throw e;s={type:u.error,error:e}}if(i){if(fe(s))throw s.error;return{matches:[a],loaderData:{},actionData:{[a.route.id]:s.data},errors:null,statusCode:200,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(fe(s)){let o=se(r,a.route.id);return t({},await c(e,r,n,void 0,{[o.route.id]:s.error}),{statusCode:_(s.error)?s.error.status:500,actionData:null,actionHeaders:t({},s.headers?{[a.route.id]:s.headers}:{})})}let l=new Request(e.url,{headers:e.headers,redirect:e.redirect,signal:e.signal});return t({},await c(l,r,n),s.statusCode?{statusCode:s.statusCode}:{},{actionData:{[a.route.id]:s.data},actionHeaders:t({},s.headers?{[a.route.id]:s.headers}:{})})}(e,a,s||Re(a,r),i,null!=s);return n}let n=await c(e,a,i,s);return me(n)?n:t({},n,{actionData:null,actionHeaders:{}})}catch(e){if((l=e)&&me(l.response)&&(l.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 l}async function c(e,r,a,n,i){let s=null!=n;if(s&&(null==n||!n.route.loader))throw ce(400,{method:e.method,pathname:new URL(e.url).pathname,routeId:null==n?void 0:n.route.id});let l=(n?[n]:X(r,Object.keys(i||{})[0])).filter((e=>e.route.loader));if(0===l.length)return{matches:r,loaderData:r.reduce(((e,t)=>Object.assign(e,{[t.route.id]:null})),{}),errors:i||null,statusCode:200,loaderHeaders:{},activeDeferreds:null};let c=await Promise.all([...l.map((t=>te("loader",e,t,r,o,!0,s,a)))]);if(e.signal.aborted){throw new Error((s?"queryRoute":"query")+"() call aborted")}let d=new Map,u=ne(r,l,c,i,d),h=new Set(l.map((e=>e.route.id)));return r.forEach((e=>{h.has(e.route.id)||(u.loaderData[e.route.id]=null)})),t({},u,{matches:r,activeDeferreds:d.size>0?Object.fromEntries(d.entries()):null})}return{dataRoutes:a,query:async function(e,r){let{requestContext:n}=void 0===r?{}:r,c=new URL(e.url),d=e.method.toLowerCase(),u=s("",l(c),null,"default"),h=f(a,u,o);if(!ve(d)&&"head"!==d){let e=ce(405,{method:d}),{matches:t,route:r}=le(a);return{basename:o,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(!h){let e=ce(404,{pathname:u.pathname}),{matches:t,route:r}=le(a);return{basename:o,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}let p=await i(e,u,h,n);return me(p)?p:t({location:u,basename:o},p)},queryRoute:async function(e,t){let{routeId:r,requestContext:n}=void 0===t?{}:t,c=new URL(e.url),d=e.method.toLowerCase(),u=s("",l(c),null,"default"),h=f(a,u,o);if(!ve(d)&&"head"!==d&&"options"!==d)throw ce(405,{method:d});if(!h)throw ce(404,{pathname:u.pathname});let p=r?h.find((e=>e.route.id===r)):Re(h,u);if(r&&!p)throw ce(403,{pathname:u.pathname,routeId:r});if(!p)throw ce(404,{pathname:u.pathname});let m=await i(e,u,h,n,p);if(me(m))return m;let g=m.errors?Object.values(m.errors)[0]:void 0;if(void 0!==g)throw g;if(m.actionData)return Object.values(m.actionData)[0];if(m.loaderData){var v;let e=Object.values(m.loaderData)[0];return null!=(v=m.activeDeferreds)&&v[p.route.id]&&(e[V]=m.activeDeferreds[p.route.id]),e}}}},e.defer=function(e,t){return void 0===t&&(t={}),new T(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("/*")&&(R(!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.replace(/^:(\w+)(\??)/g,((e,r,a)=>{let o=t[r];return"?"===a?null==o?"":o:(null==o&&n(!1,'Missing ":'+r+'" param'),o)})).replace(/\/:(\w+)(\??)/g,((e,r,a)=>{let o=t[r];return"?"===a?null==o?"":"/"+o:(null==o&&n(!1,'Missing ":'+r+'" param'),"/"+o)})).replace(/\?/g,"").replace(/(\/?)\*/,((e,r,a,n)=>null==t["*"]?"/*"===n?"/":"":""+r+t["*"]))},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,n=new Headers(a.headers);return n.has("Content-Type")||n.set("Content-Type","application/json; charset=utf-8"),new Response(JSON.stringify(e),t({},a,{headers:n}))},e.matchPath=w,e.matchRoutes=f,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 n=new Headers(a.headers);return n.set("Location",e),new Response(null,t({},a,{headers:n}))},e.resolvePath=E,e.resolveTo=M,e.stripBasename=A,e.warning=R,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 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)n=D(o[e],E(a));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:k(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 d=l[r];return e[a]=o&&!d?void 0: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}}(d||"",a),e}),{}),pathname:i,pathnameBase:s,pattern:e}}function E(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 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:_(a),hash:T(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,"/"),k=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),_=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",T=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";class U extends Error{}class O{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,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 U)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]:C(a)})}),{})}get pendingKeys(){return Array.from(this.pendingKeysSet)}}function C(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}const B=["post","put","patch","delete"],N=new Set(B),F=["get",...B],W=new Set(F),q=new Set([301,302,303,307,308]),$=new Set([307,308]),K={state:"idle",location:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},Y={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0,json:void 0,text:void 0},J={state:"unblocked",proceed:void 0,reset:void 0,location:void 0},V=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,X=e=>({hasErrorBoundary:Boolean(e.hasErrorBoundary)}),G="remix-router-transitions";const Q=Symbol("deferred");function Z(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 ee(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||_e(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 te(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&&!Ae(a.formMethod))return{path:r,error:be(405,{method:a.formMethod})};let n,i,s=()=>({path:r,error:be(400,{type:"invalid-body"})}),u=a.formMethod||"get",c=e?u.toUpperCase():u.toLowerCase(),h=De(r);if(void 0!==a.body){if("text/plain"===a.formEncType){if(!Me(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(!Me(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=he(a.formData),i=a.formData;else if(a.body instanceof FormData)n=he(a.body),i=a.body;else if(a.body instanceof URLSearchParams)n=a.body,i=fe(n);else if(null==a.body)n=new URLSearchParams,i=new FormData;else try{n=new URLSearchParams(a.body),i=fe(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(Me(f.formMethod))return{path:r,submission:f};let p=d(r);return t&&p.search&&_e(p.search)&&n.append("index",""),p.search="?"+n,{path:l(p),submission:f}}function re(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 ae(e,r,a,o,n,i,s,l,d,u,c,h,f,m,y,v){let g=v?Object.values(v)[0]:y?Object.values(y)[0]:void 0,b=e.createURL(r.location),w=e.createURL(n),D=v?Object.keys(v)[0]:void 0,S=re(a,D).filter(((e,a)=>{let{route:n}=e;if(n.lazy)return!0;if(null==n.loader)return!1;if(i)return!!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)||l.some((t=>t===e.route.id)))return!0;let d=r.matches[a],u=e;return ne(e,t({currentUrl:b,currentParams:d.params,nextUrl:w,nextParams:u.params},o,{actionResult:g,defaultShouldRevalidate:s||b.pathname+b.search===w.pathname+w.search||b.search!==w.search||oe(d,u)}))})),E=[];return c.forEach(((e,n)=>{if(i||!a.some((t=>t.route.id===e.routeId))||u.has(n))return;let l=p(f,e.path,m);if(!l)return void E.push({key:n,routeId:e.routeId,path:e.path,matches:null,match:null,controller:null});let c=r.fetchers.get(n),y=Te(l,e.path),v=!1;v=!h.has(n)&&(!!d.includes(n)||(c&&"idle"!==c.state&&void 0===c.data?s:ne(y,t({currentUrl:b,currentParams:r.matches[r.matches.length-1].params,nextUrl:w,nextParams:a[a.length-1].params},o,{actionResult:g,defaultShouldRevalidate:s})))),v&&E.push({key:n,routeId:e.routeId,path:e.path,matches:l,match:y,controller:new AbortController})})),[S,E]}function oe(e,t){let r=e.route.path;return e.pathname!==t.pathname||null!=r&&r.endsWith("*")&&e.params["*"]!==t.params["*"]}function ne(e,t){if(e.route.shouldRevalidate){let r=e.route.shouldRevalidate(t);if("boolean"==typeof r)return r}return t.defaultShouldRevalidate}async function ie(e,r,a){if(!e.lazy)return e;let i=await e.lazy();if(!e.lazy)return e;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])}return Object.assign(s,l),Object.assign(s,t({},r(s),{lazy:void 0})),s}function se(e){return Promise.all(e.matches.map((e=>e.bikeshed_loadRoute())))}async function le(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=>t({},e,{bikeshed_loadRoute:t=>(h.add(e.route.id),u.has(e.route.id)?async function(e,t,r,a,n,i,s){let l,d,u=e=>{let a,o=new Promise(((e,t)=>a=t));d=()=>a(),t.signal.addEventListener("abort",d);let n={request:t,params:r.params,context:s},l=i?i((async t=>void 0!==t?e(n,t):e(n))):e(n);return Promise.race([l,o])};try{let i=r.route[e];if(r.route.lazy)if(i){let e,t=await Promise.all([u(i).catch((t=>{e=t})),ie(r.route,n,a)]);if(e)throw e;l=t[0]}else{if(await ie(r.route,n,a),i=r.route[e],!i){if("action"===e){let e=new URL(t.url),a=e.pathname+e.search;throw be(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 be(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.bikeshed_loadRoute()` was not called for route id "'+e.route.id+'". You must call `match.bikeshed_loadRoute()` 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 de(e){let{result:t,type:r}=e;if(Le(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),response:t}:{type:c.data,data:e,response:t}}return r===c.error?{type:r,error:t}:xe(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 ue(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"),!V.test(s)){let o=a.slice(0,a.findIndex((e=>e.route.id===r))+1);s=ee(new URL(t.url),o,n,!0,s,i),e.headers.set("Location",s)}return e}function ce(e,t,r,a){let o=e.createURL(De(t)).toString(),n={signal:r};if(a&&Me(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=he(a.formData):n.body=a.formData}return new Request(o,n)}function he(e){let t=new URLSearchParams;for(let[r,a]of e.entries())t.append(r,"string"==typeof a?a:a.name);return t}function fe(e){let t=new FormData;for(let[r,a]of e.entries())t.append(r,a);return t}function pe(e,t,r,a,n){let i,s={},l=null,d=!1,u={};return r.forEach(((r,c)=>{let h=t[c].route.id;if(o(!Pe(r),"Cannot handle redirect results in processLoaderData"),Re(r)){let t=ve(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,d||(d=!0,i=z(r.error)?r.error.status:500),r.response&&(u[h]=r.response.headers)}else Ee(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.response&&(200===r.response.status||d||(i=r.response.status),u[h]=r.response.headers))})),a&&(l=a,s[Object.keys(a)[0]]=void 0),{loaderData:s,errors:l,statusCode:i||200,loaderHeaders:u}}function me(e,r,a,n,i,s,l,d){let{loaderData:u,errors:c}=pe(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(Re(d)){let r=ve(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(Pe(d))o(!1,"Unhandled fetcher revalidation redirect");else if(Ee(d))o(!1,"Unhandled fetcher deferred data");else{let t=Ie(d.data);e.fetchers.set(a,t)}}return{loaderData:u,errors:c}}function ye(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 ve(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 ge(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 be(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 we(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(Pe(r))return{result:r,idx:t}}}function De(e){return l(t({},"string"==typeof e?d(e):e,{hash:""}))}function Se(e){return Le(e.result)&&q.has(e.result.status)}function Ee(e){return e.type===c.deferred}function Re(e){return e.type===c.error}function Pe(e){return(e&&e.type)===c.redirect}function xe(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 Le(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"object"==typeof e.headers&&void 0!==e.body}function Ae(e){return W.has(e.toLowerCase())}function Me(e){return N.has(e.toLowerCase())}async function je(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&&!oe(u,d)&&void 0!==(i&&i[d.route.id]);if(Ee(l)&&(n||c)){let e=a[s];o(e,"Expected an AbortSignal for revalidating fetcher deferred result"),await ke(l,e,n).then((e=>{e&&(r[s]=e||r[s])}))}}}async function ke(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 _e(e){return new URLSearchParams(e).getAll("index").some((e=>""===e))}function Te(e,t){let r="string"==typeof t?d(t).search:t.search;if(e[e.length-1].route.index&&_e(r||""))return e[e.length-1];let a=L(e);return a[a.length-1]}function Ue(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 Oe(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 Ce(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 He(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 Ie(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=U,e.Action=r,e.IDLE_BLOCKER=J,e.IDLE_FETCHER=Y,e.IDLE_NAVIGATION=K,e.UNSAFE_DEFERRED_SYMBOL=Q,e.UNSAFE_DeferredData=O,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=X;let u,h,y={},v=f(e.routes,d,void 0,y),g=e.basename||"/",b=e.unstable_dataStrategy||se,w=t({v7_fetcherPersist:!1,v7_normalizeFormMethod:!1,v7_partialHydration:!1,v7_prependBasename:!1,v7_relativeSplatPath:!1},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=be(404,{pathname:e.history.location.pathname}),{matches:r,route:a}=ge(v);A=r,M={[a.id]:t}}let j,k=A.some((e=>e.route.lazy)),_=A.some((e=>e.route.loader));if(k)h=!1;else if(_)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&&!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 T,U={historyAction:e.history.action,location:e.history.location,matches:A,initialized:h,navigation:K,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},O=r.Pop,C=!1,H=!1,I=new Map,z=null,B=!1,N=!1,F=[],W=[],q=new Map,Q=0,Z=-1,re=new Map,oe=new Set,ne=new Map,ie=new Map,he=new Set,fe=new Map,pe=new Map,De=!1;function xe(e,r){void 0===r&&(r={}),U=t({},U,e);let a=[],o=[];w.v7_fetcherPersist&&U.fetchers.forEach(((e,t)=>{"idle"===e.state&&(he.has(t)?o.push(t):a.push(t))})),[...S].forEach((e=>e(U,{deletedFetchers:o,unstable_viewTransitionOpts:r.viewTransitionOpts,unstable_flushSync:!0===r.flushSync}))),w.v7_fetcherPersist&&(a.forEach((e=>U.fetchers.delete(e))),o.forEach((e=>$e(e))))}function Le(a,o,n){var i,s;let l,{flushSync:d}=void 0===n?{}:n,c=null!=U.actionData&&null!=U.navigation.formMethod&&Me(U.navigation.formMethod)&&"loading"===U.navigation.state&&!0!==(null==(i=a.state)?void 0:i._isRedirect);l=o.actionData?Object.keys(o.actionData).length>0?o.actionData:null:c?U.actionData:null;let h=o.loaderData?ye(U.loaderData,o.loaderData,o.matches||[],o.errors):U.loaderData,f=U.blockers;f.size>0&&(f=new Map(f),f.forEach(((e,t)=>f.set(t,J))));let p,m=!0===C||null!=U.navigation.formMethod&&Me(U.navigation.formMethod)&&!0!==(null==(s=a.state)?void 0:s._isRedirect);if(u&&(v=u,u=void 0),B||O===r.Pop||(O===r.Push?e.history.push(a,a.state):O===r.Replace&&e.history.replace(a,a.state)),O===r.Pop){let e=I.get(U.location.pathname);e&&e.has(a.pathname)?p={currentLocation:U.location,nextLocation:a}:I.has(a.pathname)&&(p={currentLocation:a,nextLocation:U.location})}else if(H){let e=I.get(U.location.pathname);e?e.add(a.pathname):(e=new Set([a.pathname]),I.set(U.location.pathname,e)),p={currentLocation:U.location,nextLocation:a}}xe(t({},o,{actionData:l,loaderData:h,historyAction:O,location:a,initialized:!0,navigation:K,revalidation:"idle",restoreScrollPosition:tt(a,o.matches||U.matches),preventScrollReset:m,blockers:f}),{viewTransitionOpts:p,flushSync:!0===d}),O=r.Pop,C=!1,H=!1,B=!1,N=!1,F=[],W=[]}async function Ae(a,o,n){T&&T.abort(),T=null,O=a,B=!0===(n&&n.startUninterruptedRevalidation),function(e,t){if(E&&x){let r=et(e,t);E[r]=x()}}(U.location,U.matches),C=!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=be(404,{pathname:o.pathname}),{matches:t,route:r}=ge(i);return Ze(),void Le(o,{matches:t,loaderData:{},errors:{[r.id]:e}},{flushSync:d})}if(U.initialized&&!N&&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}(U.location,o)&&!(n&&n.submission&&Me(n.submission.formMethod)))return void Le(o,{matches:l},{flushSync:d});T=new AbortController;let h,f,m=ce(e.history,o,T.signal,n&&n.submission);if(n&&n.pendingError)f={[ve(l).route.id]:n.pendingError};else if(n&&n.submission&&Me(n.submission.formMethod)){let e=await async function(e,t,a,o,n){void 0===n&&(n={});let i;Ne(),xe({navigation:Ce(t,a)},{flushSync:!0===n.flushSync});let s=Te(o,t);if(s.route.action||s.route.lazy){if(i=(await ze("action",e,[s],o))[0],e.signal.aborted)return{shortCircuited:!0}}else i={type:c.error,error:be(405,{method:e.method,pathname:t.pathname,routeId:s.route.id})};if(Pe(i)){let t;return t=n&&null!=n.replace?n.replace:i.response.headers.get("Location")===U.location.pathname+U.location.search,await _e(e,i,{submission:a,replace:t}),{shortCircuited:!0}}if(Re(i)){let e=ve(o,s.route.id);return!0!==(n&&n.replace)&&(O=r.Push),{pendingActionData:{},pendingActionError:{[e.route.id]:i.error}}}if(Ee(i))throw be(400,{type:"defer-action"});return{pendingActionData:{[s.route.id]:i.data}}}(m,o,n.submission,l,{replace:n.replace,flushSync:d});if(e.shortCircuited)return;h=e.pendingActionData,f=e.pendingActionError,s=Oe(o,n.submission),d=!1,m=new Request(m.url,{signal:m.signal})}let{shortCircuited:y,loaderData:b,errors:D}=await async function(r,a,o,n,i,s,l,d,c,h,f){let p=n||Oe(a,i),m=i||s||Ue(p),y=u||v,[b,D]=ae(e.history,U,o,m,a,w.v7_partialHydration&&!0===d,N,F,W,he,ne,oe,y,g,h,f);if(Ze((e=>!(o&&o.some((t=>t.route.id===e)))||b&&b.some((t=>t.route.id===e)))),Z=++Q,0===b.length&&0===D.length){let e=Je();return Le(a,t({matches:o,loaderData:{},errors:f||null},h?{actionData:h}:{},e?{fetchers:new Map(U.fetchers)}:{}),{flushSync:c}),{shortCircuited:!0}}if(!(B||w.v7_partialHydration&&d)){D.forEach((e=>{let t=U.fetchers.get(e.key),r=He(void 0,t?t.data:void 0);U.fetchers.set(e.key,r)}));let e=h||U.actionData;xe(t({navigation:p},e?0===Object.keys(e).length?{actionData:null}:{actionData:e}:{},D.length>0?{fetchers:new Map(U.fetchers)}:{}),{flushSync:c})}D.forEach((e=>{q.has(e.key)&&Ke(e.key),e.controller&&q.set(e.key,e.controller)}));let S=()=>D.forEach((e=>Ke(e.key)));T&&T.signal.addEventListener("abort",S);let{loaderResults:E,fetcherResults:R}=await Be(U.matches,o,b,D,r);if(r.signal.aborted)return{shortCircuited:!0};T&&T.signal.removeEventListener("abort",S);D.forEach((e=>q.delete(e.key)));let P=we([...E,...R]);if(P){if(P.idx>=b.length){let e=D[P.idx-b.length].key;oe.add(e)}return await _e(r,P.result,{replace:l}),{shortCircuited:!0}}let{loaderData:x,errors:L}=me(U,o,b,E,f,D,R,fe);fe.forEach(((e,t)=>{e.subscribe((r=>{(r||e.done)&&fe.delete(t)}))}));let A=Je(),M=Ve(Z),j=A||M||D.length>0;return t({loaderData:x,errors:L},j?{fetchers:new Map(U.fetchers)}:{})}(m,o,l,s,n&&n.submission,n&&n.fetcherSubmission,n&&n.replace,n&&!0===n.initialHydration,d,h,f);y||(T=null,Le(o,t({matches:l},h?{actionData:h}:{},{loaderData:b,errors:D})))}async function _e(n,l,d){let{submission:u,fetcherSubmission:c,replace:h}=void 0===d?{}:d;l.response.headers.has("X-Remix-Revalidate")&&(N=!0);let f=l.response.headers.get("Location");o(f,"Expected a Location header on the redirect Response");let p=s(U.location,f,{_isRedirect:!0});if(V.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(U.location,e,{_isRedirect:!0}))}if(i){let t=!1;if(l.response.headers.has("X-Remix-Reload-Document"))t=!0;else if(V.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))}T=null;let m=!0===h?r.Replace:r.Push,{formMethod:y,formAction:v,formEncType:b}=U.navigation;!u&&!c&&y&&v&&b&&(u=Ue(U.navigation));let w=u||c;if($.has(l.response.status)&&w&&Me(w.formMethod))await Ae(m,p,{submission:t({},w,{formAction:f}),preventScrollReset:C});else{let e=Oe(p,u);await Ae(m,p,{overrideNavigation:e,fetcherSubmission:c,preventScrollReset:C})}}async function ze(e,t,r,a){try{let o=await le(b,e,t,r,a,y,d);return await Promise.all(o.map(((e,o)=>Se(e)?{type:c.redirect,response:ue(e.result,t,r[o].route.id,a,g,w.v7_relativeSplatPath)}:de(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?ze("loader",n,a,r):[],...o.map((t=>{if(t.matches&&t.match&&t.controller){return ze("loader",ce(e.history,t.path,t.controller.signal),[t.match],t.matches).then((e=>e[0]))}return Promise.resolve({type:c.error,error:be(404,{pathname:t.path})})}))]);return await Promise.all([je(t,a,i,i.map((()=>n.signal)),!1,U.loaderData),je(t,o.map((e=>e.match)),s,o.map((e=>e.controller?e.controller.signal:null)),!0)]),{loaderResults:i,fetcherResults:s}}function Ne(){N=!0,F.push(...Ze()),ne.forEach(((e,t)=>{q.has(t)&&(W.push(t),Ke(t))}))}function Fe(e,t,r){void 0===r&&(r={}),U.fetchers.set(e,t),xe({fetchers:new Map(U.fetchers)},{flushSync:!0===(r&&r.flushSync)})}function We(e,t,r,a){void 0===a&&(a={});let o=ve(U.matches,t);$e(e),xe({errors:{[o.route.id]:r},fetchers:new Map(U.fetchers)},{flushSync:!0===(a&&a.flushSync)})}function qe(e){return w.v7_fetcherPersist&&(ie.set(e,(ie.get(e)||0)+1),he.has(e)&&he.delete(e)),U.fetchers.get(e)||Y}function $e(e){let t=U.fetchers.get(e);!q.has(e)||t&&"loading"===t.state&&re.has(e)||Ke(e),ne.delete(e),re.delete(e),oe.delete(e),he.delete(e),U.fetchers.delete(e)}function Ke(e){let t=q.get(e);o(t,"Expected fetch controller: "+e),t.abort(),q.delete(e)}function Ye(e){for(let t of e){let e=Ie(qe(t).data);U.fetchers.set(t,e)}}function Je(){let e=[],t=!1;for(let r of oe){let a=U.fetchers.get(r);o(a,"Expected fetcher: "+r),"loading"===a.state&&(oe.delete(r),e.push(r),t=!0)}return Ye(e),t}function Ve(e){let t=[];for(let[r,a]of re)if(a<e){let e=U.fetchers.get(r);o(e,"Expected fetcher: "+r),"loading"===e.state&&(Ke(r),re.delete(r),t.push(r))}return Ye(t),t.length>0}function Xe(e){U.blockers.delete(e),pe.delete(e)}function Ge(e,t){let r=U.blockers.get(e)||J;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(U.blockers);a.set(e,t),xe({blockers:a})}function Qe(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=U.blockers.get(i);return l&&"proceeding"===l.state?void 0:s({currentLocation:t,nextLocation:r,historyAction:a})?i:void 0}function Ze(e){let t=[];return fe.forEach(((r,a)=>{e&&!e(a)||(r.cancel(),t.push(a),fe.delete(a))})),t}function et(e,t){if(P){return P(e,t.map((e=>m(e,U.loaderData))))||e.key}return e.key}function tt(e,t){if(E){let r=et(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 U},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(De)return void(De=!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=Qe({currentLocation:U.location,nextLocation:a,historyAction:r});return i&&null!=o?(De=!0,e.history.go(-1*o),void Ge(i,{state:"blocked",location:a,proceed(){Ge(i,{state:"proceeding",proceed:void 0,reset:void 0,location:a}),e.history.go(o)},reset(){let e=new Map(U.blockers);e.set(i,J),xe({blockers:e})}})):Ae(r,a)})),i){!function(e,t){try{let r=e.sessionStorage.getItem(G);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(G,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 U.initialized||Ae(r.Pop,U.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&&U.navigation===K){L=!0;let e=tt(U.location,U.matches);null!=e&&xe({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=ee(U.location,U.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}=te(w.v7_normalizeFormMethod,!1,i,n),c=U.location,h=s(U.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&&Me(d.formMethod)&&d.formAction===U.location.pathname+U.location.search&&(p=r.Replace);let m=n&&"preventScrollReset"in n?!0===n.preventScrollReset:void 0,y=!0===(n&&n.unstable_flushSync),v=Qe({currentLocation:c,nextLocation:h,historyAction:p});if(!v)return await Ae(p,h,{submission:d,pendingError:u,preventScrollReset:m,replace:n&&n.replace,enableViewTransition:n&&n.unstable_viewTransition,flushSync:y});Ge(v,{state:"blocked",location:h,proceed(){Ge(v,{state:"proceeding",proceed:void 0,reset:void 0,location:h}),a(o,n)},reset(){let e=new Map(U.blockers);e.set(v,J),xe({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.");q.has(t)&&Ke(t);let i=!0===(n&&n.unstable_flushSync),s=u||v,d=ee(U.location,U.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 We(t,r,be(404,{pathname:d}),{flushSync:i});let{path:h,submission:f,error:m}=te(w.v7_normalizeFormMethod,!0,d,n);if(m)return void We(t,r,m,{flushSync:i});let y=Te(c,h);C=!0===(n&&n.preventScrollReset),f&&Me(f.formMethod)?async function(t,r,a,n,i,s,l){if(Ne(),ne.delete(t),!n.route.action&&!n.route.lazy){let e=be(405,{method:l.formMethod,pathname:a,routeId:r});return void We(t,r,e,{flushSync:s})}let d=U.fetchers.get(t);Fe(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=ce(e.history,a,c.signal,l);q.set(t,c);let f=Q,m=(await ze("action",h,[n],i))[0];if(h.signal.aborted)return void(q.get(t)===c&&q.delete(t));if(w.v7_fetcherPersist&&he.has(t)){if(Pe(m)||Re(m))return void Fe(t,Ie(void 0))}else{if(Pe(m))return q.delete(t),Z>f?void Fe(t,Ie(void 0)):(oe.add(t),Fe(t,He(l)),_e(h,m,{fetcherSubmission:l}));if(Re(m))return void We(t,r,m.error)}if(Ee(m))throw be(400,{type:"defer-action"});let y=U.navigation.location||U.location,b=ce(e.history,y,c.signal),D=u||v,S="idle"!==U.navigation.state?p(D,U.navigation.location,g):U.matches;o(S,"Didn't find any matches after fetcher action");let E=++Q;re.set(t,E);let R=He(l,m.data);U.fetchers.set(t,R);let[P,x]=ae(e.history,U,S,l,y,!1,N,F,W,he,ne,oe,D,g,{[n.route.id]:m.data},void 0);x.filter((e=>e.key!==t)).forEach((e=>{let t=e.key,r=U.fetchers.get(t),a=He(void 0,r?r.data:void 0);U.fetchers.set(t,a),q.has(t)&&Ke(t),e.controller&&q.set(t,e.controller)})),xe({fetchers:new Map(U.fetchers)});let L=()=>x.forEach((e=>Ke(e.key)));c.signal.addEventListener("abort",L);let{loaderResults:A,fetcherResults:M}=await Be(U.matches,S,P,x,b);if(c.signal.aborted)return;c.signal.removeEventListener("abort",L),re.delete(t),q.delete(t),x.forEach((e=>q.delete(e.key)));let j=we([...A,...M]);if(j){if(j.idx>=P.length){let e=x[j.idx-P.length].key;oe.add(e)}return _e(b,j.result)}let{loaderData:k,errors:_}=me(U,U.matches,P,A,void 0,x,M,fe);if(U.fetchers.has(t)){let e=Ie(m.data);U.fetchers.set(t,e)}Ve(E),"loading"===U.navigation.state&&E>Z?(o(O,"Expected pending action"),T&&T.abort(),Le(U.navigation.location,{matches:S,loaderData:k,errors:_,fetchers:new Map(U.fetchers)})):(xe({errors:_,loaderData:ye(U.loaderData,k,S,_),fetchers:new Map(U.fetchers)}),N=!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=U.fetchers.get(t);Fe(t,He(l,d?d.data:void 0),{flushSync:s});let u=new AbortController,c=ce(e.history,a,u.signal);q.set(t,u);let h=Q,f=(await ze("loader",c,[n],i))[0];Ee(f)&&(f=await ke(f,c.signal,!0)||f);q.get(t)===u&&q.delete(t);if(c.signal.aborted)return;if(he.has(t))return void Fe(t,Ie(void 0));if(Pe(f))return Z>h?void Fe(t,Ie(void 0)):(oe.add(t),void await _e(c,f));if(Re(f))return void We(t,r,f.error);o(!Ee(f),"Unhandled fetcher deferred data"),Fe(t,Ie(f.data))}(t,r,h,y,c,i,f))},revalidate:function(){Ne(),xe({revalidation:"loading"}),"submitting"!==U.navigation.state&&("idle"!==U.navigation.state?Ae(O||U.historyAction,U.navigation.location,{overrideNavigation:U.navigation}):Ae(U.historyAction,U.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),he.add(e)):ie.set(e,t)}else $e(e);xe({fetchers:new Map(U.fetchers)})},dispose:function(){D&&D(),z&&z(),S.clear(),T&&T.abort(),U.fetchers.forEach(((e,t)=>$e(t))),U.blockers.forEach(((e,t)=>Xe(t)))},getBlocker:function(e,t){let r=U.blockers.get(e)||J;return pe.get(e)!==t&&pe.set(e,t),r},deleteBlocker:Xe,_internalFetchControllers:q,_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)||se;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=X;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){o(e.signal,"query()/queryRoute() requests must contain an AbortController signal");try{if(Me(e.method.toLowerCase())){let o=await async function(e,r,a,o,n){let i;if(a.route.action||a.route.lazy){i=(await v("action",e,[a],r,n,o))[0],e.signal.aborted&&Z(e,n,u)}else{let t=be(405,{method:e.method,pathname:new URL(e.url).pathname,routeId:a.route.id});if(n)throw t;i={type:c.error,error:t}}if(Pe(i))throw new Response(null,{status:i.response.status,headers:{Location:i.response.headers.get("Location")}});if(Ee(i)){let e=be(400,{type:"defer-action"});if(n)throw e;i={type:c.error,error:e}}if(n){if(Re(i))throw i.error;return{matches:[a],loaderData:{},actionData:{[a.route.id]:i.data},errors:null,statusCode:200,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(Re(i)){let n=ve(r,a.route.id);return t({},await y(e,r,o,void 0,{[n.route.id]:i.error}),{statusCode:z(i.error)?i.error.status:500,actionData:null,actionHeaders:t({},i.response?{[a.route.id]:i.response.headers}:{})})}let s=new Request(e.url,{headers:e.headers,redirect:e.redirect,signal:e.signal});return t({},await y(s,r,o),{actionData:{[a.route.id]:i.data}},i.response?{statusCode:i.response.status,actionHeaders:{[a.route.id]:i.response.headers}}:{actionHeaders:{}})}(e,a,i||Te(a,r),n,null!=i);return o}let o=await y(e,a,n,i);return Le(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)&&Le(e.result)){if(e.type===c.error)throw e.result;return e.result}if(function(e){if(!Le(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){let i=null!=o;if(i&&(null==o||!o.route.loader)&&(null==o||!o.route.lazy))throw be(400,{method:e.method,pathname:new URL(e.url).pathname,routeId:null==o?void 0:o.route.id});let s=(o?[o]:re(r,Object.keys(n||{})[0])).filter((e=>e.route.loader||e.route.lazy));if(0===s.length)return{matches:r,loaderData:r.reduce(((e,t)=>Object.assign(e,{[t.route.id]:null})),{}),errors:n||null,statusCode:200,loaderHeaders:{},activeDeferreds:null};let l=await v("loader",e,s,r,i,a);e.signal.aborted&&Z(e,i,u);let d=new Map,c=pe(r,s,l,n,d),h=new Set(s.map((e=>e.route.id)));return r.forEach((e=>{h.has(e.route.id)||(c.loaderData[e.route.id]=null)})),t({},c,{matches:r,activeDeferreds:d.size>0?Object.fromEntries(d.entries()):null})}async function v(e,t,r,o,s,l){let c=await le(d,e,t,r,o,n,a,l);return await Promise.all(c.map(((e,a)=>{if(Se(e))throw ue(e.result,t,r[a].route.id,o,i,u.v7_relativeSplatPath);if(Le(e.result)&&s)throw e;return de(e)})))}return{dataRoutes:h,query:async function(e,r){let{requestContext:a}=void 0===r?{}:r,o=new URL(e.url),n=e.method,d=s("",l(o),null,"default"),u=p(h,d,i);if(!Ae(n)&&"HEAD"!==n){let e=be(405,{method:n}),{matches:t,route:r}=ge(h);return{basename:i,location:d,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(!u){let e=be(404,{pathname:d.pathname}),{matches:t,route:r}=ge(h);return{basename:i,location:d,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}let c=await m(e,d,u,a);return Le(c)?c:t({location:d,basename:i},c)},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(!Ae(n)&&"HEAD"!==n&&"OPTIONS"!==n)throw be(405,{method:n});if(!u)throw be(404,{pathname:d.pathname});let c=r?u.find((e=>e.route.id===r)):Te(u,d);if(r&&!c)throw be(403,{pathname:d.pathname,routeId:r});if(!c)throw be(404,{pathname:d.pathname});let f=await m(e,d,u,a,c);if(Le(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[Q]=f.activeDeferreds[c.route.id]),e}}}},e.defer=function(e,t){return void 0===t&&(t={}),new O(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=xe,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=k,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,Object.defineProperty(e,"__esModule",{value:!0})}));
//# sourceMappingURL=router.umd.min.js.map

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

data: any;
statusCode?: number;
headers?: Headers;
response?: Response;
}

@@ -38,5 +37,3 @@ /**

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

@@ -49,3 +46,3 @@ /**

error: any;
headers?: Headers;
response?: Response;
}

@@ -55,7 +52,39 @@ /**

*/
export declare type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
export declare type MutationFormMethod = "post" | "put" | "patch" | "delete";
export declare type FormMethod = "get" | MutationFormMethod;
export declare type FormEncType = "application/x-www-form-urlencoded" | "multipart/form-data";
export type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
/**
* Result from a loader or action called via dataStrategy
*/
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 type FormMethod = LowerCaseFormMethod;
export type MutationFormMethod = Exclude<FormMethod, "get">;
/**
* In v7, active navigation/fetcher form methods are exposed in uppercase on the
* RouterState. This is to align with the normalization done via fetch().
*/
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;
/**
* @private

@@ -65,8 +94,24 @@ * Internal interface to pass around for action submissions, not intended for

*/
export interface Submission {
formMethod: FormMethod;
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;
};
/**

@@ -77,6 +122,6 @@ * @private

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

@@ -86,3 +131,3 @@ /**

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

@@ -92,17 +137,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

@@ -115,19 +186,52 @@ * (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;
}
/**
* Function provided by the framework-aware layers to set `hasErrorBoundary`
* from the framework-aware `errorElement` prop
*
* @deprecated Use `mapRouteProperties` instead
*/
export interface DetectErrorBoundaryFunction {
(route: AgnosticRouteObject): boolean;
}
export interface DataStrategyMatch extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
bikeshed_loadRoute: (bikeshed_handlerOverride?: (bikeshed_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
* onto the route. Either they're meaningful to the router, or they'll get
* ignored.
*/
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>;
/**
* lazy() function to load a route definition, which can add non-matching
* related properties to a route
*/
export interface LazyRouteFunction<R extends AgnosticRouteObject> {
(): Promise<RequireOne<Omit<R, ImmutableRouteKey>>>;
}
/**
* Base RouteObject with common props shared by all types of routes
*/
declare type AgnosticBaseRouteObject = {
type AgnosticBaseRouteObject = {
caseSensitive?: boolean;

@@ -141,2 +245,3 @@ path?: string;

handle?: any;
lazy?: LazyRouteFunction<AgnosticBaseRouteObject>;
};

@@ -146,3 +251,3 @@ /**

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

@@ -154,3 +259,3 @@ index: true;

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

@@ -163,7 +268,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[];

@@ -175,4 +280,5 @@ id: string;

*/
export declare type AgnosticDataRouteObject = AgnosticDataIndexRouteObject | AgnosticDataNonIndexRouteObject;
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;
/**

@@ -187,4 +293,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>

@@ -195,3 +301,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;

@@ -222,3 +328,3 @@ };

}
export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], parentPath?: number[], allIds?: Set<string>): AgnosticDataRouteObject[];
export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], mapRouteProperties: MapRoutePropertiesFunction, parentPath?: number[], manifest?: RouteManifest): AgnosticDataRouteObject[];
/**

@@ -230,2 +336,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;
/**

@@ -292,6 +406,2 @@ * Returns a path with params interpolated.

/**
* @private
*/
export declare function warning(cond: any, message: string): void;
/**
* Returns a resolved path object relative to the given pathname.

@@ -326,2 +436,3 @@ *

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[];
/**

@@ -351,3 +462,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;
/**

@@ -385,5 +496,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;
/**

@@ -395,11 +506,26 @@ * 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);

@@ -406,0 +532,0 @@ }

@@ -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(

@@ -488,3 +502,3 @@ "",

function warning(cond: any, message: string) {
export function warning(cond: any, message: string) {
if (!cond) {

@@ -497,3 +511,3 @@ // eslint-disable-next-line no-console

//
// 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

@@ -643,2 +657,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

@@ -645,0 +666,0 @@ // way to warn them about it since the page will refresh...

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

AgnosticRouteObject,
TrackedPromise,
DataStrategyFunction,
DataStrategyFunctionArgs,
DataStrategyMatch,
ErrorResponse,
FormEncType,
FormMethod,
HTMLFormMethod,
JsonFunction,
LazyRouteFunction,
LoaderFunction,

@@ -22,6 +27,10 @@ LoaderFunctionArgs,

PathMatch,
PathParam,
PathPattern,
RedirectFunction,
ShouldRevalidateFunction,
Submission,
ShouldRevalidateFunctionArgs,
TrackedPromise,
UIMatch,
V7_FormMethod,
} from "./utils";

@@ -31,3 +40,2 @@

AbortedDeferredError,
ErrorResponse,
defer,

@@ -43,6 +51,6 @@ generatePath,

redirect,
redirectDocument,
resolvePath,
resolveTo,
stripBasename,
warning,
} from "./utils";

@@ -67,5 +75,5 @@

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

@@ -84,8 +92,14 @@ } from "./history";

/** @internal */
export type { RouteManifest as UNSAFE_RouteManifest } from "./utils";
export {
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";
export { invariant as UNSAFE_invariant } from "./history";
export {
invariant as UNSAFE_invariant,
warning as UNSAFE_warning,
} from "./history";
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-ba938b84",
"version": "0.0.0-experimental-bc2c864b",
"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 { invariant, parsePath } from "./history";
import { invariant, parsePath, warning } from "./history";

@@ -24,4 +24,3 @@ /**

data: any;
statusCode?: number;
headers?: Headers;
response?: Response;
}

@@ -44,5 +43,3 @@

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

@@ -56,3 +53,3 @@

error: any;
headers?: Headers;
response?: Response;
}

@@ -69,9 +66,47 @@

export type MutationFormMethod = "post" | "put" | "patch" | "delete";
export type FormMethod = "get" | MutationFormMethod;
/**
* 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";
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 type FormMethod = LowerCaseFormMethod;
export type MutationFormMethod = Exclude<FormMethod, "get">;
/**
* In v7, active navigation/fetcher form methods are exposed in uppercase on the
* RouterState. This is to align with the normalization done via fetch().
*/
export type V7_FormMethod = UpperCaseFormMethod;
export type V7_MutationFormMethod = Exclude<V7_FormMethod, "GET">;
export type FormEncType =
| "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;
/**

@@ -82,8 +117,27 @@ * @private

*/
export interface Submission {
formMethod: 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;
};

@@ -95,12 +149,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> {}

@@ -110,10 +169,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 };

@@ -123,7 +195,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

@@ -136,17 +229,82 @@ * (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;
}
/**
* Function provided by the framework-aware layers to set `hasErrorBoundary`
* from the framework-aware `errorElement` prop
*
* @deprecated Use `mapRouteProperties` instead
*/
export interface DetectErrorBoundaryFunction {
(route: AgnosticRouteObject): boolean;
}
export interface DataStrategyMatch
extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
// TODO: What to call these?
bikeshed_loadRoute: (
bikeshed_handlerOverride?: (
bikeshed_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
* onto the route. Either they're meaningful to the router, or they'll get
* ignored.
*/
export type ImmutableRouteKey =
| "lazy"
| "caseSensitive"
| "path"
| "id"
| "index"
| "children";
export const immutableRouteKeys = new Set<ImmutableRouteKey>([
"lazy",
"caseSensitive",
"path",
"id",
"index",
"children",
]);
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
>;
/**
* lazy() function to load a route definition, which can add non-matching
* related properties to a route
*/
export interface LazyRouteFunction<R extends AgnosticRouteObject> {
(): Promise<RequireOne<Omit<R, ImmutableRouteKey>>>;
}
/**
* Base RouteObject with common props shared by all types of routes

@@ -163,2 +321,3 @@ */

handle?: any;
lazy?: LazyRouteFunction<AgnosticBaseRouteObject>;
};

@@ -206,2 +365,4 @@

export type RouteManifest = Record<string, AgnosticDataRouteObject | undefined>;
// Recursive helper for finding path parameters in the absence of wildcards

@@ -229,5 +390,5 @@ type _PathParam<Path extends string> =

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

@@ -241,6 +402,6 @@ : // look for wildcard at the end of the path

// 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>;

@@ -289,8 +450,9 @@

// 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[],
mapRouteProperties: MapRoutePropertiesFunction,
parentPath: number[] = [],
allIds: Set<string> = new Set<string>()
manifest: RouteManifest = {}
): AgnosticDataRouteObject[] {

@@ -305,10 +467,14 @@ return routes.map((route, index) => {

invariant(
!allIds.has(id),
!manifest[id],
`Found a route id collision on id "${id}". Route ` +
"id's must be globally unique within Data Router usages"
);
allIds.add(id);
if (isIndexRoute(route)) {
let indexRoute: AgnosticDataIndexRouteObject = { ...route, id };
let indexRoute: AgnosticDataIndexRouteObject = {
...route,
...mapRouteProperties(route),
id,
};
manifest[id] = indexRoute;
return indexRoute;

@@ -318,7 +484,17 @@ } else {

...route,
...mapRouteProperties(route),
id,
children: route.children
? convertRoutesToDataRoutes(route.children, treePath, allIds)
: undefined,
children: undefined,
};
manifest[id] = pathOrLayoutRoute;
if (route.children) {
pathOrLayoutRoute.children = convertRoutesToDataRoutes(
route.children,
mapRouteProperties,
treePath,
manifest
);
}
return pathOrLayoutRoute;

@@ -370,2 +546,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<

@@ -423,3 +621,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

@@ -501,6 +699,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_

@@ -514,3 +712,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) {

@@ -537,3 +735,3 @@ result.push(...restExploded);

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

@@ -645,3 +843,3 @@ const indexRouteValue = 2;

): string {
let path = originalPath;
let path: string = originalPath;
if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {

@@ -658,45 +856,35 @@ warning(

return (
path
.replace(
/^:(\w+)(\??)/g,
(_, key: PathParam<Path>, optional: string | undefined) => {
let param = params[key];
if (optional === "?") {
return param == null ? "" : param;
}
if (param == null) {
invariant(false, `Missing ":${key}" param`);
}
return param;
}
)
.replace(
/\/:(\w+)(\??)/g,
(_, key: PathParam<Path>, optional: string | undefined) => {
let param = params[key];
if (optional === "?") {
return param == null ? "" : `/${param}`;
}
if (param == null) {
invariant(false, `Missing ":${key}" param`);
}
return `/${param}`;
}
)
// Remove any optional markers from optional static segments
.replace(/\?/g, "")
.replace(/(\/?)\*/, (_, prefix, __, str) => {
// ensure `/` is added at the beginning if the path is absolute
const prefix = path.startsWith("/") ? "/" : "";
const stringify = (p: any) =>
p == null ? "" : typeof p === "string" ? p : String(p);
const segments = path
.split(/\/+/)
.map((segment, index, array) => {
const isLastSegment = index === array.length - 1;
// only apply the splat if it's the last segment
if (isLastSegment && segment === "*") {
const star = "*" as PathParam<Path>;
// Apply the splat
return stringify(params[star]);
}
if (params[star] == null) {
// If no splat was provided, trim the trailing slash _unless_ it's
// the entire path
return str === "/*" ? "/" : "";
}
const keyMatch = segment.match(/^:([\w-]+)(\??)$/);
if (keyMatch) {
const [, key, optional] = keyMatch;
let param = params[key as PathParam<Path>];
invariant(optional === "?" || param != null, `Missing ":${key}" param`);
return stringify(param);
}
// Apply the splat
return `${prefix}${params[star]}`;
})
);
// Remove any optional markers from optional static segments
return segment.replace(/\?$/g, "");
})
// Remove empty segments
.filter((segment) => !!segment);
return prefix + segments.join("/");
}

@@ -768,3 +956,3 @@

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

@@ -781,4 +969,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

@@ -793,6 +981,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] = safelyDecodeURIComponent(value || "", paramName);
}
return memo;

@@ -811,2 +1001,4 @@ },

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

@@ -816,3 +1008,3 @@ path: string,

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

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

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

@@ -833,10 +1025,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 +=

@@ -851,3 +1046,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

@@ -865,3 +1060,3 @@ // non-captured trailing slash (to match a portion of the URL) or the end

return [matcher, paramNames];
return [matcher, params];
}

@@ -927,22 +1122,2 @@

/**
* @private
*/
export function warning(cond: any, message: string): void {
if (!cond) {
// eslint-disable-next-line no-console
if (typeof console !== "undefined") console.warn(message);
try {
// Welcome to debugging @remix-run/router!
//
// This error is thrown as a convenience so you can more easily
// find the source for a warning that appears in the console by
// enabling "pause on exceptions" in your JavaScript debugger.
throw new Error(message);
// eslint-disable-next-line no-empty
} catch (e) {}
}
}
/**
* Returns a resolved path object relative to the given pathname.

@@ -1036,2 +1211,21 @@ *

// 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);
}
/**

@@ -1080,3 +1274,3 @@ * @private

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

@@ -1086,8 +1280,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] === "..") {

@@ -1101,4 +1296,2 @@ toSegments.shift();

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

@@ -1254,3 +1447,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)

@@ -1289,3 +1482,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 });

@@ -1412,11 +1617,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;

@@ -1423,0 +1649,0 @@ constructor(

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