Initial commit

This commit is contained in:
Abhijit Bhatnagar 2025-08-01 08:00:35 +05:30
commit 153a4e9fd7
345 changed files with 359185 additions and 0 deletions

888
node_modules/@remix-run/router/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,888 @@
# `@remix-run/router`
## 1.23.0
### Minor Changes
- Add `fetcherKey` as a parameter to `patchRoutesOnNavigation` ([#13109](https://github.com/remix-run/react-router/pull/13109))
### Patch Changes
- Fix regression introduced in `6.29.0` via [#12169](https://github.com/remix-run/react-router/pull/12169) that caused issues navigating to hash routes inside splat routes for applications using Lazy Route Discovery (`patchRoutesOnNavigation`) ([#13108](https://github.com/remix-run/react-router/pull/13108))
## 1.22.0
### Minor Changes
- Provide the request `signal` as a parameter to `patchRoutesOnNavigation` ([#12900](https://github.com/remix-run/react-router/pull/12900))
- This can be used to abort any manifest fetches if the in-flight navigation/fetcher is aborted
### Patch Changes
- Do not log v7 deprecation warnings in production builds ([#12794](https://github.com/remix-run/react-router/pull/12794))
- Strip search parameters from `patchRoutesOnNavigation` `path` param for fetcher calls ([#12899](https://github.com/remix-run/react-router/pull/12899))
- Properly bubble headers when throwing a `data()` result ([#12845](https://github.com/remix-run/react-router/pull/12845))
- Optimize route matching by skipping redundant `matchRoutes` calls when possible ([#12169](https://github.com/remix-run/react-router/pull/12169))
## 1.21.1
### Patch Changes
- - Fix issue with fetcher data cleanup in the data layer on fetcher unmount ([#12674](https://github.com/remix-run/react-router/pull/12674))
- Fix behavior of manual fetcher keys when not opted into `future.v7_fetcherPersist`
## 1.21.0
### Minor Changes
- - Log deprecation warnings for v7 flags ([#11750](https://github.com/remix-run/react-router/pull/11750))
- Add deprecation warnings to `json`/`defer` in favor of returning raw objects
- These methods will be removed in React Router v7
### Patch Changes
- Update JSDoc URLs for new website structure (add /v6/ segment) ([#12141](https://github.com/remix-run/react-router/pull/12141))
## 1.20.0
### Minor Changes
- Stabilize `unstable_patchRoutesOnNavigation` ([#11973](https://github.com/remix-run/react-router/pull/11973))
- Add new `PatchRoutesOnNavigationFunctionArgs` type for convenience ([#11967](https://github.com/remix-run/react-router/pull/11967))
- Stabilize `unstable_dataStrategy` ([#11974](https://github.com/remix-run/react-router/pull/11974))
- Stabilize the `unstable_flushSync` option for navigations and fetchers ([#11989](https://github.com/remix-run/react-router/pull/11989))
- Stabilize the `unstable_viewTransition` option for navigations and the corresponding `unstable_useViewTransitionState` hook ([#11989](https://github.com/remix-run/react-router/pull/11989))
### Patch Changes
- Fix bug when submitting to the current contextual route (parent route with an index child) when an `?index` param already exists from a prior submission ([#12003](https://github.com/remix-run/react-router/pull/12003))
- Fix `useFormAction` bug - when removing `?index` param it would not keep other non-Remix `index` params ([#12003](https://github.com/remix-run/react-router/pull/12003))
- Fix bug with fetchers not persisting `preventScrollReset` through redirects during concurrent fetches ([#11999](https://github.com/remix-run/react-router/pull/11999))
- Remove internal cache to fix issues with interrupted `patchRoutesOnNavigation` calls ([#12055](https://github.com/remix-run/react-router/pull/12055))
- We used to cache in-progress calls to `patchRoutesOnNavigation` internally so that multiple navigations with the same start/end would only execute the function once and use the same promise
- However, this approach was at odds with `patch` short circuiting if a navigation was interrupted (and the `request.signal` aborted) since the first invocation's `patch` would no-op
- This cache also made some assumptions as to what a valid cache key might be - and is oblivious to any other application-state changes that may have occurred
- So, the cache has been removed because in _most_ cases, repeated calls to something like `import()` for async routes will already be cached automatically - and if not it's easy enough for users to implement this cache in userland
- Avoid unnecessary `console.error` on fetcher abort due to back-to-back revalidation calls ([#12050](https://github.com/remix-run/react-router/pull/12050))
- Expose errors thrown from `patchRoutesOnNavigation` directly to `useRouteError` instead of wrapping them in a 400 `ErrorResponse` instance ([#12111](https://github.com/remix-run/react-router/pull/12111))
- Fix types for `RouteObject` within `PatchRoutesOnNavigationFunction`'s `patch` method so it doesn't expect agnostic route objects passed to `patch` ([#11967](https://github.com/remix-run/react-router/pull/11967))
- Fix bugs with `partialHydration` when hydrating with errors ([#12070](https://github.com/remix-run/react-router/pull/12070))
- Remove internal `discoveredRoutes` FIFO queue from `unstable_patchRoutesOnNavigation` ([#11977](https://github.com/remix-run/react-router/pull/11977))
## 1.19.2
### Patch Changes
- Update the `unstable_dataStrategy` API to allow for more advanced implementations ([#11943](https://github.com/remix-run/react-router/pull/11943))
- Rename `unstable_HandlerResult` to `unstable_DataStrategyResult`
- The return signature has changed from a parallel array of `unstable_DataStrategyResult[]` (parallel to `matches`) to a key/value object of `routeId => unstable_DataStrategyResult`
- This allows you to more easily decide to opt-into or out-of revalidating data that may not have been revalidated by default (via `match.shouldLoad`)
- ⚠️ This is a breaking change if you've currently adopted `unstable_dataStrategy`
- Added a new `fetcherKey` parameter to `unstable_dataStrategy` to allow differentiation from navigational and fetcher calls
- You should now return/throw a result from your `handlerOverride` instead of returning a `DataStrategyResult`
- If you are aggregating the results of `match.resolve()` into a final results object you should not need to think about the `DataStrategyResult` type
- If you are manually filling your results object from within your `handlerOverride`, then you will need to assign a `DataStrategyResult` as the value so React Router knows if it's a successful execution or an error.
- Preserve view transition through redirects ([#11925](https://github.com/remix-run/react-router/pull/11925))
- Fix blocker usage when `blocker.proceed` is called quickly/synchronously ([#11930](https://github.com/remix-run/react-router/pull/11930))
- Preserve pending view transitions through a router revalidation call ([#11917](https://github.com/remix-run/react-router/pull/11917))
## 1.19.1
### Patch Changes
- Fog of War: Update `unstable_patchRoutesOnMiss` logic so that we call the method when we match routes with dynamic param or splat segments in case there exists a higher-scoring static route that we've not yet discovered. ([#11883](https://github.com/remix-run/react-router/pull/11883))
- We also now leverage an internal FIFO queue of previous paths we've already called `unstable_patchRouteOnMiss` against so that we don't re-call on subsequent navigations to the same path
- Rename `unstable_patchRoutesOnMiss` to `unstable_patchRoutesOnNavigation` to match new behavior ([#11888](https://github.com/remix-run/react-router/pull/11888))
## 1.19.0
### Minor Changes
- Add a new `replace(url, init?)` alternative to `redirect(url, init?)` that performs a `history.replaceState` instead of a `history.pushState` on client-side navigation redirects ([#11811](https://github.com/remix-run/react-router/pull/11811))
- Add a new `unstable_data()` API for usage with Remix Single Fetch ([#11836](https://github.com/remix-run/react-router/pull/11836))
- This API is not intended for direct usage in React Router SPA applications
- It is primarily intended for usage with `createStaticHandler.query()` to allow loaders/actions to return arbitrary data + `status`/`headers` without forcing the serialization of data into a `Response` instance
- This allows for more advanced serialization tactics via `unstable_dataStrategy` such as serializing via `turbo-stream` in Remix Single Fetch
- ⚠️ This removes the `status` field from `HandlerResult`
- If you need to return a specific `status` from `unstable_dataStrategy` you should instead do so via `unstable_data()`
### Patch Changes
- Fix internal cleanup of interrupted fetchers to avoid invalid revalidations on navigations ([#11839](https://github.com/remix-run/react-router/pull/11839))
- When a `fetcher.load` is interrupted by an `action` submission, we track it internally and force revalidation once the `action` completes
- We previously only cleared out this internal tracking info on a successful _navigation_ submission
- Therefore, if the `fetcher.load` was interrupted by a `fetcher.submit`, then we wouldn't remove it from this internal tracking info on successful load (incorrectly)
- And then on the next navigation it's presence in the internal tracking would automatically trigger execution of the `fetcher.load` again, ignoring any `shouldRevalidate` logic
- This fix cleans up the internal tracking so it applies to both navigation submission and fetcher submissions
- Fix initial hydration behavior when using `future.v7_partialHydration` along with `unstable_patchRoutesOnMiss` ([#11838](https://github.com/remix-run/react-router/pull/11838))
- During initial hydration, `router.state.matches` will now include any partial matches so that we can render ancestor `HydrateFallback` components
## 1.18.0
### Minor Changes
- Stabilize `future.unstable_skipActionErrorRevalidation` as `future.v7_skipActionErrorRevalidation` ([#11769](https://github.com/remix-run/react-router/pull/11769))
- When this flag is enabled, actions will not automatically trigger a revalidation if they return/throw a `Response` with a `4xx`/`5xx` status code
- You may still opt-into revalidation via `shouldRevalidate`
- This also changes `shouldRevalidate`'s `unstable_actionStatus` parameter to `actionStatus`
### Patch Changes
- Fix bubbling of errors thrown from `unstable_patchRoutesOnMiss` ([#11786](https://github.com/remix-run/react-router/pull/11786))
- Fix hydration in SSR apps using `unstable_patchRoutesOnMiss` that matched a splat route on the server ([#11790](https://github.com/remix-run/react-router/pull/11790))
## 1.17.1
### Patch Changes
- Fog of War (unstable): Trigger a new `router.routes` identity/reflow during route patching ([#11740](https://github.com/remix-run/react-router/pull/11740))
- Fog of War (unstable): Fix initial matching when a splat route matches ([#11759](https://github.com/remix-run/react-router/pull/11759))
## 1.17.0
### Minor Changes
- Add support for Lazy Route Discovery (a.k.a. Fog of War) ([#11626](https://github.com/remix-run/react-router/pull/11626))
- RFC: <https://github.com/remix-run/react-router/discussions/11113>
- `unstable_patchRoutesOnMiss` docs: <https://reactrouter.com/v6/routers/create-browser-router>
## 1.16.1
### Patch Changes
- Support `unstable_dataStrategy` on `staticHandler.queryRoute` ([#11515](https://github.com/remix-run/react-router/pull/11515))
## 1.16.0
### Minor Changes
- Add a new `unstable_dataStrategy` configuration option ([#11098](https://github.com/remix-run/react-router/pull/11098))
- This option allows Data Router applications to take control over the approach for executing route loaders and actions
- The default implementation is today's behavior, to fetch all loaders in parallel, but this option allows users to implement more advanced data flows including Remix single-fetch, middleware/context APIs, automatic loader caching, and more
- Move `unstable_dataStrategy` from `createStaticHandler` to `staticHandler.query` so it can be request-specific for use with the `ResponseStub` approach in Remix. It's not really applicable to `queryRoute` for now since that's a singular handler call anyway so any pre-processing/post/processing could be done there manually. ([#11377](https://github.com/remix-run/react-router/pull/11377))
- Add a new `future.unstable_skipActionRevalidation` future flag ([#11098](https://github.com/remix-run/react-router/pull/11098))
- Currently, active loaders revalidate after any action, regardless of the result
- With this flag enabled, actions that return/throw a 4xx/5xx response status will no longer automatically revalidate
- This should reduce load on your server since it's rare that a 4xx/5xx should actually mutate any data
- If you need to revalidate after a 4xx/5xx result with this flag enabled, you can still do that via returning `true` from `shouldRevalidate`
- `shouldRevalidate` now also receives a new `unstable_actionStatus` argument alongside `actionResult` so you can make decision based on the status of the `action` response without having to encode it into the action data
- Added a `skipLoaderErrorBubbling` flag to `staticHandler.query` to disable error bubbling on loader executions for single-fetch scenarios where the client-side router will handle the bubbling ([#11098](https://github.com/remix-run/react-router/pull/11098))
## 1.15.3
### Patch Changes
- Fix a `future.v7_partialHydration` bug that would re-run loaders below the boundary on hydration if SSR loader errors bubbled to a parent boundary ([#11324](https://github.com/remix-run/react-router/pull/11324))
- Fix a `future.v7_partialHydration` bug that would consider the router uninitialized if a route did not have a loader ([#11325](https://github.com/remix-run/react-router/pull/11325))
## 1.15.2
### Patch Changes
- Preserve hydrated errors during partial hydration runs ([#11305](https://github.com/remix-run/react-router/pull/11305))
## 1.15.1
### Patch Changes
- Fix encoding/decoding issues with pre-encoded dynamic parameter values ([#11199](https://github.com/remix-run/react-router/pull/11199))
## 1.15.0
### Minor Changes
- Add a `createStaticHandler` `future.v7_throwAbortReason` flag to throw `request.signal.reason` (defaults to a `DOMException`) when a request is aborted instead of an `Error` such as `new Error("query() call aborted: GET /path")` ([#11104](https://github.com/remix-run/react-router/pull/11104))
- Please note that `DOMException` was added in Node v17 so you will not get a `DOMException` on Node 16 and below.
### Patch Changes
- Respect the `ErrorResponse` status code if passed to `getStaticContextFormError` ([#11213](https://github.com/remix-run/react-router/pull/11213))
## 1.14.2
### Patch Changes
- Fix bug where dashes were not picked up in dynamic parameter names ([#11160](https://github.com/remix-run/react-router/pull/11160))
- Do not attempt to deserialize empty JSON responses ([#11164](https://github.com/remix-run/react-router/pull/11164))
## 1.14.1
### Patch Changes
- Fix bug with `route.lazy` not working correctly on initial SPA load when `v7_partialHydration` is specified ([#11121](https://github.com/remix-run/react-router/pull/11121))
- Fix bug preventing revalidation from occurring for persisted fetchers unmounted during the `submitting` phase ([#11102](https://github.com/remix-run/react-router/pull/11102))
- De-dup relative path logic in `resolveTo` ([#11097](https://github.com/remix-run/react-router/pull/11097))
## 1.14.0
### Minor Changes
- Added a new `future.v7_partialHydration` future flag that enables partial hydration of a data router when Server-Side Rendering. This allows you to provide `hydrationData.loaderData` that has values for _some_ initially matched route loaders, but not all. When this flag is enabled, the router will call `loader` functions for routes that do not have hydration loader data during `router.initialize()`, and it will render down to the deepest provided `HydrateFallback` (up to the first route without hydration data) while it executes the unhydrated routes. ([#11033](https://github.com/remix-run/react-router/pull/11033))
For example, the following router has a `root` and `index` route, but only provided `hydrationData.loaderData` for the `root` route. Because the `index` route has a `loader`, we need to run that during initialization. With `future.v7_partialHydration` specified, `<RouterProvider>` will render the `RootComponent` (because it has data) and then the `IndexFallback` (since it does not have data). Once `indexLoader` finishes, application will update and display `IndexComponent`.
```jsx
let router = createBrowserRouter(
[
{
id: "root",
path: "/",
loader: rootLoader,
Component: RootComponent,
Fallback: RootFallback,
children: [
{
id: "index",
index: true,
loader: indexLoader,
Component: IndexComponent,
HydrateFallback: IndexFallback,
},
],
},
],
{
future: {
v7_partialHydration: true,
},
hydrationData: {
loaderData: {
root: { message: "Hydrated from Root!" },
},
},
}
);
```
If the above example did not have an `IndexFallback`, then `RouterProvider` would instead render the `RootFallback` while it executed the `indexLoader`.
**Note:** When `future.v7_partialHydration` is provided, the `<RouterProvider fallbackElement>` prop is ignored since you can move it to a `Fallback` on your top-most route. The `fallbackElement` prop will be removed in React Router v7 when `v7_partialHydration` behavior becomes the standard behavior.
- Add a new `future.v7_relativeSplatPath` flag to implement a breaking bug fix to relative routing when inside a splat route. ([#11087](https://github.com/remix-run/react-router/pull/11087))
This fix was originally added in [#10983](https://github.com/remix-run/react-router/issues/10983) and was later reverted in [#11078](https://github.com/remix-run/react-router/pull/11078) because it was determined that a large number of existing applications were relying on the buggy behavior (see [#11052](https://github.com/remix-run/react-router/issues/11052))
**The Bug**
The buggy behavior is that without this flag, the default behavior when resolving relative paths is to _ignore_ any splat (`*`) portion of the current route path.
**The Background**
This decision was originally made thinking that it would make the concept of nested different sections of your apps in `<Routes>` easier if relative routing would _replace_ the current splat:
```jsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="dashboard/*" element={<Dashboard />} />
</Routes>
</BrowserRouter>
```
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects` will match the `Dashboard` route. The dashboard component itself can then render nested `<Routes>`:
```jsx
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="/">Dashboard Home</Link>
<Link to="team">Team</Link>
<Link to="projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Routes>
</div>
);
}
```
Now, all links and route paths are relative to the router above them. This makes code splitting and compartmentalizing your app really easy. You could render the `Dashboard` as its own independent app, or embed it into your large app without making any changes to it.
**The Problem**
The problem is that this concept of ignoring part of a path breaks a lot of other assumptions in React Router - namely that `"."` always means the current location pathname for that route. When we ignore the splat portion, we start getting invalid paths when using `"."`:
```jsx
// If we are on URL /dashboard/team, and we want to link to /dashboard/team:
function DashboardTeam() {
// ❌ This is broken and results in <a href="/dashboard">
return <Link to=".">A broken link to the Current URL</Link>;
// ✅ This is fixed but super unintuitive since we're already at /dashboard/team!
return <Link to="./team">A broken link to the Current URL</Link>;
}
```
We've also introduced an issue that we can no longer move our `DashboardTeam` component around our route hierarchy easily - since it behaves differently if we're underneath a non-splat route, such as `/dashboard/:widget`. Now, our `"."` links will, properly point to ourself _inclusive of the dynamic param value_ so behavior will break from it's corresponding usage in a `/dashboard/*` route.
Even worse, consider a nested splat route configuration:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
```
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard` component go to the same place! That is definitely not correct!
Another common issue arose in Data Routers (and Remix) where any `<Form>` should post to it's own route `action` if you the user doesn't specify a form action:
```jsx
let router = createBrowserRouter({
path: "/dashboard",
children: [
{
path: "*",
action: dashboardAction,
Component() {
// ❌ This form is broken! It throws a 405 error when it submits because
// it tries to submit to /dashboard (without the splat value) and the parent
// `/dashboard` route doesn't have an action
return <Form method="post">...</Form>;
},
},
],
});
```
This is just a compounded issue from the above because the default location for a `Form` to submit to is itself (`"."`) - and if we ignore the splat portion, that now resolves to the parent route.
**The Solution**
If you are leveraging this behavior, it's recommended to enable the future flag, move your splat to it's own route, and leverage `../` for any links to "sibling" pages:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route index path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="..">Dashboard Home</Link>
<Link to="../team">Team</Link>
<Link to="../projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Router>
</div>
);
}
```
This way, `.` means "the full current pathname for my route" in all cases (including static, dynamic, and splat routes) and `..` always means "my parents pathname".
### Patch Changes
- Catch and bubble errors thrown when trying to unwrap responses from `loader`/`action` functions ([#11061](https://github.com/remix-run/react-router/pull/11061))
- Fix `relative="path"` issue when rendering `Link`/`NavLink` outside of matched routes ([#11062](https://github.com/remix-run/react-router/pull/11062))
## 1.13.1
### Patch Changes
- Revert the `useResolvedPath` fix for splat routes due to a large number of applications that were relying on the buggy behavior (see <https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329>). We plan to re-introduce this fix behind a future flag in the next minor version. ([#11078](https://github.com/remix-run/react-router/pull/11078))
## 1.13.0
### Minor Changes
- Export the `PathParam` type from the public API ([#10719](https://github.com/remix-run/react-router/pull/10719))
### Patch Changes
- Fix bug with `resolveTo` in splat routes ([#11045](https://github.com/remix-run/react-router/pull/11045))
- This is a follow up to [#10983](https://github.com/remix-run/react-router/pull/10983) to handle the few other code paths using `getPathContributingMatches`
- This removes the `UNSAFE_getPathContributingMatches` export from `@remix-run/router` since we no longer need this in the `react-router`/`react-router-dom` layers
- Do not revalidate unmounted fetchers when `v7_fetcherPersist` is enabled ([#11044](https://github.com/remix-run/react-router/pull/11044))
## 1.12.0
### Minor Changes
- Add `unstable_flushSync` option to `router.navigate` and `router.fetch` to tell the React Router layer to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#11005](https://github.com/remix-run/react-router/pull/11005))
### Patch Changes
- Fix `relative="path"` bug where relative path calculations started from the full location pathname, instead of from the current contextual route pathname. ([#11006](https://github.com/remix-run/react-router/pull/11006))
```jsx
<Route path="/a">
<Route path="/b" element={<Component />}>
<Route path="/c" />
</Route>
</Route>;
function Component() {
return (
<>
{/* This is now correctly relative to /a/b, not /a/b/c */}
<Link to=".." relative="path" />
<Outlet />
</>
);
}
```
## 1.11.0
### Minor Changes
- Add a new `future.v7_fetcherPersist` flag to the `@remix-run/router` to change the persistence behavior of fetchers when `router.deleteFetcher` is called. Instead of being immediately cleaned up, fetchers will persist until they return to an `idle` state ([RFC](https://github.com/remix-run/remix/discussions/7698)) ([#10962](https://github.com/remix-run/react-router/pull/10962))
- This is sort of a long-standing bug fix as the `useFetchers()` API was always supposed to only reflect **in-flight** fetcher information for pending/optimistic UI -- it was not intended to reflect fetcher data or hang onto fetchers after they returned to an `idle` state
- Keep an eye out for the following specific behavioral changes when opting into this flag and check your app for compatibility:
- Fetchers that complete _while still mounted_ will no longer appear in `useFetchers()`. They served effectively no purpose in there since you can access the data via `useFetcher().data`).
- Fetchers that previously unmounted _while in-flight_ will not be immediately aborted and will instead be cleaned up once they return to an `idle` state. They will remain exposed via `useFetchers` while in-flight so you can still access pending/optimistic data after unmount.
- When `v7_fetcherPersist` is enabled, the router now performs ref-counting on fetcher keys via `getFetcher`/`deleteFetcher` so it knows when a given fetcher is totally unmounted from the UI ([#10977](https://github.com/remix-run/react-router/pull/10977))
- Once a fetcher has been totally unmounted, we can ignore post-processing of a persisted fetcher result such as a redirect or an error
- The router will also pass a new `deletedFetchers` array to the subscriber callbacks so that the UI layer can remove associated fetcher data
- Add support for optional path segments in `matchPath` ([#10768](https://github.com/remix-run/react-router/pull/10768))
### Patch Changes
- Fix `router.getFetcher`/`router.deleteFetcher` type definitions which incorrectly specified `key` as an optional parameter ([#10960](https://github.com/remix-run/react-router/pull/10960))
## 1.10.0
### Minor Changes
- Add experimental support for the [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) by allowing users to opt-into view transitions on navigations via the new `unstable_viewTransition` option to `router.navigate` ([#10916](https://github.com/remix-run/react-router/pull/10916))
### Patch Changes
- Allow 404 detection to leverage root route error boundary if path contains a URL segment ([#10852](https://github.com/remix-run/react-router/pull/10852))
- Fix `ErrorResponse` type to avoid leaking internal field ([#10876](https://github.com/remix-run/react-router/pull/10876))
## 1.9.0
### Minor Changes
- In order to move towards stricter TypeScript support in the future, we're aiming to replace current usages of `any` with `unknown` on exposed typings for user-provided data. To do this in Remix v2 without introducing breaking changes in React Router v6, we have added generics to a number of shared types. These continue to default to `any` in React Router and are overridden with `unknown` in Remix. In React Router v7 we plan to move these to `unknown` as a breaking change. ([#10843](https://github.com/remix-run/react-router/pull/10843))
- `Location` now accepts a generic for the `location.state` value
- `ActionFunctionArgs`/`ActionFunction`/`LoaderFunctionArgs`/`LoaderFunction` now accept a generic for the `context` parameter (only used in SSR usages via `createStaticHandler`)
- The return type of `useMatches` (now exported as `UIMatch`) accepts generics for `match.data` and `match.handle` - both of which were already set to `unknown`
- Move the `@private` class export `ErrorResponse` to an `UNSAFE_ErrorResponseImpl` export since it is an implementation detail and there should be no construction of `ErrorResponse` instances in userland. This frees us up to export a `type ErrorResponse` which correlates to an instance of the class via `InstanceType`. Userland code should only ever be using `ErrorResponse` as a type and should be type-narrowing via `isRouteErrorResponse`. ([#10811](https://github.com/remix-run/react-router/pull/10811))
- Export `ShouldRevalidateFunctionArgs` interface ([#10797](https://github.com/remix-run/react-router/pull/10797))
- Removed private/internal APIs only required for the Remix v1 backwards compatibility layer and no longer needed in Remix v2 (`_isFetchActionRedirect`, `_hasFetcherDoneAnything`) ([#10715](https://github.com/remix-run/react-router/pull/10715))
### Patch Changes
- Add method/url to error message on aborted `query`/`queryRoute` calls ([#10793](https://github.com/remix-run/react-router/pull/10793))
- Fix a race-condition with loader/action-thrown errors on `route.lazy` routes ([#10778](https://github.com/remix-run/react-router/pull/10778))
- Fix type for `actionResult` on the arguments object passed to `shouldRevalidate` ([#10779](https://github.com/remix-run/react-router/pull/10779))
## 1.8.0
### Minor Changes
- Add's a new `redirectDocument()` function which allows users to specify that a redirect from a `loader`/`action` should trigger a document reload (via `window.location`) instead of attempting to navigate to the redirected location via React Router ([#10705](https://github.com/remix-run/react-router/pull/10705))
### Patch Changes
- Fix an issue in `queryRoute` that was not always identifying thrown `Response` instances ([#10717](https://github.com/remix-run/react-router/pull/10717))
- Ensure hash history always includes a leading slash on hash pathnames ([#10753](https://github.com/remix-run/react-router/pull/10753))
## 1.7.2
### Patch Changes
- Trigger an error if a `defer` promise resolves/rejects with `undefined` in order to match the behavior of loaders and actions which must return a value or `null` ([#10690](https://github.com/remix-run/react-router/pull/10690))
- Properly handle fetcher redirects interrupted by normal navigations ([#10674](https://github.com/remix-run/react-router/pull/10674), [#10709](https://github.com/remix-run/react-router/pull/10709))
- Initial-load fetchers should not automatically revalidate on GET navigations ([#10688](https://github.com/remix-run/react-router/pull/10688))
- Enhance the return type of `Route.lazy` to prohibit returning an empty object ([#10634](https://github.com/remix-run/react-router/pull/10634))
## 1.7.1
### Patch Changes
- Fix issues with reused blockers on subsequent navigations ([#10656](https://github.com/remix-run/react-router/pull/10656))
## 1.7.0
### Minor Changes
- Add support for `application/json` and `text/plain` encodings for `router.navigate`/`router.fetch` submissions. To leverage these encodings, pass your data in a `body` parameter and specify the desired `formEncType`: ([#10413](https://github.com/remix-run/react-router/pull/10413))
```js
// By default, the encoding is "application/x-www-form-urlencoded"
router.navigate("/", {
formMethod: "post",
body: { key: "value" },
});
async function action({ request }) {
// await request.formData() => FormData instance with entry [key=value]
}
```
```js
// Pass `formEncType` to opt-into a different encoding (json)
router.navigate("/", {
formMethod: "post",
formEncType: "application/json",
body: { key: "value" },
});
async function action({ request }) {
// await request.json() => { key: "value" }
}
```
```js
// Pass `formEncType` to opt-into a different encoding (text)
router.navigate("/", {
formMethod: "post",
formEncType: "text/plain",
body: "Text submission",
});
async function action({ request }) {
// await request.text() => "Text submission"
}
```
### Patch Changes
- Call `window.history.pushState/replaceState` before updating React Router state (instead of after) so that `window.location` matches `useLocation` during synchronous React 17 rendering ([#10448](https://github.com/remix-run/react-router/pull/10448))
- ⚠️ However, generally apps should not be relying on `window.location` and should always reference `useLocation` when possible, as `window.location` will not be in sync 100% of the time (due to `popstate` events, concurrent mode, etc.)
- Strip `basename` from the `location` provided to `<ScrollRestoration getKey>` to match the `useLocation` behavior ([#10550](https://github.com/remix-run/react-router/pull/10550))
- Avoid calling `shouldRevalidate` for fetchers that have not yet completed a data load ([#10623](https://github.com/remix-run/react-router/pull/10623))
- Fix `unstable_useBlocker` key issues in `StrictMode` ([#10573](https://github.com/remix-run/react-router/pull/10573))
- Upgrade `typescript` to 5.1 ([#10581](https://github.com/remix-run/react-router/pull/10581))
## 1.6.3
### Patch Changes
- Allow fetcher revalidations to complete if submitting fetcher is deleted ([#10535](https://github.com/remix-run/react-router/pull/10535))
- Re-throw `DOMException` (`DataCloneError`) when attempting to perform a `PUSH` navigation with non-serializable state. ([#10427](https://github.com/remix-run/react-router/pull/10427))
- Ensure revalidations happen when hash is present ([#10516](https://github.com/remix-run/react-router/pull/10516))
- upgrade jest and jsdom ([#10453](https://github.com/remix-run/react-router/pull/10453))
## 1.6.2
### Patch Changes
- Fix HMR-driven error boundaries by properly reconstructing new routes and `manifest` in `\_internalSetRoutes` ([#10437](https://github.com/remix-run/react-router/pull/10437))
- Fix bug where initial data load would not kick off when hash is present ([#10493](https://github.com/remix-run/react-router/pull/10493))
## 1.6.1
### Patch Changes
- Fix `basename` handling when navigating without a path ([#10433](https://github.com/remix-run/react-router/pull/10433))
- "Same hash" navigations no longer re-run loaders to match browser behavior (i.e. `/path#hash -> /path#hash`) ([#10408](https://github.com/remix-run/react-router/pull/10408))
## 1.6.0
### Minor Changes
- Enable relative routing in the `@remix-run/router` when providing a source route ID from which the path is relative to: ([#10336](https://github.com/remix-run/react-router/pull/10336))
- Example: `router.navigate("../path", { fromRouteId: "some-route" })`.
- This also applies to `router.fetch` which already receives a source route ID
- Introduce a new `@remix-run/router` `future.v7_prependBasename` flag to enable `basename` prefixing to all paths coming into `router.navigate` and `router.fetch`.
- Previously the `basename` was prepended in the React Router layer, but now that relative routing is being handled by the router we need prepend the `basename` _after_ resolving any relative paths
- This also enables `basename` support in `useFetcher` as well
### Patch Changes
- Enhance `LoaderFunction`/`ActionFunction` return type to prevent `undefined` from being a valid return value ([#10267](https://github.com/remix-run/react-router/pull/10267))
- Ensure proper 404 error on `fetcher.load` call to a route without a `loader` ([#10345](https://github.com/remix-run/react-router/pull/10345))
- Deprecate the `createRouter` `detectErrorBoundary` option in favor of the new `mapRouteProperties` option for converting a framework-agnostic route to a framework-aware route. This allows us to set more than just the `hasErrorBoundary` property during route pre-processing, and is now used for mapping `Component -> element` and `ErrorBoundary -> errorElement` in `react-router`. ([#10287](https://github.com/remix-run/react-router/pull/10287))
- Fixed a bug where fetchers were incorrectly attempting to revalidate on search params changes or routing to the same URL (using the same logic for route `loader` revalidations). However, since fetchers have a static href, they should only revalidate on `action` submissions or `router.revalidate` calls. ([#10344](https://github.com/remix-run/react-router/pull/10344))
- Decouple `AbortController` usage between revalidating fetchers and the thing that triggered them such that the unmount/deletion of a revalidating fetcher doesn't impact the ongoing triggering navigation/revalidation ([#10271](https://github.com/remix-run/react-router/pull/10271))
## 1.5.0
### Minor Changes
- Added support for [**Future Flags**](https://reactrouter.com/v6/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))
## 1.3.2
### Patch Changes
- Remove inaccurate console warning for POP navigations and update active blocker logic ([#10030](https://github.com/remix-run/react-router/pull/10030))
- Only check for differing origin on absolute URL redirects ([#10033](https://github.com/remix-run/react-router/pull/10033))
## 1.3.1
### Patch Changes
- Fixes 2 separate issues for revalidating fetcher `shouldRevalidate` calls ([#9948](https://github.com/remix-run/react-router/pull/9948))
- The `shouldRevalidate` function was only being called for _explicit_ revalidation scenarios (after a mutation, manual `useRevalidator` call, or an `X-Remix-Revalidate` header used for cookie setting in Remix). It was not properly being called on _implicit_ revalidation scenarios that also apply to navigation `loader` revalidation, such as a change in search params or clicking a link for the page we're already on. It's now correctly called in those additional scenarios.
- The parameters being passed were incorrect and inconsistent with one another since the `current*`/`next*` parameters reflected the static `fetcher.load` URL (and thus were identical). Instead, they should have reflected the the navigation that triggered the revalidation (as the `form*` parameters did). These parameters now correctly reflect the triggering navigation.
- Respect `preventScrollReset` on `<fetcher.Form>` ([#9963](https://github.com/remix-run/react-router/pull/9963))
- Do not short circuit on hash change only mutation submissions ([#9944](https://github.com/remix-run/react-router/pull/9944))
- Remove `instanceof` check from `isRouteErrorResponse` to avoid bundling issues on the server ([#9930](https://github.com/remix-run/react-router/pull/9930))
- Fix navigation for hash routers on manual URL changes ([#9980](https://github.com/remix-run/react-router/pull/9980))
- Detect when a `defer` call only contains critical data and remove the `AbortController` ([#9965](https://github.com/remix-run/react-router/pull/9965))
- Send the name as the value when url-encoding `File` `FormData` entries ([#9867](https://github.com/remix-run/react-router/pull/9867))
## 1.3.0
### Minor Changes
- Added support for navigation blocking APIs ([#9709](https://github.com/remix-run/react-router/pull/9709))
- Expose deferred information from `createStaticHandler` ([#9760](https://github.com/remix-run/react-router/pull/9760))
### Patch Changes
- Improved absolute redirect url detection in actions/loaders ([#9829](https://github.com/remix-run/react-router/pull/9829))
- Fix URL creation with memory histories ([#9814](https://github.com/remix-run/react-router/pull/9814))
- Fix `generatePath` when optional params are present ([#9764](https://github.com/remix-run/react-router/pull/9764))
- Fix scroll reset if a submission redirects ([#9886](https://github.com/remix-run/react-router/pull/9886))
- Fix 404 bug with same-origin absolute redirects ([#9913](https://github.com/remix-run/react-router/pull/9913))
- Support `OPTIONS` requests in `staticHandler.queryRoute` ([#9914](https://github.com/remix-run/react-router/pull/9914))
## 1.2.1
### Patch Changes
- Include submission info in `shouldRevalidate` on action redirects ([#9777](https://github.com/remix-run/react-router/pull/9777), [#9782](https://github.com/remix-run/react-router/pull/9782))
- Reset `actionData` on action redirect to current location ([#9772](https://github.com/remix-run/react-router/pull/9772))
## 1.2.0
### Minor Changes
- Remove `unstable_` prefix from `createStaticHandler`/`createStaticRouter`/`StaticRouterProvider` ([#9738](https://github.com/remix-run/react-router/pull/9738))
### Patch Changes
- Fix explicit `replace` on submissions and `PUSH` on submission to new paths ([#9734](https://github.com/remix-run/react-router/pull/9734))
- Fix a few bugs where loader/action data wasn't properly cleared on errors ([#9735](https://github.com/remix-run/react-router/pull/9735))
- Prevent `useLoaderData` usage in `errorElement` ([#9735](https://github.com/remix-run/react-router/pull/9735))
- Skip initial scroll restoration for SSR apps with `hydrationData` ([#9664](https://github.com/remix-run/react-router/pull/9664))
## 1.1.0
This release introduces support for [Optional Route Segments](https://github.com/remix-run/react-router/issues/9546). Now, adding a `?` to the end of any path segment will make that entire segment optional. This works for both static segments and dynamic parameters.
**Optional Params Examples**
- Path `lang?/about` will match:
- `/:lang/about`
- `/about`
- Path `/multistep/:widget1?/widget2?/widget3?` will match:
- `/multistep`
- `/multistep/:widget1`
- `/multistep/:widget1/:widget2`
- `/multistep/:widget1/:widget2/:widget3`
**Optional Static Segment Example**
- Path `/home?` will match:
- `/`
- `/home`
- Path `/fr?/about` will match:
- `/about`
- `/fr/about`
### Minor Changes
- Allows optional routes and optional static segments ([#9650](https://github.com/remix-run/react-router/pull/9650))
### Patch Changes
- Stop incorrectly matching on partial named parameters, i.e. `<Route path="prefix-:param">`, to align with how splat parameters work. If you were previously relying on this behavior then it's recommended to extract the static portion of the path at the `useParams` call site: ([#9506](https://github.com/remix-run/react-router/pull/9506))
```jsx
// Old behavior at URL /prefix-123
<Route path="prefix-:id" element={<Comp /> }>
function Comp() {
let params = useParams(); // { id: '123' }
let id = params.id; // "123"
...
}
// New behavior at URL /prefix-123
<Route path=":id" element={<Comp /> }>
function Comp() {
let params = useParams(); // { id: 'prefix-123' }
let id = params.id.replace(/^prefix-/, ''); // "123"
...
}
```
- Persist `headers` on `loader` `request`'s after SSR document `action` request ([#9721](https://github.com/remix-run/react-router/pull/9721))
- Fix requests sent to revalidating loaders so they reflect a GET request ([#9660](https://github.com/remix-run/react-router/pull/9660))
- Fix issue with deeply nested optional segments ([#9727](https://github.com/remix-run/react-router/pull/9727))
- GET forms now expose a submission on the loading navigation ([#9695](https://github.com/remix-run/react-router/pull/9695))
- Fix error boundary tracking for multiple errors bubbling to the same boundary ([#9702](https://github.com/remix-run/react-router/pull/9702))
## 1.0.5
### Patch Changes
- Fix requests sent to revalidating loaders so they reflect a `GET` request ([#9680](https://github.com/remix-run/react-router/pull/9680))
- Remove `instanceof Response` checks in favor of `isResponse` ([#9690](https://github.com/remix-run/react-router/pull/9690))
- Fix `URL` creation in Cloudflare Pages or other non-browser-environments ([#9682](https://github.com/remix-run/react-router/pull/9682), [#9689](https://github.com/remix-run/react-router/pull/9689))
- Add `requestContext` support to static handler `query`/`queryRoute` ([#9696](https://github.com/remix-run/react-router/pull/9696))
- Note that the unstable API of `queryRoute(path, routeId)` has been changed to `queryRoute(path, { routeId, requestContext })`
## 1.0.4
### Patch Changes
- Throw an error if an `action`/`loader` function returns `undefined` as revalidations need to know whether the loader has previously been executed. `undefined` also causes issues during SSR stringification for hydration. You should always ensure you `loader`/`action` returns a value, and you may return `null` if you don't wish to return anything. ([#9511](https://github.com/remix-run/react-router/pull/9511))
- Properly handle redirects to external domains ([#9590](https://github.com/remix-run/react-router/pull/9590), [#9654](https://github.com/remix-run/react-router/pull/9654))
- Preserve the HTTP method on 307/308 redirects ([#9597](https://github.com/remix-run/react-router/pull/9597))
- Support `basename` in static data routers ([#9591](https://github.com/remix-run/react-router/pull/9591))
- Enhanced `ErrorResponse` bodies to contain more descriptive text in internal 403/404/405 scenarios
## 1.0.3
### Patch Changes
- Fix hrefs generated when using `createHashRouter` ([#9409](https://github.com/remix-run/react-router/pull/9409))
- fix encoding/matching issues with special chars ([#9477](https://github.com/remix-run/react-router/pull/9477), [#9496](https://github.com/remix-run/react-router/pull/9496))
- Support `basename` and relative routing in `loader`/`action` redirects ([#9447](https://github.com/remix-run/react-router/pull/9447))
- Ignore pathless layout routes when looking for proper submission `action` function ([#9455](https://github.com/remix-run/react-router/pull/9455))
- properly support `index` routes with a `path` in `useResolvedPath` ([#9486](https://github.com/remix-run/react-router/pull/9486))
- Add UMD build for `@remix-run/router` ([#9446](https://github.com/remix-run/react-router/pull/9446))
- fix `createURL` in local file execution in Firefox ([#9464](https://github.com/remix-run/react-router/pull/9464))
- Updates to `unstable_createStaticHandler` for incorporating into Remix ([#9482](https://github.com/remix-run/react-router/pull/9482), [#9465](https://github.com/remix-run/react-router/pull/9465))
## 1.0.2
### Patch Changes
- Reset `actionData` after a successful action redirect ([#9334](https://github.com/remix-run/react-router/pull/9334))
- Update `matchPath` to avoid false positives on dash-separated segments ([#9300](https://github.com/remix-run/react-router/pull/9300))
- If an index route has children, it will result in a runtime error. We have strengthened our `RouteObject`/`RouteProps` types to surface the error in TypeScript. ([#9366](https://github.com/remix-run/react-router/pull/9366))
## 1.0.1
### Patch Changes
- Preserve state from `initialEntries` ([#9288](https://github.com/remix-run/react-router/pull/9288))
- Preserve `?index` for fetcher get submissions to index routes ([#9312](https://github.com/remix-run/react-router/pull/9312))
## 1.0.0
This is the first stable release of `@remix-run/router`, which provides all the underlying routing and data loading/mutation logic for `react-router`. You should _not_ be using this package directly unless you are authoring a routing library similar to `react-router`.
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/en/6.4.0/start/overview) and the [tutorial](https://reactrouter.com/en/6.4.0/start/tutorial).
For an overview of the features provided by `@remix-run/router`, please check out the [`README`](./README.md).

23
node_modules/@remix-run/router/LICENSE.md generated vendored Normal file
View file

@ -0,0 +1,23 @@
MIT License
Copyright (c) React Training LLC 2015-2019
Copyright (c) Remix Software Inc. 2020-2021
Copyright (c) Shopify Inc. 2022-2023
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

135
node_modules/@remix-run/router/README.md generated vendored Normal file
View file

@ -0,0 +1,135 @@
# Remix Router
The `@remix-run/router` package is a framework-agnostic routing package (sometimes referred to as a browser-emulator) that serves as the heart of [React Router][react-router] and [Remix][remix] and provides all the core functionality for routing coupled with data loading and data mutations. It comes with built-in handling of errors, race-conditions, interruptions, cancellations, lazy-loading data, and much, much more.
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]
>
> 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].
## API
A Router instance can be created using `createRouter`:
```js
// Create and initialize a router. "initialize" contains all side effects
// including history listeners and kicking off the initial data fetch
let router = createRouter({
// 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();
```
Internally, the Router represents the state in an object of the following format, which is available through `router.state`. You can also register a subscriber of the signature `(state: RouterState) => void` to execute when the state updates via `router.subscribe()`;
```ts
interface RouterState {
// False during the initial data load, true once we have our initial data
initialized: boolean;
// The `history` action of the most recently completed navigation
historyAction: Action;
// The current location of the router. During a navigation this reflects
// the "old" location and is updated upon completion of the navigation
location: Location;
// The current set of route matches
matches: DataRouteMatch[];
// The state of the current navigation
navigation: Navigation;
// The state of any in-progress router.revalidate() calls
revalidation: RevalidationState;
// Data from the loaders for the current matches
loaderData: RouteData;
// Data from the action for the current matches
actionData: RouteData | null;
// Errors thrown from loaders/actions for the current matches
errors: RouteData | null;
// Map of all active fetchers
fetchers: Map<string, Fetcher>;
// Scroll position to restore to for the active Location, false if we
// should not restore, or null if we don't have a saved position
// Note: must be enabled via router.enableScrollRestoration()
restoreScrollPosition: number | false | null;
// Proxied `preventScrollReset` value passed to router.navigate()
preventScrollReset: boolean;
}
```
### Navigations
All navigations are done through the `router.navigate` API which is overloaded to support different types of navigations:
```js
// Link navigation (pushes onto the history stack by default)
router.navigate("/page");
// Link navigation (replacing the history stack)
router.navigate("/page", { replace: true });
// Pop navigation (moving backward/forward in the history stack)
router.navigate(-1);
// Form submission navigation
let formData = new FormData();
formData.append(key, value);
router.navigate("/page", {
formMethod: "post",
formData,
});
// Relative routing from a source routeId
router.navigate("../../somewhere", {
fromRouteId: "active-route-id",
});
```
### Fetchers
Fetchers are a mechanism to call loaders/actions without triggering a navigation, and are done through the `router.fetch()` API. All fetch calls require a unique key to identify the fetcher.
```js
// Execute the loader for /page
router.fetch("key", "/page");
// Submit to the action for /page
let formData = new FormData();
formData.append(key, value);
router.fetch("key", "/page", {
formMethod: "post",
formData,
});
```
### Revalidation
By default, active loaders will revalidate after any navigation or fetcher mutation. If you need to kick off a revalidation for other use-cases, you can use `router.revalidate()` to re-execute all active loaders.
### 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
[remix]: https://remix.run
[react-router-repo]: https://github.com/remix-run/react-router
[remix-routers-repo]: https://github.com/brophdawg11/remix-routers
[api-development-strategy]: https://reactrouter.com/v6/guides/api-development-strategy
[future-flags-post]: https://remix.run/blog/future-flags

250
node_modules/@remix-run/router/dist/history.d.ts generated vendored Normal file
View file

@ -0,0 +1,250 @@
/**
* Actions represent the type of change to a location value.
*/
export declare enum Action {
/**
* A POP indicates a change to an arbitrary index in the history stack, such
* as a back or forward navigation. It does not describe the direction of the
* navigation, only that the current index changed.
*
* Note: This is the default action for newly created history objects.
*/
Pop = "POP",
/**
* A PUSH indicates a new entry being added to the history stack, such as when
* a link is clicked and a new page loads. When this happens, all subsequent
* entries in the stack are lost.
*/
Push = "PUSH",
/**
* A REPLACE indicates the entry at the current index in the history stack
* being replaced by a new one.
*/
Replace = "REPLACE"
}
/**
* The pathname, search, and hash values of a URL.
*/
export interface Path {
/**
* A URL pathname, beginning with a /.
*/
pathname: string;
/**
* A URL search string, beginning with a ?.
*/
search: string;
/**
* A URL fragment identifier, beginning with a #.
*/
hash: string;
}
/**
* An entry in a history stack. A location contains information about the
* URL path, as well as possibly some arbitrary state and a key.
*/
export interface Location<State = any> extends Path {
/**
* A value of arbitrary data associated with this location.
*/
state: State;
/**
* A unique string associated with this location. May be used to safely store
* and retrieve data in some other storage API, like `localStorage`.
*
* Note: This value is always "default" on the initial location.
*/
key: string;
}
/**
* A change to the current location.
*/
export interface Update {
/**
* The action that triggered the change.
*/
action: Action;
/**
* The new location.
*/
location: Location;
/**
* The delta between this location and the former location in the history stack
*/
delta: number | null;
}
/**
* A function that receives notifications about location changes.
*/
export interface Listener {
(update: Update): void;
}
/**
* Describes a location that is the destination of some navigation, either via
* `history.push` or `history.replace`. This may be either a URL or the pieces
* of a URL path.
*/
export type To = string | Partial<Path>;
/**
* A history is an interface to the navigation stack. The history serves as the
* source of truth for the current location, as well as provides a set of
* methods that may be used to change it.
*
* It is similar to the DOM's `window.history` object, but with a smaller, more
* focused API.
*/
export interface History {
/**
* The last action that modified the current location. This will always be
* Action.Pop when a history instance is first created. This value is mutable.
*/
readonly action: Action;
/**
* The current location. This value is mutable.
*/
readonly location: Location;
/**
* Returns a valid href for the given `to` value that may be used as
* the value of an <a href> attribute.
*
* @param to - The destination URL
*/
createHref(to: To): string;
/**
* Returns a URL for the given `to` value
*
* @param to - The destination URL
*/
createURL(to: To): URL;
/**
* Encode a location the same way window.history would do (no-op for memory
* history) so we ensure our PUSH/REPLACE navigations for data routers
* behave the same as POP
*
* @param to Unencoded path
*/
encodeLocation(to: To): Path;
/**
* Pushes a new location onto the history stack, increasing its length by one.
* If there were any entries in the stack after the current one, they are
* lost.
*
* @param to - The new URL
* @param state - Data to associate with the new location
*/
push(to: To, state?: any): void;
/**
* Replaces the current location in the history stack with a new one. The
* location that was replaced will no longer be available.
*
* @param to - The new URL
* @param state - Data to associate with the new location
*/
replace(to: To, state?: any): void;
/**
* Navigates `n` entries backward/forward in the history stack relative to the
* current index. For example, a "back" navigation would use go(-1).
*
* @param delta - The delta in the stack index
*/
go(delta: number): void;
/**
* Sets up a listener that will be called whenever the current location
* changes.
*
* @param listener - A function that will be called when the location changes
* @returns unlisten - A function that may be used to stop listening
*/
listen(listener: Listener): () => void;
}
/**
* A user-supplied object that describes a location. Used when providing
* entries to `createMemoryHistory` via its `initialEntries` option.
*/
export type InitialEntry = string | Partial<Location>;
export type MemoryHistoryOptions = {
initialEntries?: InitialEntry[];
initialIndex?: number;
v5Compat?: boolean;
};
/**
* A memory history stores locations in memory. This is useful in stateful
* environments where there is no web browser, such as node tests or React
* Native.
*/
export interface MemoryHistory extends History {
/**
* The current index in the history stack.
*/
readonly index: number;
}
/**
* Memory history stores the current location in memory. It is designed for use
* in stateful non-browser environments like tests and React Native.
*/
export declare function createMemoryHistory(options?: MemoryHistoryOptions): MemoryHistory;
/**
* A browser history stores the current location in regular URLs in a web
* browser environment. This is the standard for most web apps and provides the
* cleanest URLs the browser's address bar.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory
*/
export interface BrowserHistory extends UrlHistory {
}
export type BrowserHistoryOptions = UrlHistoryOptions;
/**
* Browser history stores the location in regular URLs. This is the standard for
* most web apps, but it requires some configuration on the server to ensure you
* serve the same app at multiple URLs.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
*/
export declare function createBrowserHistory(options?: BrowserHistoryOptions): BrowserHistory;
/**
* A hash history stores the current location in the fragment identifier portion
* of the URL in a web browser environment.
*
* This is ideal for apps that do not control the server for some reason
* (because the fragment identifier is never sent to the server), including some
* shared hosting environments that do not provide fine-grained controls over
* which pages are served at which URLs.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory
*/
export interface HashHistory extends UrlHistory {
}
export type HashHistoryOptions = UrlHistoryOptions;
/**
* Hash history stores the location in window.location.hash. This makes it ideal
* for situations where you don't want to send the location to the server for
* some reason, either because you do cannot configure it or the URL space is
* reserved for something else.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
*/
export declare function createHashHistory(options?: HashHistoryOptions): HashHistory;
/**
* @private
*/
export declare function invariant(value: boolean, message?: string): asserts value;
export declare function invariant<T>(value: T | null | undefined, message?: string): asserts value is T;
export declare function warning(cond: any, message: string): void;
/**
* Creates a Location object with a unique key from the given Path
*/
export declare function createLocation(current: string | Location, to: To, state?: any, key?: string): Readonly<Location>;
/**
* Creates a string URL path from the given pathname, search, and hash components.
*/
export declare function createPath({ pathname, search, hash, }: Partial<Path>): string;
/**
* Parses a string URL path into its separate pathname, search, and hash components.
*/
export declare function parsePath(path: string): Partial<Path>;
export interface UrlHistory extends History {
}
export type UrlHistoryOptions = {
window?: Window;
v5Compat?: boolean;
};

9
node_modules/@remix-run/router/dist/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,9 @@
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticPatchRoutesOnNavigationFunction, AgnosticPatchRoutesOnNavigationFunctionArgs, AgnosticRouteMatch, AgnosticRouteObject, DataStrategyFunction, DataStrategyFunctionArgs, DataStrategyMatch, DataStrategyResult, ErrorResponse, FormEncType, FormMethod, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathParam, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, DataWithResponseInit as UNSAFE_DataWithResponseInit, } from "./utils";
export { AbortedDeferredError, data, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, redirectDocument, replace, resolvePath, resolveTo, stripBasename, } from "./utils";
export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
export { Action, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, parsePath, } from "./history";
export * from "./router";
/** @internal */
export type { RouteManifest as UNSAFE_RouteManifest } from "./utils";
export { DeferredData as UNSAFE_DeferredData, ErrorResponseImpl as UNSAFE_ErrorResponseImpl, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, convertRouteMatchToUiMatch as UNSAFE_convertRouteMatchToUiMatch, decodePath as UNSAFE_decodePath, getResolveToMatches as UNSAFE_getResolveToMatches, } from "./utils";
export { invariant as UNSAFE_invariant, warning as UNSAFE_warning, } from "./history";

5607
node_modules/@remix-run/router/dist/router.cjs.js generated vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

525
node_modules/@remix-run/router/dist/router.d.ts generated vendored Normal file
View file

@ -0,0 +1,525 @@
import type { History, Location, Path, To } from "./history";
import { Action as HistoryAction } from "./history";
import type { AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteObject, DataStrategyFunction, DeferredData, DetectErrorBoundaryFunction, FormEncType, HTMLFormMethod, MapRoutePropertiesFunction, RouteData, Submission, UIMatch, AgnosticPatchRoutesOnNavigationFunction, DataWithResponseInit } from "./utils";
/**
* A Router instance manages all navigation and data loading/mutations
*/
export interface Router {
/**
* @internal
* PRIVATE - DO NOT USE
*
* Return the basename for the router
*/
get basename(): RouterInit["basename"];
/**
* @internal
* PRIVATE - DO NOT USE
*
* Return the future config for the router
*/
get future(): FutureConfig;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Return the current state of the router
*/
get state(): RouterState;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Return the routes for this router instance
*/
get routes(): AgnosticDataRouteObject[];
/**
* @internal
* PRIVATE - DO NOT USE
*
* 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
* initial data fetches. Returns a function to cleanup listeners and abort
* any in-progress loads
*/
initialize(): Router;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Subscribe to router.state updates
*
* @param fn function to call with the new state
*/
subscribe(fn: RouterSubscriber): () => void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Enable scroll restoration behavior in the router
*
* @param savedScrollPositions Object that will manage positions, in case
* it's being restored from sessionStorage
* @param getScrollPosition Function to get the active Y scroll position
* @param getKey Function to get the key to use for restoration
*/
enableScrollRestoration(savedScrollPositions: Record<string, number>, getScrollPosition: GetScrollPositionFunction, getKey?: GetScrollRestorationKeyFunction): () => void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Navigate forward/backward in the history stack
* @param to Delta to move in the history stack
*/
navigate(to: number): Promise<void>;
/**
* Navigate to the given path
* @param to Path to navigate to
* @param opts Navigation options (method, submission, etc.)
*/
navigate(to: To | null, opts?: RouterNavigateOptions): Promise<void>;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Trigger a fetcher load/submission
*
* @param key Fetcher key
* @param routeId Route that owns the fetcher
* @param href href to fetch
* @param opts Fetcher options, (method, submission, etc.)
*/
fetch(key: string, routeId: string, href: string | null, opts?: RouterFetchOptions): void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Trigger a revalidation of all current route loaders and fetcher loads
*/
revalidate(): void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Utility function to create an href for the given location
* @param location
*/
createHref(location: Location | URL): string;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Utility function to URL encode a destination path according to the internal
* history implementation
* @param to
*/
encodeLocation(to: To): Path;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Get/create a fetcher for the given key
* @param key
*/
getFetcher<TData = any>(key: string): Fetcher<TData>;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Delete the fetcher for a given key
* @param key
*/
deleteFetcher(key: string): void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Cleanup listeners and abort any in-progress loads
*/
dispose(): void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Get a navigation blocker
* @param key The identifier for the blocker
* @param fn The blocker function implementation
*/
getBlocker(key: string, fn: BlockerFunction): Blocker;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Delete a navigation blocker
* @param key The identifier for the blocker
*/
deleteBlocker(key: string): void;
/**
* @internal
* PRIVATE DO NOT USE
*
* Patch additional children routes into an existing parent route
* @param routeId The parent route id or a callback function accepting `patch`
* to perform batch patching
* @param children The additional children routes
*/
patchRoutes(routeId: string | null, children: AgnosticRouteObject[]): void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* HMR needs to pass in-flight route updates to React Router
* TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)
*/
_internalSetRoutes(routes: AgnosticRouteObject[]): void;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Internal fetch AbortControllers accessed by unit tests
*/
_internalFetchControllers: Map<string, AbortController>;
/**
* @internal
* PRIVATE - DO NOT USE
*
* Internal pending DeferredData instances accessed by unit tests
*/
_internalActiveDeferreds: Map<string, DeferredData>;
}
/**
* State maintained internally by the router. During a navigation, all states
* reflect the the "old" location unless otherwise noted.
*/
export interface RouterState {
/**
* The action of the most recent navigation
*/
historyAction: HistoryAction;
/**
* The current location reflected by the router
*/
location: Location;
/**
* The current set of route matches
*/
matches: AgnosticDataRouteMatch[];
/**
* Tracks whether we've completed our initial data load
*/
initialized: boolean;
/**
* Current scroll position we should start at for a new view
* - number -> scroll position to restore to
* - false -> do not restore scroll at all (used during submissions)
* - null -> don't have a saved position, scroll to hash or top of page
*/
restoreScrollPosition: number | false | null;
/**
* Indicate whether this navigation should skip resetting the scroll position
* if we are unable to restore the scroll position
*/
preventScrollReset: boolean;
/**
* Tracks the state of the current navigation
*/
navigation: Navigation;
/**
* Tracks any in-progress revalidations
*/
revalidation: RevalidationState;
/**
* Data from the loaders for the current matches
*/
loaderData: RouteData;
/**
* Data from the action for the current matches
*/
actionData: RouteData | null;
/**
* Errors caught from loaders for the current matches
*/
errors: RouteData | null;
/**
* Map of current fetchers
*/
fetchers: Map<string, Fetcher>;
/**
* Map of current blockers
*/
blockers: Map<string, Blocker>;
}
/**
* Data that can be passed into hydrate a Router from SSR
*/
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;
v7_skipActionErrorRevalidation: boolean;
}
/**
* Initialization options for createRouter
*/
export interface RouterInit {
routes: AgnosticRouteObject[];
history: History;
basename?: string;
/**
* @deprecated Use `mapRouteProperties` instead
*/
detectErrorBoundary?: DetectErrorBoundaryFunction;
mapRouteProperties?: MapRoutePropertiesFunction;
future?: Partial<FutureConfig>;
hydrationData?: HydrationState;
window?: Window;
dataStrategy?: DataStrategyFunction;
patchRoutesOnNavigation?: AgnosticPatchRoutesOnNavigationFunction;
}
/**
* State returned from a server-side query() call
*/
export interface StaticHandlerContext {
basename: Router["basename"];
location: RouterState["location"];
matches: RouterState["matches"];
loaderData: RouterState["loaderData"];
actionData: RouterState["actionData"];
errors: RouterState["errors"];
statusCode: number;
loaderHeaders: Record<string, Headers>;
actionHeaders: Record<string, Headers>;
activeDeferreds: Record<string, DeferredData> | null;
_deepestRenderedBoundaryId?: string | null;
}
/**
* A StaticHandler instance manages a singular SSR navigation/fetch event
*/
export interface StaticHandler {
dataRoutes: AgnosticDataRouteObject[];
query(request: Request, opts?: {
requestContext?: unknown;
skipLoaderErrorBubbling?: boolean;
dataStrategy?: DataStrategyFunction;
}): Promise<StaticHandlerContext | Response>;
queryRoute(request: Request, opts?: {
routeId?: string;
requestContext?: unknown;
dataStrategy?: DataStrategyFunction;
}): Promise<any>;
}
type ViewTransitionOpts = {
currentLocation: Location;
nextLocation: Location;
};
/**
* Subscriber function signature for changes to router state
*/
export interface RouterSubscriber {
(state: RouterState, opts: {
deletedFetchers: string[];
viewTransitionOpts?: ViewTransitionOpts;
flushSync: boolean;
}): void;
}
/**
* Function signature for determining the key to be used in scroll restoration
* for a given location
*/
export interface GetScrollRestorationKeyFunction {
(location: Location, matches: UIMatch[]): string | null;
}
/**
* Function signature for determining the current scroll position
*/
export interface GetScrollPositionFunction {
(): number;
}
export type RelativeRoutingType = "route" | "path";
type BaseNavigateOrFetchOptions = {
preventScrollReset?: boolean;
relative?: RelativeRoutingType;
flushSync?: boolean;
};
type BaseNavigateOptions = BaseNavigateOrFetchOptions & {
replace?: boolean;
state?: any;
fromRouteId?: string;
viewTransition?: boolean;
};
type BaseSubmissionOptions = {
formMethod?: HTMLFormMethod;
formEncType?: FormEncType;
} & ({
formData: FormData;
body?: undefined;
} | {
formData?: undefined;
body: any;
});
/**
* Options for a navigate() call for a normal (non-submission) navigation
*/
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 type RouterFetchOptions = LoadFetchOptions | SubmitFetchOptions;
/**
* Potential states for state.navigation
*/
export type NavigationStates = {
Idle: {
state: "idle";
location: undefined;
formMethod: undefined;
formAction: undefined;
formEncType: undefined;
formData: undefined;
json: undefined;
text: undefined;
};
Loading: {
state: "loading";
location: Location;
formMethod: Submission["formMethod"] | undefined;
formAction: Submission["formAction"] | undefined;
formEncType: Submission["formEncType"] | undefined;
formData: Submission["formData"] | undefined;
json: Submission["json"] | undefined;
text: Submission["text"] | undefined;
};
Submitting: {
state: "submitting";
location: Location;
formMethod: Submission["formMethod"];
formAction: Submission["formAction"];
formEncType: Submission["formEncType"];
formData: Submission["formData"];
json: Submission["json"];
text: Submission["text"];
};
};
export type Navigation = NavigationStates[keyof NavigationStates];
export type RevalidationState = "idle" | "loading";
/**
* Potential states for fetchers
*/
type FetcherStates<TData = any> = {
Idle: {
state: "idle";
formMethod: undefined;
formAction: undefined;
formEncType: undefined;
text: undefined;
formData: undefined;
json: undefined;
data: TData | undefined;
};
Loading: {
state: "loading";
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;
};
Submitting: {
state: "submitting";
formMethod: Submission["formMethod"];
formAction: Submission["formAction"];
formEncType: Submission["formEncType"];
text: Submission["text"];
formData: Submission["formData"];
json: Submission["json"];
data: TData | undefined;
};
};
export type Fetcher<TData = any> = FetcherStates<TData>[keyof FetcherStates<TData>];
interface BlockerBlocked {
state: "blocked";
reset(): void;
proceed(): void;
location: Location;
}
interface BlockerUnblocked {
state: "unblocked";
reset: undefined;
proceed: undefined;
location: undefined;
}
interface BlockerProceeding {
state: "proceeding";
reset: undefined;
proceed: undefined;
location: Location;
}
export type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;
export type BlockerFunction = (args: {
currentLocation: Location;
nextLocation: Location;
historyAction: HistoryAction;
}) => boolean;
export declare const IDLE_NAVIGATION: NavigationStates["Idle"];
export declare const IDLE_FETCHER: FetcherStates["Idle"];
export declare const IDLE_BLOCKER: BlockerUnblocked;
/**
* Create a router and listen to history POP navigations
*/
export declare function createRouter(init: RouterInit): Router;
export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol;
/**
* Future flags to toggle new feature behavior
*/
export interface StaticHandlerFutureConfig {
v7_relativeSplatPath: boolean;
v7_throwAbortReason: boolean;
}
export interface CreateStaticHandlerOptions {
basename?: string;
/**
* @deprecated Use `mapRouteProperties` instead
*/
detectErrorBoundary?: DetectErrorBoundaryFunction;
mapRouteProperties?: MapRoutePropertiesFunction;
future?: Partial<StaticHandlerFutureConfig>;
}
export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler;
/**
* Given an existing StaticHandlerContext and an error thrown at render time,
* provide an updated StaticHandlerContext suitable for a second SSR render
*/
export declare function getStaticContextFromError(routes: AgnosticDataRouteObject[], context: StaticHandlerContext, error: any): StaticHandlerContext;
export declare function isDataWithResponseInit(value: any): value is DataWithResponseInit<unknown>;
export declare function isDeferredData(value: any): value is DeferredData;
export {};

5038
node_modules/@remix-run/router/dist/router.js generated vendored Normal file

File diff suppressed because it is too large Load diff

1
node_modules/@remix-run/router/dist/router.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

5613
node_modules/@remix-run/router/dist/router.umd.js generated vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

12
node_modules/@remix-run/router/dist/router.umd.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

555
node_modules/@remix-run/router/dist/utils.d.ts generated vendored Normal file
View file

@ -0,0 +1,555 @@
import type { Location, Path, To } from "./history";
/**
* Map of routeId -> data returned from a loader/action/error
*/
export interface RouteData {
[routeId: string]: any;
}
export declare enum ResultType {
data = "data",
deferred = "deferred",
redirect = "redirect",
error = "error"
}
/**
* Successful result from a loader or action
*/
export interface SuccessResult {
type: ResultType.data;
data: unknown;
statusCode?: number;
headers?: Headers;
}
/**
* Successful defer() result from a loader or action
*/
export interface DeferredResult {
type: ResultType.deferred;
deferredData: DeferredData;
statusCode?: number;
headers?: Headers;
}
/**
* Redirect result from a loader or action
*/
export interface RedirectResult {
type: ResultType.redirect;
response: Response;
}
/**
* Unsuccessful result from a loader or action
*/
export interface ErrorResult {
type: ResultType.error;
error: unknown;
statusCode?: number;
headers?: Headers;
}
/**
* Result from a loader or action - potentially successful or unsuccessful
*/
export type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult;
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
* Internal interface to pass around for action submissions, not intended for
* external consumption
*/
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;
};
/**
* @private
* Arguments passed to route loader/action functions. Same for now but we keep
* this as a private implementation detail in case they diverge in the future.
*/
interface DataFunctionArgs<Context> {
request: Request;
params: Params;
context?: Context;
}
/**
* Arguments passed to loader functions
*/
export interface LoaderFunctionArgs<Context = any> extends DataFunctionArgs<Context> {
}
/**
* Arguments passed to action functions
*/
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 type LoaderFunction<Context = any> = {
(args: LoaderFunctionArgs<Context>, handlerCtx?: unknown): DataFunctionReturnValue;
} & {
hydrate?: boolean;
};
/**
* Route action function signature
*/
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"];
actionStatus?: number;
actionResult?: any;
defaultShouldRevalidate: boolean;
}
/**
* Route shouldRevalidate function signature. This runs after any submission
* (navigation or fetcher), so we flatten the navigation/fetcher submission
* onto the arguments. It shouldn't matter whether it came from a navigation
* or a fetcher, what really matters is the URLs and the formData since loaders
* have to re-run based on the data models that were potentially mutated.
*/
export interface ShouldRevalidateFunction {
(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> {
shouldLoad: boolean;
resolve: (handlerOverride?: (handler: (ctx?: unknown) => DataFunctionReturnValue) => DataFunctionReturnValue) => Promise<DataStrategyResult>;
}
export interface DataStrategyFunctionArgs<Context = any> extends DataFunctionArgs<Context> {
matches: DataStrategyMatch[];
fetcherKey: string | null;
}
/**
* Result from a loader or action called via dataStrategy
*/
export interface DataStrategyResult {
type: "data" | "error";
result: unknown;
}
export interface DataStrategyFunction {
(args: DataStrategyFunctionArgs): Promise<Record<string, DataStrategyResult>>;
}
export type AgnosticPatchRoutesOnNavigationFunctionArgs<O extends AgnosticRouteObject = AgnosticRouteObject, M extends AgnosticRouteMatch = AgnosticRouteMatch> = {
signal: AbortSignal;
path: string;
matches: M[];
fetcherKey: string | undefined;
patch: (routeId: string | null, children: O[]) => void;
};
export type AgnosticPatchRoutesOnNavigationFunction<O extends AgnosticRouteObject = AgnosticRouteObject, M extends AgnosticRouteMatch = AgnosticRouteMatch> = (opts: AgnosticPatchRoutesOnNavigationFunctionArgs<O, M>) => void | Promise<void>;
/**
* 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
*/
type AgnosticBaseRouteObject = {
caseSensitive?: boolean;
path?: string;
id?: string;
loader?: LoaderFunction | boolean;
action?: ActionFunction | boolean;
hasErrorBoundary?: boolean;
shouldRevalidate?: ShouldRevalidateFunction;
handle?: any;
lazy?: LazyRouteFunction<AgnosticBaseRouteObject>;
};
/**
* Index routes must not have children
*/
export type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {
children?: undefined;
index: true;
};
/**
* Non-index routes may have children, but cannot have index
*/
export type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {
children?: AgnosticRouteObject[];
index?: false;
};
/**
* A route object represents a logical route, with (optionally) its child
* routes organized in a tree-like structure.
*/
export type AgnosticRouteObject = AgnosticIndexRouteObject | AgnosticNonIndexRouteObject;
export type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {
id: string;
};
export type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {
children?: AgnosticDataRouteObject[];
id: string;
};
/**
* A data route object, which is just a RouteObject with a required unique ID
*/
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;
/**
* Examples:
* "/a/b/*" -> "*"
* ":a" -> "a"
* "/a/:b" -> "b"
* "/a/blahblahblah:b" -> "b"
* "/:a/:b" -> "a" | "b"
* "/:a/b/:c/*" -> "a" | "c" | "*"
*/
export type PathParam<Path extends string> = Path extends "*" | "/*" ? "*" : Path extends `${infer Rest}/*` ? "*" | _PathParam<Rest> : _PathParam<Path>;
export type ParamParseKey<Segment extends string> = [
PathParam<Segment>
] extends [never] ? string : PathParam<Segment>;
/**
* The parameters that were parsed from the URL path.
*/
export type Params<Key extends string = string> = {
readonly [key in Key]: string | undefined;
};
/**
* A RouteMatch contains info about how a route matched a URL.
*/
export interface AgnosticRouteMatch<ParamKey extends string = string, RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject> {
/**
* The names and values of dynamic parameters in the URL.
*/
params: Params<ParamKey>;
/**
* The portion of the URL pathname that was matched.
*/
pathname: string;
/**
* The portion of the URL pathname that was matched before child routes.
*/
pathnameBase: string;
/**
* The route object that was used to match.
*/
route: RouteObjectType;
}
export interface AgnosticDataRouteMatch extends AgnosticRouteMatch<string, AgnosticDataRouteObject> {
}
export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], mapRouteProperties: MapRoutePropertiesFunction, parentPath?: string[], manifest?: RouteManifest): AgnosticDataRouteObject[];
/**
* Matches the given routes to a location and returns the match data.
*
* @see https://reactrouter.com/v6/utils/match-routes
*/
export declare function matchRoutes<RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject>(routes: RouteObjectType[], locationArg: Partial<Location> | string, basename?: string): AgnosticRouteMatch<string, RouteObjectType>[] | null;
export declare function matchRoutesImpl<RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject>(routes: RouteObjectType[], locationArg: Partial<Location> | string, basename: string, allowPartial: boolean): 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;
/**
* Returns a path with params interpolated.
*
* @see https://reactrouter.com/v6/utils/generate-path
*/
export declare function generatePath<Path extends string>(originalPath: Path, params?: {
[key in PathParam<Path>]: string | null;
}): string;
/**
* A PathPattern is used to match on some portion of a URL pathname.
*/
export interface PathPattern<Path extends string = string> {
/**
* A string to match against a URL pathname. May contain `:id`-style segments
* to indicate placeholders for dynamic parameters. May also end with `/*` to
* indicate matching the rest of the URL pathname.
*/
path: Path;
/**
* Should be `true` if the static portions of the `path` should be matched in
* the same case.
*/
caseSensitive?: boolean;
/**
* Should be `true` if this pattern should match the entire URL pathname.
*/
end?: boolean;
}
/**
* A PathMatch contains info about how a PathPattern matched on a URL pathname.
*/
export interface PathMatch<ParamKey extends string = string> {
/**
* The names and values of dynamic parameters in the URL.
*/
params: Params<ParamKey>;
/**
* The portion of the URL pathname that was matched.
*/
pathname: string;
/**
* The portion of the URL pathname that was matched before child routes.
*/
pathnameBase: string;
/**
* The pattern that was used to match.
*/
pattern: PathPattern;
}
/**
* Performs pattern matching on a URL pathname and returns information about
* the match.
*
* @see https://reactrouter.com/v6/utils/match-path
*/
export declare function matchPath<ParamKey extends ParamParseKey<Path>, Path extends string>(pattern: PathPattern<Path> | Path, pathname: string): PathMatch<ParamKey> | null;
export declare function decodePath(value: string): string;
/**
* @private
*/
export declare function stripBasename(pathname: string, basename: string): string | null;
/**
* Returns a resolved path object relative to the given pathname.
*
* @see https://reactrouter.com/v6/utils/resolve-path
*/
export declare function resolvePath(to: To, fromPathname?: string): Path;
/**
* @private
*
* When processing relative navigation we want to ignore ancestor routes that
* do not contribute to the path, such that index/pathless layout routes don't
* interfere.
*
* For example, when moving a route element into an index route and/or a
* pathless layout route, relative link behavior contained within should stay
* the same. Both of the following examples should link back to the root:
*
* <Route path="/">
* <Route path="accounts" element={<Link to=".."}>
* </Route>
*
* <Route path="/">
* <Route path="accounts">
* <Route element={<AccountsLayout />}> // <-- Does not contribute
* <Route index element={<Link to=".."} /> // <-- Does not contribute
* </Route
* </Route>
* </Route>
*/
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[];
/**
* @private
*/
export declare function resolveTo(toArg: To, routePathnames: string[], locationPathname: string, isPathRelative?: boolean): Path;
/**
* @private
*/
export declare function getToPathname(to: To): string | undefined;
/**
* @private
*/
export declare const joinPaths: (paths: string[]) => string;
/**
* @private
*/
export declare const normalizePathname: (pathname: string) => string;
/**
* @private
*/
export declare const normalizeSearch: (search: string) => string;
/**
* @private
*/
export declare const normalizeHash: (hash: string) => string;
export type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response;
/**
* This is a shortcut for creating `application/json` responses. Converts `data`
* to JSON and sets the `Content-Type` header.
*
* @deprecated The `json` method is deprecated in favor of returning raw objects.
* This method will be removed in v7.
*/
export declare const json: JsonFunction;
export declare class DataWithResponseInit<D> {
type: string;
data: D;
init: ResponseInit | null;
constructor(data: D, init?: ResponseInit);
}
/**
* Create "responses" that contain `status`/`headers` without forcing
* serialization into an actual `Response` - used by Remix single fetch
*/
export declare function data<D>(data: D, init?: number | ResponseInit): DataWithResponseInit<D>;
export interface TrackedPromise extends Promise<any> {
_tracked?: boolean;
_data?: any;
_error?: any;
}
export declare class AbortedDeferredError extends Error {
}
export declare class DeferredData {
private pendingKeysSet;
private controller;
private abortPromise;
private unlistenAbortSignal;
private subscribers;
data: Record<string, unknown>;
init?: ResponseInit;
deferredKeys: string[];
constructor(data: Record<string, unknown>, responseInit?: ResponseInit);
private trackPromise;
private onSettle;
private emit;
subscribe(fn: (aborted: boolean, settledKey?: string) => void): () => boolean;
cancel(): void;
resolveData(signal: AbortSignal): Promise<boolean>;
get done(): boolean;
get unwrappedData(): {};
get pendingKeys(): string[];
}
export type DeferFunction = (data: Record<string, unknown>, init?: number | ResponseInit) => DeferredData;
/**
* @deprecated The `defer` method is deprecated in favor of returning raw
* objects. This method will be removed in v7.
*/
export declare const defer: DeferFunction;
export type RedirectFunction = (url: string, init?: number | ResponseInit) => Response;
/**
* A redirect response. Sets the status code and the `Location` header.
* Defaults to "302 Found".
*/
export declare const redirect: RedirectFunction;
/**
* 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;
/**
* A redirect response that will perform a `history.replaceState` instead of a
* `history.pushState` for client-side navigation redirects.
* Sets the status code and the `Location` header.
* Defaults to "302 Found".
*/
export declare const replace: 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 ErrorResponseImpl implements ErrorResponse {
status: number;
statusText: string;
data: any;
private error?;
private internal;
constructor(status: number, statusText: string | undefined, data: any, internal?: boolean);
}
/**
* Check if the given error is an ErrorResponse generated from a 4xx/5xx
* Response thrown from an action/loader
*/
export declare function isRouteErrorResponse(error: any): error is ErrorResponse;
export {};

746
node_modules/@remix-run/router/history.ts generated vendored Normal file
View file

@ -0,0 +1,746 @@
////////////////////////////////////////////////////////////////////////////////
//#region Types and Constants
////////////////////////////////////////////////////////////////////////////////
/**
* Actions represent the type of change to a location value.
*/
export enum Action {
/**
* A POP indicates a change to an arbitrary index in the history stack, such
* as a back or forward navigation. It does not describe the direction of the
* navigation, only that the current index changed.
*
* Note: This is the default action for newly created history objects.
*/
Pop = "POP",
/**
* A PUSH indicates a new entry being added to the history stack, such as when
* a link is clicked and a new page loads. When this happens, all subsequent
* entries in the stack are lost.
*/
Push = "PUSH",
/**
* A REPLACE indicates the entry at the current index in the history stack
* being replaced by a new one.
*/
Replace = "REPLACE",
}
/**
* The pathname, search, and hash values of a URL.
*/
export interface Path {
/**
* A URL pathname, beginning with a /.
*/
pathname: string;
/**
* A URL search string, beginning with a ?.
*/
search: string;
/**
* A URL fragment identifier, beginning with a #.
*/
hash: string;
}
// TODO: (v7) Change the Location generic default from `any` to `unknown` and
// remove Remix `useLocation` wrapper.
/**
* An entry in a history stack. A location contains information about the
* URL path, as well as possibly some arbitrary state and a key.
*/
export interface Location<State = any> extends Path {
/**
* A value of arbitrary data associated with this location.
*/
state: State;
/**
* A unique string associated with this location. May be used to safely store
* and retrieve data in some other storage API, like `localStorage`.
*
* Note: This value is always "default" on the initial location.
*/
key: string;
}
/**
* A change to the current location.
*/
export interface Update {
/**
* The action that triggered the change.
*/
action: Action;
/**
* The new location.
*/
location: Location;
/**
* The delta between this location and the former location in the history stack
*/
delta: number | null;
}
/**
* A function that receives notifications about location changes.
*/
export interface Listener {
(update: Update): void;
}
/**
* Describes a location that is the destination of some navigation, either via
* `history.push` or `history.replace`. This may be either a URL or the pieces
* of a URL path.
*/
export type To = string | Partial<Path>;
/**
* A history is an interface to the navigation stack. The history serves as the
* source of truth for the current location, as well as provides a set of
* methods that may be used to change it.
*
* It is similar to the DOM's `window.history` object, but with a smaller, more
* focused API.
*/
export interface History {
/**
* The last action that modified the current location. This will always be
* Action.Pop when a history instance is first created. This value is mutable.
*/
readonly action: Action;
/**
* The current location. This value is mutable.
*/
readonly location: Location;
/**
* Returns a valid href for the given `to` value that may be used as
* the value of an <a href> attribute.
*
* @param to - The destination URL
*/
createHref(to: To): string;
/**
* Returns a URL for the given `to` value
*
* @param to - The destination URL
*/
createURL(to: To): URL;
/**
* Encode a location the same way window.history would do (no-op for memory
* history) so we ensure our PUSH/REPLACE navigations for data routers
* behave the same as POP
*
* @param to Unencoded path
*/
encodeLocation(to: To): Path;
/**
* Pushes a new location onto the history stack, increasing its length by one.
* If there were any entries in the stack after the current one, they are
* lost.
*
* @param to - The new URL
* @param state - Data to associate with the new location
*/
push(to: To, state?: any): void;
/**
* Replaces the current location in the history stack with a new one. The
* location that was replaced will no longer be available.
*
* @param to - The new URL
* @param state - Data to associate with the new location
*/
replace(to: To, state?: any): void;
/**
* Navigates `n` entries backward/forward in the history stack relative to the
* current index. For example, a "back" navigation would use go(-1).
*
* @param delta - The delta in the stack index
*/
go(delta: number): void;
/**
* Sets up a listener that will be called whenever the current location
* changes.
*
* @param listener - A function that will be called when the location changes
* @returns unlisten - A function that may be used to stop listening
*/
listen(listener: Listener): () => void;
}
type HistoryState = {
usr: any;
key?: string;
idx: number;
};
const PopStateEventType = "popstate";
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region Memory History
////////////////////////////////////////////////////////////////////////////////
/**
* A user-supplied object that describes a location. Used when providing
* entries to `createMemoryHistory` via its `initialEntries` option.
*/
export type InitialEntry = string | Partial<Location>;
export type MemoryHistoryOptions = {
initialEntries?: InitialEntry[];
initialIndex?: number;
v5Compat?: boolean;
};
/**
* A memory history stores locations in memory. This is useful in stateful
* environments where there is no web browser, such as node tests or React
* Native.
*/
export interface MemoryHistory extends History {
/**
* The current index in the history stack.
*/
readonly index: number;
}
/**
* Memory history stores the current location in memory. It is designed for use
* in stateful non-browser environments like tests and React Native.
*/
export function createMemoryHistory(
options: MemoryHistoryOptions = {}
): MemoryHistory {
let { initialEntries = ["/"], initialIndex, v5Compat = false } = options;
let entries: Location[]; // Declare so we can access from createMemoryLocation
entries = initialEntries.map((entry, index) =>
createMemoryLocation(
entry,
typeof entry === "string" ? null : entry.state,
index === 0 ? "default" : undefined
)
);
let index = clampIndex(
initialIndex == null ? entries.length - 1 : initialIndex
);
let action = Action.Pop;
let listener: Listener | null = null;
function clampIndex(n: number): number {
return Math.min(Math.max(n, 0), entries.length - 1);
}
function getCurrentLocation(): Location {
return entries[index];
}
function createMemoryLocation(
to: To,
state: any = null,
key?: string
): Location {
let location = createLocation(
entries ? getCurrentLocation().pathname : "/",
to,
state,
key
);
warning(
location.pathname.charAt(0) === "/",
`relative pathnames are not supported in memory history: ${JSON.stringify(
to
)}`
);
return location;
}
function createHref(to: To) {
return typeof to === "string" ? to : createPath(to);
}
let history: MemoryHistory = {
get index() {
return index;
},
get action() {
return action;
},
get location() {
return getCurrentLocation();
},
createHref,
createURL(to) {
return new URL(createHref(to), "http://localhost");
},
encodeLocation(to: To) {
let path = typeof to === "string" ? parsePath(to) : to;
return {
pathname: path.pathname || "",
search: path.search || "",
hash: path.hash || "",
};
},
push(to, state) {
action = Action.Push;
let nextLocation = createMemoryLocation(to, state);
index += 1;
entries.splice(index, entries.length, nextLocation);
if (v5Compat && listener) {
listener({ action, location: nextLocation, delta: 1 });
}
},
replace(to, state) {
action = Action.Replace;
let nextLocation = createMemoryLocation(to, state);
entries[index] = nextLocation;
if (v5Compat && listener) {
listener({ action, location: nextLocation, delta: 0 });
}
},
go(delta) {
action = Action.Pop;
let nextIndex = clampIndex(index + delta);
let nextLocation = entries[nextIndex];
index = nextIndex;
if (listener) {
listener({ action, location: nextLocation, delta });
}
},
listen(fn: Listener) {
listener = fn;
return () => {
listener = null;
};
},
};
return history;
}
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region Browser History
////////////////////////////////////////////////////////////////////////////////
/**
* A browser history stores the current location in regular URLs in a web
* browser environment. This is the standard for most web apps and provides the
* cleanest URLs the browser's address bar.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory
*/
export interface BrowserHistory extends UrlHistory {}
export type BrowserHistoryOptions = UrlHistoryOptions;
/**
* Browser history stores the location in regular URLs. This is the standard for
* most web apps, but it requires some configuration on the server to ensure you
* serve the same app at multiple URLs.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
*/
export function createBrowserHistory(
options: BrowserHistoryOptions = {}
): BrowserHistory {
function createBrowserLocation(
window: Window,
globalHistory: Window["history"]
) {
let { pathname, search, hash } = window.location;
return createLocation(
"",
{ pathname, search, hash },
// state defaults to `null` because `window.history.state` does
(globalHistory.state && globalHistory.state.usr) || null,
(globalHistory.state && globalHistory.state.key) || "default"
);
}
function createBrowserHref(window: Window, to: To) {
return typeof to === "string" ? to : createPath(to);
}
return getUrlBasedHistory(
createBrowserLocation,
createBrowserHref,
null,
options
);
}
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region Hash History
////////////////////////////////////////////////////////////////////////////////
/**
* A hash history stores the current location in the fragment identifier portion
* of the URL in a web browser environment.
*
* This is ideal for apps that do not control the server for some reason
* (because the fragment identifier is never sent to the server), including some
* shared hosting environments that do not provide fine-grained controls over
* which pages are served at which URLs.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory
*/
export interface HashHistory extends UrlHistory {}
export type HashHistoryOptions = UrlHistoryOptions;
/**
* Hash history stores the location in window.location.hash. This makes it ideal
* for situations where you don't want to send the location to the server for
* some reason, either because you do cannot configure it or the URL space is
* reserved for something else.
*
* @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
*/
export function createHashHistory(
options: HashHistoryOptions = {}
): HashHistory {
function createHashLocation(
window: Window,
globalHistory: Window["history"]
) {
let {
pathname = "/",
search = "",
hash = "",
} = parsePath(window.location.hash.substr(1));
// Hash URL should always have a leading / just like window.location.pathname
// does, so if an app ends up at a route like /#something then we add a
// leading slash so all of our path-matching behaves the same as if it would
// in a browser router. This is particularly important when there exists a
// root splat route (<Route path="*">) since that matches internally against
// "/*" and we'd expect /#something to 404 in a hash router app.
if (!pathname.startsWith("/") && !pathname.startsWith(".")) {
pathname = "/" + pathname;
}
return createLocation(
"",
{ pathname, search, hash },
// state defaults to `null` because `window.history.state` does
(globalHistory.state && globalHistory.state.usr) || null,
(globalHistory.state && globalHistory.state.key) || "default"
);
}
function createHashHref(window: Window, to: To) {
let base = window.document.querySelector("base");
let href = "";
if (base && base.getAttribute("href")) {
let url = window.location.href;
let hashIndex = url.indexOf("#");
href = hashIndex === -1 ? url : url.slice(0, hashIndex);
}
return href + "#" + (typeof to === "string" ? to : createPath(to));
}
function validateHashLocation(location: Location, to: To) {
warning(
location.pathname.charAt(0) === "/",
`relative pathnames are not supported in hash history.push(${JSON.stringify(
to
)})`
);
}
return getUrlBasedHistory(
createHashLocation,
createHashHref,
validateHashLocation,
options
);
}
//#endregion
////////////////////////////////////////////////////////////////////////////////
//#region UTILS
////////////////////////////////////////////////////////////////////////////////
/**
* @private
*/
export function invariant(value: boolean, message?: string): asserts value;
export function invariant<T>(
value: T | null | undefined,
message?: string
): asserts value is T;
export function invariant(value: any, message?: string) {
if (value === false || value === null || typeof value === "undefined") {
throw new Error(message);
}
}
export function warning(cond: any, message: string) {
if (!cond) {
// eslint-disable-next-line no-console
if (typeof console !== "undefined") console.warn(message);
try {
// Welcome to debugging history!
//
// This error is thrown as a convenience, so you can more easily
// find the source for a warning that appears in the console by
// enabling "pause on exceptions" in your JavaScript debugger.
throw new Error(message);
// eslint-disable-next-line no-empty
} catch (e) {}
}
}
function createKey() {
return Math.random().toString(36).substr(2, 8);
}
/**
* For browser-based histories, we combine the state and key into an object
*/
function getHistoryState(location: Location, index: number): HistoryState {
return {
usr: location.state,
key: location.key,
idx: index,
};
}
/**
* Creates a Location object with a unique key from the given Path
*/
export function createLocation(
current: string | Location,
to: To,
state: any = null,
key?: string
): Readonly<Location> {
let location: Readonly<Location> = {
pathname: typeof current === "string" ? current : current.pathname,
search: "",
hash: "",
...(typeof to === "string" ? parsePath(to) : to),
state,
// TODO: This could be cleaned up. push/replace should probably just take
// full Locations now and avoid the need to run through this flow at all
// But that's a pretty big refactor to the current test suite so going to
// keep as is for the time being and just let any incoming keys take precedence
key: (to && (to as Location).key) || key || createKey(),
};
return location;
}
/**
* Creates a string URL path from the given pathname, search, and hash components.
*/
export function createPath({
pathname = "/",
search = "",
hash = "",
}: Partial<Path>) {
if (search && search !== "?")
pathname += search.charAt(0) === "?" ? search : "?" + search;
if (hash && hash !== "#")
pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
return pathname;
}
/**
* Parses a string URL path into its separate pathname, search, and hash components.
*/
export function parsePath(path: string): Partial<Path> {
let parsedPath: Partial<Path> = {};
if (path) {
let hashIndex = path.indexOf("#");
if (hashIndex >= 0) {
parsedPath.hash = path.substr(hashIndex);
path = path.substr(0, hashIndex);
}
let searchIndex = path.indexOf("?");
if (searchIndex >= 0) {
parsedPath.search = path.substr(searchIndex);
path = path.substr(0, searchIndex);
}
if (path) {
parsedPath.pathname = path;
}
}
return parsedPath;
}
export interface UrlHistory extends History {}
export type UrlHistoryOptions = {
window?: Window;
v5Compat?: boolean;
};
function getUrlBasedHistory(
getLocation: (window: Window, globalHistory: Window["history"]) => Location,
createHref: (window: Window, to: To) => string,
validateLocation: ((location: Location, to: To) => void) | null,
options: UrlHistoryOptions = {}
): UrlHistory {
let { window = document.defaultView!, v5Compat = false } = options;
let globalHistory = window.history;
let action = Action.Pop;
let listener: Listener | null = null;
let index = getIndex()!;
// Index should only be null when we initialize. If not, it's because the
// user called history.pushState or history.replaceState directly, in which
// case we should log a warning as it will result in bugs.
if (index == null) {
index = 0;
globalHistory.replaceState({ ...globalHistory.state, idx: index }, "");
}
function getIndex(): number {
let state = globalHistory.state || { idx: null };
return state.idx;
}
function handlePop() {
action = Action.Pop;
let nextIndex = getIndex();
let delta = nextIndex == null ? null : nextIndex - index;
index = nextIndex;
if (listener) {
listener({ action, location: history.location, delta });
}
}
function push(to: To, state?: any) {
action = Action.Push;
let location = createLocation(history.location, to, state);
if (validateLocation) validateLocation(location, to);
index = getIndex() + 1;
let historyState = getHistoryState(location, index);
let url = history.createHref(location);
// try...catch because iOS limits us to 100 pushState calls :/
try {
globalHistory.pushState(historyState, "", url);
} catch (error) {
// If the exception is because `state` can't be serialized, let that throw
// outwards just like a replace call would so the dev knows the cause
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#shared-history-push/replace-state-steps
// https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal
if (error instanceof DOMException && error.name === "DataCloneError") {
throw error;
}
// They are going to lose state here, but there is no real
// way to warn them about it since the page will refresh...
window.location.assign(url);
}
if (v5Compat && listener) {
listener({ action, location: history.location, delta: 1 });
}
}
function replace(to: To, state?: any) {
action = Action.Replace;
let location = createLocation(history.location, to, state);
if (validateLocation) validateLocation(location, to);
index = getIndex();
let historyState = getHistoryState(location, index);
let url = history.createHref(location);
globalHistory.replaceState(historyState, "", url);
if (v5Compat && listener) {
listener({ action, location: history.location, delta: 0 });
}
}
function createURL(to: To): URL {
// window.location.origin is "null" (the literal string value) in Firefox
// under certain conditions, notably when serving from a local HTML file
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
let base =
window.location.origin !== "null"
? window.location.origin
: window.location.href;
let href = typeof to === "string" ? to : createPath(to);
// Treating this as a full URL will strip any trailing spaces so we need to
// pre-encode them since they might be part of a matching splat param from
// an ancestor route
href = href.replace(/ $/, "%20");
invariant(
base,
`No window.location.(origin|href) available to create URL for href: ${href}`
);
return new URL(href, base);
}
let history: History = {
get action() {
return action;
},
get location() {
return getLocation(window, globalHistory);
},
listen(fn: Listener) {
if (listener) {
throw new Error("A history only accepts one active listener");
}
window.addEventListener(PopStateEventType, handlePop);
listener = fn;
return () => {
window.removeEventListener(PopStateEventType, handlePop);
listener = null;
};
},
createHref(to) {
return createHref(window, to);
},
createURL,
encodeLocation(to) {
// Encode a Location the same way window.location would
let url = createURL(to);
return {
pathname: url.pathname,
search: url.search,
hash: url.hash,
};
},
push,
replace,
go(n) {
return globalHistory.go(n);
},
};
return history;
}
//#endregion

106
node_modules/@remix-run/router/index.ts generated vendored Normal file
View file

@ -0,0 +1,106 @@
export type {
ActionFunction,
ActionFunctionArgs,
AgnosticDataIndexRouteObject,
AgnosticDataNonIndexRouteObject,
AgnosticDataRouteMatch,
AgnosticDataRouteObject,
AgnosticIndexRouteObject,
AgnosticNonIndexRouteObject,
AgnosticPatchRoutesOnNavigationFunction,
AgnosticPatchRoutesOnNavigationFunctionArgs,
AgnosticRouteMatch,
AgnosticRouteObject,
DataStrategyFunction,
DataStrategyFunctionArgs,
DataStrategyMatch,
DataStrategyResult,
ErrorResponse,
FormEncType,
FormMethod,
HTMLFormMethod,
JsonFunction,
LazyRouteFunction,
LoaderFunction,
LoaderFunctionArgs,
ParamParseKey,
Params,
PathMatch,
PathParam,
PathPattern,
RedirectFunction,
ShouldRevalidateFunction,
ShouldRevalidateFunctionArgs,
TrackedPromise,
UIMatch,
V7_FormMethod,
DataWithResponseInit as UNSAFE_DataWithResponseInit,
} from "./utils";
export {
AbortedDeferredError,
data,
defer,
generatePath,
getToPathname,
isRouteErrorResponse,
joinPaths,
json,
matchPath,
matchRoutes,
normalizePathname,
redirect,
redirectDocument,
replace,
resolvePath,
resolveTo,
stripBasename,
} from "./utils";
export type {
BrowserHistory,
BrowserHistoryOptions,
HashHistory,
HashHistoryOptions,
History,
InitialEntry,
Location,
MemoryHistory,
MemoryHistoryOptions,
Path,
To,
} from "./history";
export {
Action,
createBrowserHistory,
createHashHistory,
createMemoryHistory,
createPath,
parsePath,
} from "./history";
export * from "./router";
///////////////////////////////////////////////////////////////////////////////
// DANGER! PLEASE READ ME!
// We consider these exports an implementation detail and do not guarantee
// against any breaking changes, regardless of the semver release. Use with
// extreme caution and only if you understand the consequences. Godspeed.
///////////////////////////////////////////////////////////////////////////////
/** @internal */
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,
decodePath as UNSAFE_decodePath,
getResolveToMatches as UNSAFE_getResolveToMatches,
} from "./utils";
export {
invariant as UNSAFE_invariant,
warning as UNSAFE_warning,
} from "./history";

33
node_modules/@remix-run/router/package.json generated vendored Normal file
View file

@ -0,0 +1,33 @@
{
"name": "@remix-run/router",
"version": "1.23.0",
"description": "Nested/Data-driven/Framework-agnostic Routing",
"keywords": [
"remix",
"router",
"location"
],
"repository": {
"type": "git",
"url": "https://github.com/remix-run/react-router",
"directory": "packages/router"
},
"license": "MIT",
"author": "Remix Software <hello@remix.run>",
"sideEffects": false,
"main": "./dist/router.cjs.js",
"unpkg": "./dist/router.umd.min.js",
"module": "./dist/router.js",
"types": "./dist/index.d.ts",
"files": [
"dist/",
"*.ts",
"CHANGELOG.md"
],
"engines": {
"node": ">=14.0.0"
},
"publishConfig": {
"access": "public"
}
}

6001
node_modules/@remix-run/router/router.ts generated vendored Normal file

File diff suppressed because it is too large Load diff

1722
node_modules/@remix-run/router/utils.ts generated vendored Normal file

File diff suppressed because it is too large Load diff