diff --git a/.eslintignore b/.eslintignore index f36aec4840..49a812d5b4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,8 +8,6 @@ worker-configuration.d.ts /playground-local/ integration/helpers/**/dist/ integration/helpers/**/build/ -# Temporary until we can get prettier upgraded to support `import ... with` syntax -integration/helpers/rsc-parcel/src/server.tsx playwright-report/ test-results/ build.utils.d.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index dfbb78e0a2..665426b14b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -348,7 +348,6 @@ Date: 2025-06-27 ### Patch Changes - `react-router` - Do not serialize types for `useRouteLoaderData` ([#13752](https://github.com/remix-run/react-router/pull/13752)) - - For types to distinguish a `clientLoader` from a `serverLoader`, you MUST annotate `clientLoader` args: ```ts @@ -449,7 +448,6 @@ Date: 2025-05-25 - `@react-router/dev` - Add additional logging to `build` command output when cleaning assets from server build ([#13547](https://github.com/remix-run/react-router/pull/13547)) - `@react-router/dev` - Don't clean assets from server build when `build.ssrEmitAssets` has been enabled in Vite config ([#13547](https://github.com/remix-run/react-router/pull/13547)) - `@react-router/dev` - Fix typegen when same route is used at multiple paths ([#13574](https://github.com/remix-run/react-router/pull/13574)) - - For example, `routes/route.tsx` is used at 4 different paths here: ```ts @@ -468,7 +466,6 @@ Date: 2025-05-25 - Now, typegen creates unions as necessary for alternate paths for the same route file - `@react-router/dev` - Better types for `params` ([#13543](https://github.com/remix-run/react-router/pull/13543)) - - For example: ```ts @@ -515,7 +512,6 @@ Date: 2025-05-25 ``` - `@react-router/dev` - Fix `href` for optional segments ([#13595](https://github.com/remix-run/react-router/pull/13595)) - - Type generation now expands paths with optionals into their corresponding non-optional paths - For example, the path `/user/:id?` gets expanded into `/user` and `/user/:id` to more closely model visitable URLs - `href` then uses these expanded (non-optional) paths to construct type-safe paths for your app: @@ -623,7 +619,6 @@ Behind the scenes, React Router will generate the corresponding `declare module` - `react-router` - Added a new `routeDiscovery` option in `react-router.config.ts` to configure Lazy Route Discovery behavior ([#13451](https://github.com/remix-run/react-router/pull/13451)) - `react-router` - Add support for route component props in `createRoutesStub` ([#13528](https://github.com/remix-run/react-router/pull/13528)) - - This allows you to unit test your route components using the props instead of the hooks: ```tsx @@ -742,7 +737,6 @@ Date: 2025-04-17 ### Patch Changes - `react-router` - When using the object-based `route.lazy` API, the `HydrateFallback` and `hydrateFallbackElement` properties are now skipped when lazy loading routes after hydration ([#13376](https://github.com/remix-run/react-router/pull/13376)) - - If you move the code for these properties into a separate file, since the hydrate properties were unused already (if the route wasn't present during hydration), you can avoid downloading them at all. For example: ```ts diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 519e54c0c6..5c81337d4b 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -18,6 +18,7 @@ React Router has been around since 2014 largely under the development and oversight of [Michael Jackson](https://x.com/mjackson) and [Ryan Florence](https://x.com/ryanflorence). After the launch of [Remix](https://remix.run/) in 2021, the subsequent creation of the Remix team, and the merging of Remix v2 into React Router v7[^1][^2], the project shifted from a [Founder-Leader](https://www.redhat.com/en/blog/understanding-open-source-governance-models) model to a "Steering Committee" (SC) model that operates on a Request for Comments (RFC) process. [^1]: https://remix.run/blog/merging-remix-and-react-router + [^2]: https://remix.run/blog/incremental-path-to-react-19 This document will outline the process in which React Router will continue to evolve and how new features will make their way into the codebase. This is an evergreen document and will be updated as needed to reflect future changes in the process. diff --git a/decisions/0010-splitting-up-client-and-server-code-in-vite.md b/decisions/0010-splitting-up-client-and-server-code-in-vite.md index 70755110d7..144ce7d57c 100644 --- a/decisions/0010-splitting-up-client-and-server-code-in-vite.md +++ b/decisions/0010-splitting-up-client-and-server-code-in-vite.md @@ -96,6 +96,7 @@ Checking for `.server` modules only requires checking the module's path and does `vite-env-only` does require AST parsing and transformations so it will always be slower than `.server` modules. [^1]: Vite provides a lower-level module graph API, but the module graph is not guaranteed to be complete as it is only populated as modules are requested. + [^2]: When a file changes on disk, Vite invalidates the corresponding module in its cache to power features like HMR. [decision-0009]: ./0009-do-not-rely-on-treeshaking-for-correctness.md diff --git a/docs/explanation/state-management.md b/docs/explanation/state-management.md index 7df9ffd6ef..d7af20e5fe 100644 --- a/docs/explanation/state-management.md +++ b/docs/explanation/state-management.md @@ -25,14 +25,12 @@ React Router seamlessly bridges the gap between the backend and frontend via mec Here's why using typical React state patterns might be an anti-pattern in React Router: 1. **Network-related State:** If your React state is managing anything related to the network—such as data from loaders, pending form submissions, or navigational states—it's likely that you're managing state that React Router already manages: - - **[`useNavigation`][use_navigation]**: This hook gives you access to `navigation.state`, `navigation.formData`, `navigation.location`, etc. - **[`useFetcher`][use_fetcher]**: This facilitates interaction with `fetcher.state`, `fetcher.formData`, `fetcher.data` etc. - **[`loaderData`][loader_data]**: Access the data for a route. - **[`actionData`][action_data]**: Access the data from the latest action. 2. **Storing Data in React Router:** A lot of data that developers might be tempted to store in React state has a more natural home in React Router, such as: - - **URL Search Params:** Parameters within the URL that hold state. - **[Cookies][cookies]:** Small pieces of data stored on the user's device. - **[Server Sessions][sessions]:** Server-managed user sessions. diff --git a/docs/start/rsc/parcel.md b/docs/start/rsc/parcel.md index a02c094e5f..735e38b478 100644 --- a/docs/start/rsc/parcel.md +++ b/docs/start/rsc/parcel.md @@ -93,10 +93,13 @@ function fetchServer(request: Request) { routes: routes(), // Encode the match with the React Server implementation. generateResponse(match) { - return new Response(renderToReadableStream(match.payload), { - status: match.statusCode, - headers: match.headers, - }); + return new Response( + renderToReadableStream(match.payload), + { + status: match.statusCode, + headers: match.headers, + } + ); }, }); } @@ -115,10 +118,13 @@ app.use( app.use(compression(), express.static("public")); // Ignore Chrome extension requests. -app.get("/.well-known/appspecific/com.chrome.devtools.json", (_, res) => { - res.status(404); - res.end(); -}); +app.get( + "/.well-known/appspecific/com.chrome.devtools.json", + (_, res) => { + res.status(404); + res.end(); + } +); // Hookup our application. app.use( @@ -126,14 +132,17 @@ app.use( prerender( request, fetchServer, - (routes as unknown as { bootstrapScript?: string }).bootstrapScript + (routes as unknown as { bootstrapScript?: string }) + .bootstrapScript ) ) ); const PORT = Number.parseInt(process.env.PORT || "3000"); app.listen(PORT, () => { - console.log(`Server listening on port ${PORT} (http://localhost:${PORT})`); + console.log( + `Server listening on port ${PORT} (http://localhost:${PORT})` + ); }); ``` diff --git a/docs/tutorials/address-book.md b/docs/tutorials/address-book.md index 4a19e75dde..a052fed980 100644 --- a/docs/tutorials/address-book.md +++ b/docs/tutorials/address-book.md @@ -1238,8 +1238,8 @@ export default function SidebarLayout({ isActive ? "active" : isPending - ? "pending" - : "" + ? "pending" + : "" } to={`contacts/${contact.id}`} > diff --git a/docs/tutorials/quickstart.md b/docs/tutorials/quickstart.md index 36e953d6e5..1a628bad8f 100644 --- a/docs/tutorials/quickstart.md +++ b/docs/tutorials/quickstart.md @@ -205,8 +205,8 @@ First, as a convenience, add `dev` and `start` commands in `package.json` that w { "scripts": { "dev": "node ./server.js", - "start": "cross-env NODE_ENV=production node ./server.js" - } + "start": "cross-env NODE_ENV=production node ./server.js", + }, // ... } ``` diff --git a/examples/auth-router-provider/index.html b/examples/auth-router-provider/index.html index 821806494c..36f5483ddc 100644 --- a/examples/auth-router-provider/index.html +++ b/examples/auth-router-provider/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/auth-router-provider/src/index.css b/examples/auth-router-provider/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/auth-router-provider/src/index.css +++ b/examples/auth-router-provider/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/auth/index.html b/examples/auth/index.html index 821806494c..36f5483ddc 100644 --- a/examples/auth/index.html +++ b/examples/auth/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/auth/src/index.css b/examples/auth/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/auth/src/index.css +++ b/examples/auth/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/basic-data-router/index.html b/examples/basic-data-router/index.html index 3e9f1dca9e..1fc2b9f3ac 100644 --- a/examples/basic-data-router/index.html +++ b/examples/basic-data-router/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/basic-data-router/src/index.css b/examples/basic-data-router/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/basic-data-router/src/index.css +++ b/examples/basic-data-router/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/basic/index.html b/examples/basic/index.html index a8652d215a..8e4443cefa 100644 --- a/examples/basic/index.html +++ b/examples/basic/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/basic/src/index.css b/examples/basic/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/basic/src/index.css +++ b/examples/basic/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/custom-filter-link/index.html b/examples/custom-filter-link/index.html index 1ee5b99d22..fa491c1efe 100644 --- a/examples/custom-filter-link/index.html +++ b/examples/custom-filter-link/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/custom-filter-link/src/index.css b/examples/custom-filter-link/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/custom-filter-link/src/index.css +++ b/examples/custom-filter-link/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/custom-link/index.html b/examples/custom-link/index.html index 65563af715..50661dac02 100644 --- a/examples/custom-link/index.html +++ b/examples/custom-link/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/custom-link/src/index.css b/examples/custom-link/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/custom-link/src/index.css +++ b/examples/custom-link/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/custom-query-parsing/index.html b/examples/custom-query-parsing/index.html index ed0744f798..fb06fac430 100644 --- a/examples/custom-query-parsing/index.html +++ b/examples/custom-query-parsing/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/custom-query-parsing/src/index.css b/examples/custom-query-parsing/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/custom-query-parsing/src/index.css +++ b/examples/custom-query-parsing/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/data-router/index.html b/examples/data-router/index.html index a8652d215a..8e4443cefa 100644 --- a/examples/data-router/index.html +++ b/examples/data-router/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/data-router/src/index.css b/examples/data-router/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/data-router/src/index.css +++ b/examples/data-router/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/error-boundaries/index.html b/examples/error-boundaries/index.html index 09697ef99f..79a03e35c1 100644 --- a/examples/error-boundaries/index.html +++ b/examples/error-boundaries/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/error-boundaries/src/index.css b/examples/error-boundaries/src/index.css index b2983c71dc..40b7f17bca 100644 --- a/examples/error-boundaries/src/index.css +++ b/examples/error-boundaries/src/index.css @@ -1,15 +1,15 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; max-width: 600px; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; background-color: #eee; padding: 1px 3px; } diff --git a/examples/lazy-loading-router-provider/index.html b/examples/lazy-loading-router-provider/index.html index 3b9fb14a37..b16b2a6da8 100644 --- a/examples/lazy-loading-router-provider/index.html +++ b/examples/lazy-loading-router-provider/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/lazy-loading-router-provider/src/index.css b/examples/lazy-loading-router-provider/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/lazy-loading-router-provider/src/index.css +++ b/examples/lazy-loading-router-provider/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/lazy-loading/index.html b/examples/lazy-loading/index.html index 5d3e4116b8..8af226d8c9 100644 --- a/examples/lazy-loading/index.html +++ b/examples/lazy-loading/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/lazy-loading/src/index.css b/examples/lazy-loading/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/lazy-loading/src/index.css +++ b/examples/lazy-loading/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/modal-route-with-outlet/index.html b/examples/modal-route-with-outlet/index.html index f0484acaf7..dd55d4f0b3 100644 --- a/examples/modal-route-with-outlet/index.html +++ b/examples/modal-route-with-outlet/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/modal-route-with-outlet/src/index.css b/examples/modal-route-with-outlet/src/index.css index 6ec17f3992..d9e5f08c13 100644 --- a/examples/modal-route-with-outlet/src/index.css +++ b/examples/modal-route-with-outlet/src/index.css @@ -7,16 +7,16 @@ html { } body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } [data-reach-dialog-content] { diff --git a/examples/modal/index.html b/examples/modal/index.html index f0484acaf7..dd55d4f0b3 100644 --- a/examples/modal/index.html +++ b/examples/modal/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/modal/src/index.css b/examples/modal/src/index.css index 6ec17f3992..d9e5f08c13 100644 --- a/examples/modal/src/index.css +++ b/examples/modal/src/index.css @@ -7,16 +7,16 @@ html { } body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } [data-reach-dialog-content] { diff --git a/examples/multi-app/home/index.css b/examples/multi-app/home/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/multi-app/home/index.css +++ b/examples/multi-app/home/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/multi-app/inbox/index.css b/examples/multi-app/inbox/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/multi-app/inbox/index.css +++ b/examples/multi-app/inbox/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/multi-app/inbox/index.html b/examples/multi-app/inbox/index.html index 914d3be1ae..741a76221e 100644 --- a/examples/multi-app/inbox/index.html +++ b/examples/multi-app/inbox/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/multi-app/index.html b/examples/multi-app/index.html index 9857b557fc..156bbdb25a 100644 --- a/examples/multi-app/index.html +++ b/examples/multi-app/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/navigation-blocking/index.html b/examples/navigation-blocking/index.html index a8e66e86e0..fa25916f55 100644 --- a/examples/navigation-blocking/index.html +++ b/examples/navigation-blocking/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/notes/index.html b/examples/notes/index.html index e66a208668..2d1a4ed8ae 100644 --- a/examples/notes/index.html +++ b/examples/notes/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/notes/src/index.css b/examples/notes/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/notes/src/index.css +++ b/examples/notes/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/route-objects/index.html b/examples/route-objects/index.html index 244e1ebe78..3559db99e4 100644 --- a/examples/route-objects/index.html +++ b/examples/route-objects/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/route-objects/src/index.css b/examples/route-objects/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/route-objects/src/index.css +++ b/examples/route-objects/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/scroll-restoration/index.html b/examples/scroll-restoration/index.html index a8652d215a..8e4443cefa 100644 --- a/examples/scroll-restoration/index.html +++ b/examples/scroll-restoration/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/scroll-restoration/src/index.css b/examples/scroll-restoration/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/scroll-restoration/src/index.css +++ b/examples/scroll-restoration/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/search-params/index.html b/examples/search-params/index.html index 7fe1513aff..0b740d6738 100644 --- a/examples/search-params/index.html +++ b/examples/search-params/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/search-params/src/index.css b/examples/search-params/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/search-params/src/index.css +++ b/examples/search-params/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/ssr-data-router/index.html b/examples/ssr-data-router/index.html index 590104678c..c2d8885193 100644 --- a/examples/ssr-data-router/index.html +++ b/examples/ssr-data-router/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/ssr-data-router/src/index.css b/examples/ssr-data-router/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/ssr-data-router/src/index.css +++ b/examples/ssr-data-router/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/ssr/index.html b/examples/ssr/index.html index 7a35efa29c..bf525fc122 100644 --- a/examples/ssr/index.html +++ b/examples/ssr/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/ssr/src/index.css b/examples/ssr/src/index.css index 3e1f253f03..4f23a3d050 100644 --- a/examples/ssr/src/index.css +++ b/examples/ssr/src/index.css @@ -1,12 +1,12 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/examples/view-transitions/index.html b/examples/view-transitions/index.html index 3e9f1dca9e..1fc2b9f3ac 100644 --- a/examples/view-transitions/index.html +++ b/examples/view-transitions/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/view-transitions/src/index.css b/examples/view-transitions/src/index.css index c1c1c06a32..dfe631fe61 100644 --- a/examples/view-transitions/src/index.css +++ b/examples/view-transitions/src/index.css @@ -36,12 +36,14 @@ } ::view-transition-old(content) { - animation: 500ms cubic-bezier(0.4, 0, 1, 1) both fade-out, + animation: + 500ms cubic-bezier(0.4, 0, 1, 1) both fade-out, 500ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left; } ::view-transition-new(content) { - animation: 500ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, + animation: + 500ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, 500ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right; } diff --git a/integration/CHANGELOG.md b/integration/CHANGELOG.md index 6fccf850d7..2cf67d87b7 100644 --- a/integration/CHANGELOG.md +++ b/integration/CHANGELOG.md @@ -5,7 +5,6 @@ ### Minor Changes - Unstable Vite support for Node-based Remix apps ([#7590](https://github.com/remix-run/remix/pull/7590)) - - `remix build` 👉 `vite build && vite build --ssr` - `remix dev` 👉 `vite dev` diff --git a/integration/error-boundary-test.ts b/integration/error-boundary-test.ts index 42f2312ddb..846df0a0c1 100644 --- a/integration/error-boundary-test.ts +++ b/integration/error-boundary-test.ts @@ -597,7 +597,7 @@ test.describe("Default ErrorBoundary", () => { let errorBoundaryCode = !includeRootErrorBoundary ? "" : rootErrorBoundaryThrows - ? js` + ? js` export function ErrorBoundary() { let error = useRouteError(); return ( @@ -615,7 +615,7 @@ test.describe("Default ErrorBoundary", () => { ) } ` - : js` + : js` export function ErrorBoundary() { let error = useRouteError(); return ( diff --git a/integration/error-data-request-test.ts b/integration/error-data-request-test.ts index bf66905ffb..237b37aa2a 100644 --- a/integration/error-data-request-test.ts +++ b/integration/error-data-request-test.ts @@ -107,9 +107,8 @@ test.describe("ErrorBoundary", () => { } test("returns a 200 empty response on a data fetch to a path with no loaders", async () => { - let { status, headers, data } = await fixture.requestSingleFetchData( - "/_root.data" - ); + let { status, headers, data } = + await fixture.requestSingleFetchData("/_root.data"); expect(status).toBe(200); expect(headers.has("X-Remix-Error")).toBe(false); expect(data).toEqual({}); diff --git a/integration/helpers/playwright-fixture.ts b/integration/helpers/playwright-fixture.ts index e03f8cf19c..61b8238169 100644 --- a/integration/helpers/playwright-fixture.ts +++ b/integration/helpers/playwright-fixture.ts @@ -34,8 +34,8 @@ export class PlaywrightFixture { waitForHydration === true ? "networkidle" : waitForHydration === false - ? "commit" - : "load", + ? "commit" + : "load", }); if (response == null) throw new Error( diff --git a/integration/helpers/rsc-parcel/src/server.tsx b/integration/helpers/rsc-parcel/src/server.tsx index 5c3017029b..90a2e8a66c 100644 --- a/integration/helpers/rsc-parcel/src/server.tsx +++ b/integration/helpers/rsc-parcel/src/server.tsx @@ -14,7 +14,7 @@ import { // Import the prerender function from the client environment import { prerender } from "./prerender" with { env: "react-client" }; import { routes } from "./routes"; -import { assets } from "./parcel-entry-wrapper" +import { assets } from "./parcel-entry-wrapper"; function fetchServer(request: Request) { return matchRSCServerRequest({ diff --git a/integration/single-fetch-test.ts b/integration/single-fetch-test.ts index 64fc051751..089de1a540 100644 --- a/integration/single-fetch-test.ts +++ b/integration/single-fetch-test.ts @@ -1578,9 +1578,8 @@ test.describe("single-fetch", () => { expect(res.headers.get("Location")).toBe("/base/target"); expect(await res.text()).toBe(""); - let { status, data } = await fixture.requestSingleFetchData( - "/base/data.data" - ); + let { status, data } = + await fixture.requestSingleFetchData("/base/data.data"); expect(data).toEqual({ [SingleFetchRedirectSymbol]: { status: 302, diff --git a/package.json b/package.json index 9393281fe3..c38750e12c 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "jest": "^29.6.4", "jest-environment-jsdom": "^29.6.2", "jsonfile": "^6.1.0", - "prettier": "^2.8.8", + "prettier": "^3.6.2", "prompts": "^2.4.2", "react-server-dom-parcel": "^19.0.0", "remark-gfm": "^3.0.1", diff --git a/packages/create-react-router/copy-template.ts b/packages/create-react-router/copy-template.ts index 451316e375..38fb997c6a 100644 --- a/packages/create-react-router/copy-template.ts +++ b/packages/create-react-router/copy-template.ts @@ -471,7 +471,7 @@ function getRepoInfo(validatedGithubUrl: string): RepoInfo { Name: string, Tree: string | undefined, Branch: string | undefined, - FileInfo: string | undefined + FileInfo: string | undefined, ]; let filePath = file.join("/"); diff --git a/packages/create-react-router/loading-indicator.ts b/packages/create-react-router/loading-indicator.ts index 63254db6cd..d27aa6e8ea 100644 --- a/packages/create-react-router/loading-indicator.ts +++ b/packages/create-react-router/loading-indicator.ts @@ -142,8 +142,8 @@ async function gradient( `${(noMotion ? getMotionlessFrame(frameIndex) : color.supportsColor - ? frame - : getColorlessFrame(frameIndex) + ? frame + : getColorlessFrame(frameIndex) ).padEnd(MAX_FRAMES - 1, " ")} ${text}` ); if (!done) await sleep(20); diff --git a/packages/create-react-router/prompt.ts b/packages/create-react-router/prompt.ts index 716ff7ea8d..521aa9110a 100644 --- a/packages/create-react-router/prompt.ts +++ b/packages/create-react-router/prompt.ts @@ -33,7 +33,7 @@ export async function prompt< any[] > ? T[number] - : T + : T, >(questions: T, opts: PromptTypeOptions

= {}): Promise> { let { onSubmit = identity, @@ -76,7 +76,7 @@ function toPrompt< | typeof TextPrompt | typeof ConfirmPrompt | typeof SelectPrompt - | typeof MultiSelectPrompt + | typeof MultiSelectPrompt, >(el: T, args: any, opts: any = {}) { if ( el !== TextPrompt && @@ -122,14 +122,14 @@ interface ConfirmPromptType extends BasePromptType { } interface SelectPromptType< - Choices extends Readonly[]> + Choices extends Readonly[]>, > extends BasePromptType { type: "select"; choices: Choices; } interface MultiSelectPromptType< - Choices extends Readonly[]> + Choices extends Readonly[]>, > extends BasePromptType { type: "multiselect"; choices: Choices; @@ -142,45 +142,45 @@ interface SelectChoiceType { } type PromptType< - Choices extends Readonly = Readonly + Choices extends Readonly = Readonly, > = | TextPromptType | ConfirmPromptType | SelectPromptType | MultiSelectPromptType; -type PromptChoices> = T extends SelectPromptType< - infer Choices -> - ? Choices - : T extends MultiSelectPromptType - ? Choices - : never; +type PromptChoices> = + T extends SelectPromptType + ? Choices + : T extends MultiSelectPromptType + ? Choices + : never; type Answer< T extends PromptType, - Choices extends Readonly = PromptChoices + Choices extends Readonly = PromptChoices, > = T extends TextPromptType ? string : T extends ConfirmPromptType - ? boolean - : T extends SelectPromptType - ? Choices[number]["value"] - : T extends MultiSelectPromptType - ? (Choices[number]["value"] | undefined)[] - : never; + ? boolean + : T extends SelectPromptType + ? Choices[number]["value"] + : T extends MultiSelectPromptType + ? (Choices[number]["value"] | undefined)[] + : never; type Answers< - T extends Readonly> | Readonly[]> -> = T extends Readonly> - ? Partial<{ [key in T["name"]]: Answer }> - : T extends Readonly[]> - ? UnionToIntersection> - : never; + T extends Readonly> | Readonly[]>, +> = + T extends Readonly> + ? Partial<{ [key in T["name"]]: Answer }> + : T extends Readonly[]> + ? UnionToIntersection> + : never; interface PromptTypeOptions< T extends PromptType, - Choices extends Readonly = PromptChoices + Choices extends Readonly = PromptChoices, > { onSubmit?( question: T | Readonly, diff --git a/packages/create-react-router/prompts-confirm.ts b/packages/create-react-router/prompts-confirm.ts index 593ae29683..8735ff489f 100644 --- a/packages/create-react-router/prompts-confirm.ts +++ b/packages/create-react-router/prompts-confirm.ts @@ -18,7 +18,7 @@ export interface ConfirmPromptOptions extends PromptOptions { export type ConfirmPromptChoices = [ { value: true; label: string }, - { value: false; label: string } + { value: false; label: string }, ]; export class ConfirmPrompt extends Prompt { diff --git a/packages/create-react-router/prompts-multi-select.ts b/packages/create-react-router/prompts-multi-select.ts index 64b88995d4..83bfd38ab9 100644 --- a/packages/create-react-router/prompts-multi-select.ts +++ b/packages/create-react-router/prompts-multi-select.ts @@ -9,7 +9,7 @@ import { type SelectChoice } from "./prompts-select"; import { color, strip, clear, type ActionKey } from "./utils"; export interface MultiSelectPromptOptions< - Choices extends Readonly[]> + Choices extends Readonly[]>, > extends PromptOptions { hint?: string; message: string; @@ -21,7 +21,7 @@ export interface MultiSelectPromptOptions< } export class MultiSelectPrompt< - Choices extends Readonly[]> + Choices extends Readonly[]>, > extends Prompt { choices: Readonly>; label: string; diff --git a/packages/create-react-router/prompts-select.ts b/packages/create-react-router/prompts-select.ts index 2a1eb4c77a..95365ca96e 100644 --- a/packages/create-react-router/prompts-select.ts +++ b/packages/create-react-router/prompts-select.ts @@ -14,7 +14,7 @@ export interface SelectChoice { } export interface SelectPromptOptions< - Choices extends Readonly[]> + Choices extends Readonly[]>, > extends PromptOptions { hint?: string; message: string; @@ -26,7 +26,7 @@ export interface SelectPromptOptions< } export class SelectPrompt< - Choices extends Readonly[]> + Choices extends Readonly[]>, > extends Prompt { choices: Choices; label: string; @@ -184,9 +184,9 @@ export class SelectPrompt< this.done ? "" : this.hint - ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + - color.dim(` (${this.hint})`) - : "", + ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + + color.dim(` (${this.hint})`) + : "", "\n", ]; diff --git a/packages/create-react-router/prompts-text.ts b/packages/create-react-router/prompts-text.ts index 146ea04a6d..a40efdb885 100644 --- a/packages/create-react-router/prompts-text.ts +++ b/packages/create-react-router/prompts-text.ts @@ -252,9 +252,9 @@ export class TextPrompt extends Prompt { this.done ? "" : this.hint - ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + - color.dim(` (${this.hint})`) - : "", + ? (this.out.columns < 80 ? "\n" + " ".repeat(8) : "") + + color.dim(` (${this.hint})`) + : "", "\n" + prefix, " ", this.done ? color.dim(this.rendered) : this.rendered, diff --git a/packages/react-router-architect/CHANGELOG.md b/packages/react-router-architect/CHANGELOG.md index 711a92256f..754a7927a1 100644 --- a/packages/react-router-architect/CHANGELOG.md +++ b/packages/react-router-architect/CHANGELOG.md @@ -166,7 +166,6 @@ ### Major Changes - For Remix consumers migrating to React Router, the `crypto` global from the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is now required when using cookie and session APIs. This means that the following APIs are provided from `react-router` rather than platform-specific packages: ([#11837](https://github.com/remix-run/react-router/pull/11837)) - - `createCookie` - `createCookieSessionStorage` - `createMemorySessionStorage` @@ -175,7 +174,6 @@ For consumers running older versions of Node, the `installGlobals` function from `@remix-run/node` has been updated to define `globalThis.crypto`, using [Node's `require('node:crypto').webcrypto` implementation.](https://nodejs.org/api/webcrypto.html) Since platform-specific packages no longer need to implement this API, the following low-level APIs have been removed: - - `createCookieFactory` - `createSessionStorageFactory` - `createCookieSessionStorageFactory` diff --git a/packages/react-router-architect/sessions/arcTableSessionStorage.ts b/packages/react-router-architect/sessions/arcTableSessionStorage.ts index 135a758d2e..03e39a2980 100644 --- a/packages/react-router-architect/sessions/arcTableSessionStorage.ts +++ b/packages/react-router-architect/sessions/arcTableSessionStorage.ts @@ -45,7 +45,7 @@ interface ArcTableSessionStorageOptions { */ export function createArcTableSessionStorage< Data = SessionData, - FlashData = Data + FlashData = Data, >({ cookie, ...props diff --git a/packages/react-router-cloudflare/CHANGELOG.md b/packages/react-router-cloudflare/CHANGELOG.md index a6e8f71e37..0dd8f27e80 100644 --- a/packages/react-router-cloudflare/CHANGELOG.md +++ b/packages/react-router-cloudflare/CHANGELOG.md @@ -147,7 +147,6 @@ - For Remix consumers migrating to React Router, all exports from `@remix-run/cloudflare-pages` are now provided for React Router consumers in the `@react-router/cloudflare` package. There is no longer a separate package for Cloudflare Pages. ([#11801](https://github.com/remix-run/react-router/pull/11801)) - For Remix consumers migrating to React Router, the `crypto` global from the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is now required when using cookie and session APIs. This means that the following APIs are provided from `react-router` rather than platform-specific packages: ([#11837](https://github.com/remix-run/react-router/pull/11837)) - - `createCookie` - `createCookieSessionStorage` - `createMemorySessionStorage` @@ -156,7 +155,6 @@ For consumers running older versions of Node, the `installGlobals` function from `@remix-run/node` has been updated to define `globalThis.crypto`, using [Node's `require('node:crypto').webcrypto` implementation.](https://nodejs.org/api/webcrypto.html) Since platform-specific packages no longer need to implement this API, the following low-level APIs have been removed: - - `createCookieFactory` - `createSessionStorageFactory` - `createCookieSessionStorageFactory` diff --git a/packages/react-router-cloudflare/sessions/workersKVStorage.ts b/packages/react-router-cloudflare/sessions/workersKVStorage.ts index 512839fad2..1dbd644e03 100644 --- a/packages/react-router-cloudflare/sessions/workersKVStorage.ts +++ b/packages/react-router-cloudflare/sessions/workersKVStorage.ts @@ -26,7 +26,7 @@ interface WorkersKVSessionStorageOptions { */ export function createWorkersKVSessionStorage< Data = SessionData, - FlashData = Data + FlashData = Data, >({ cookie, kv, diff --git a/packages/react-router-cloudflare/worker.ts b/packages/react-router-cloudflare/worker.ts index 68862ec079..95a639527a 100644 --- a/packages/react-router-cloudflare/worker.ts +++ b/packages/react-router-cloudflare/worker.ts @@ -19,7 +19,7 @@ type MaybePromise = T | Promise; export type GetLoadContextFunction< Env = unknown, Params extends string = any, - Data extends Record = Record + Data extends Record = Record, > = (args: { request: Request; context: { diff --git a/packages/react-router-dev/CHANGELOG.md b/packages/react-router-dev/CHANGELOG.md index a7ff321a69..47778c1c50 100644 --- a/packages/react-router-dev/CHANGELOG.md +++ b/packages/react-router-dev/CHANGELOG.md @@ -195,7 +195,6 @@ ### Minor Changes - Added a new `react-router.config.ts` `routeDiscovery` option to configure Lazy Route Discovery behavior. ([#13451](https://github.com/remix-run/react-router/pull/13451)) - - By default, Lazy Route Discovery is enabled and makes manifest requests to the `/__manifest` path: - `routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" }` - You can modify the manifest path used: @@ -394,7 +393,6 @@ ### Minor Changes - Generate a "SPA fallback" HTML file for scenarios where applications are prerendering the `/` route with `ssr:false` ([#12948](https://github.com/remix-run/react-router/pull/12948)) - - If you specify `ssr:false` without a `prerender` config, this is considered "SPA Mode" and the generated `index.html` file will only render down to the root route and will be able to hydrate for any valid application path - If you specify `ssr:false` with a `prerender` config but _do not_ include the `/` path (i.e., `prerender: ['/blog/post']`), then we still generate a "SPA Mode" `index.html` file that can hydrate for any path in the application - However, previously if you specified `ssr:false` and included the `/` path in your `prerender` config, we would prerender the `/` route into `index.html` as a non-SPA page @@ -404,7 +402,6 @@ - `npx sirv-cli build/client --single __spa-fallback.html` - Allow a `loader` in the root route in SPA mode because it can be called/server-rendered at build time ([#12948](https://github.com/remix-run/react-router/pull/12948)) - - `Route.HydrateFallbackProps` now also receives `loaderData` - This will be defined so long as the `HydrateFallback` is rendering while _children_ routes are loading - This will be `undefined` if the `HydrateFallback` is rendering because the route has it's own hydrating `clientLoader` @@ -449,7 +446,6 @@ - Skip action-only resource routes when using `prerender:true` ([#13004](https://github.com/remix-run/react-router/pull/13004)) - Enhance invalid export detection when using `ssr:false` ([#12948](https://github.com/remix-run/react-router/pull/12948)) - - `headers`/`action` are prohibited in all routes with `ssr:false` because there will be no runtime server on which to run them - `loader` functions are more nuanced and depend on whether a given route is prerendered - When using `ssr:false` without a `prerender` config, only the `root` route can have a `loader` @@ -466,7 +462,6 @@ - Add `future.unstable_viteEnvironmentApi` flag to enable experimental Vite Environment API support ([#12936](https://github.com/remix-run/react-router/pull/12936)) - Disable Lazy Route Discovery for all `ssr:false` apps and not just "SPA Mode" because there is no runtime server to serve the search-param-configured `__manifest` requests ([#12894](https://github.com/remix-run/react-router/pull/12894)) - - We previously only disabled this for "SPA Mode" which is `ssr:false` and no `prerender` config but we realized it should apply to all `ssr:false` apps, including those prerendering multiple pages - In those `prerender` scenarios we would prerender the `/__manifest` file assuming the static file server would serve it but that makes some unneccesary assumptions about the static file server behaviors @@ -539,7 +534,6 @@ - Properly initialize `NODE_ENV` if not already set for compatibility with React 19 ([#12578](https://github.com/remix-run/react-router/pull/12578)) - Remove the leftover/unused `abortDelay` prop from `ServerRouter` and update the default `entry.server.tsx` to use the new `streamTimeout` value for Single Fetch ([#12478](https://github.com/remix-run/react-router/pull/12478)) - - The `abortDelay` functionality was removed in v7 as it was coupled to the `defer` implementation from Remix v2, but this removal of this prop was missed - If you were still using this prop in your `entry.server` file, it's likely your app is not aborting streams as you would expect and you will need to adopt the new [`streamTimeout`](https://reactrouter.com/explanation/special-files#streamtimeout) value introduced with Single Fetch @@ -625,7 +619,6 @@ ``` - Consolidate types previously duplicated across `@remix-run/router`, `@remix-run/server-runtime`, and `@remix-run/react` now that they all live in `react-router` ([#12177](https://github.com/remix-run/react-router/pull/12177)) - - Examples: `LoaderFunction`, `LoaderFunctionArgs`, `ActionFunction`, `ActionFunctionArgs`, `DataFunctionArgs`, `RouteManifest`, `LinksFunction`, `Route`, `EntryRoute` - The `RouteManifest` type used by the "remix" code is now slightly stricter because it is using the former `@remix-run/router` `RouteManifest` - `Record -> Record` @@ -633,7 +626,6 @@ - Removed `ServerRuntimeMeta*` types in favor of the `Meta*` types they were duplicated from - Update default `isbot` version to v5 and drop support for `isbot@3` ([#11770](https://github.com/remix-run/react-router/pull/11770)) - - If you have `isbot@4` or `isbot@5` in your `package.json`: - You do not need to make any changes - If you have `isbot@3` in your `package.json` and you have your own `entry.server.tsx` file in your repo @@ -643,7 +635,6 @@ - You are using the internal default entry provided by React Router v7 and you will need to upgrade to `isbot@5` in your `package.json` - Drop support for Node 18, update minimum Node vestion to 20 ([#12171](https://github.com/remix-run/react-router/pull/12171)) - - Remove `installGlobals()` as this should no longer be necessary - For Remix consumers migrating to React Router, Vite manifests (i.e. `.vite/manifest.json`) are now written within each build subdirectory, e.g. `build/client/.vite/manifest.json` and `build/server/.vite/manifest.json` instead of `build/.vite/client-manifest.json` and `build/.vite/server-manifest.json`. This means that the build output is now much closer to what you'd expect from a typical Vite project. ([#11573](https://github.com/remix-run/react-router/pull/11573)) @@ -681,7 +672,6 @@ ``` This initial implementation targets type inference for: - - `Params` : Path parameters from your routing config in `routes.ts` including file-based routing - `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module - `ActionData` : Action data from `action` and/or `clientAction` within your route module @@ -696,7 +686,6 @@ ``` Check out our docs for more: - - [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety) - [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety) @@ -719,7 +708,6 @@ ### Minor Changes - New `future.unstable_singleFetch` flag ([#8773](https://github.com/remix-run/remix/pull/8773)) - - Naked objects returned from loaders/actions are no longer automatically converted to JSON responses. They'll be streamed as-is via `turbo-stream` so `Date`'s will become `Date` through `useLoaderData()` - You can return naked objects with `Promise`'s without needing to use `defer()` - including nested `Promise`'s - If you need to return a custom status code or custom response headers, you can still use the `defer` utility @@ -866,11 +854,9 @@ - Always ignore route files starting with `.` ([#8801](https://github.com/remix-run/remix/pull/8801)) - Vite: Enable use of [`vite preview`](https://main.vitejs.dev/guide/static-deploy.html#deploying-a-static-site) to preview Remix SPA applications ([#8624](https://github.com/remix-run/remix/pull/8624)) - - In the SPA template, `npm run start` has been renamed to `npm run preview` which uses `vite preview` instead of a standalone HTTP server such as `http-server` or `serv-cli` - Vite: Remove the ability to pass `publicPath` as an option to the Remix vite plugin ([#8145](https://github.com/remix-run/remix/pull/8145)) - - ⚠️ **This is a breaking change for projects using the unstable Vite plugin with a `publicPath`** - This is already handled in Vite via the [`base`](https://vitejs.dev/guide/build.html#public-base-path) config so we now set the Remix `publicPath` from the Vite `base` config @@ -899,7 +885,6 @@ - Vite: Provide `Unstable_ServerBundlesFunction` and `Unstable_VitePluginConfig` types ([#8654](https://github.com/remix-run/remix/pull/8654)) - Vite: add `--sourcemapClient` and `--sourcemapServer` flags to `remix vite:build` ([#8613](https://github.com/remix-run/remix/pull/8613)) - - `--sourcemapClient` - `--sourcemapClient=inline` @@ -1139,7 +1124,6 @@ ### Patch Changes - Fix issue with `isbot` v4 released on 1/1/2024 ([#8415](https://github.com/remix-run/remix/pull/8415)) - - `remix dev` will now add `"isbot": "^4"` to `package.json` instead of using `latest` - Update built-in `entry.server` files to work with both `isbot@3` and `isbot@4` for backwards-compatibility with Remix apps that have pinned `isbot` to v3 - Templates are updated to use `isbot@4` moving forward via `create-remix` @@ -1161,7 +1145,6 @@ ### Patch Changes - Vite: Error messages when `.server` files are referenced by client ([#8267](https://github.com/remix-run/remix/pull/8267)) - - Previously, referencing a `.server` module from client code resulted in an error message like: - `The requested module '/app/models/answer.server.ts' does not provide an export named 'isDateType'` - This was confusing because `answer.server.ts` _does_ provide the `isDateType` export, but Remix was replacing `.server` modules with empty modules (`export {}`) for the client build @@ -1238,7 +1221,6 @@ - Add support for `clientLoader`/`clientAction`/`HydrateFallback` route exports ([RFC](https://github.com/remix-run/remix/discussions/7634)) ([#8173](https://github.com/remix-run/remix/pull/8173)) Remix now supports loaders/actions that run on the client (in addition to, or instead of the loader/action that runs on the server). While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as: - - Leveraging a data source local to the browser (i.e., `localStorage`) - Managing a client-side cache of server data (like `IndexedDB`) - Bypassing the Remix server in a BFF setup and hitting your API directly from the browser @@ -1347,7 +1329,6 @@ - Add `@remix-run/node` to Vite's `optimizeDeps.include` array ([#8177](https://github.com/remix-run/remix/pull/8177)) - Improve Vite plugin performance ([#8121](https://github.com/remix-run/remix/pull/8121)) - - Parallelize detection of route module exports - Disable `server.preTransformRequests` in Vite child compiler since it's only used to process route modules @@ -1517,7 +1498,6 @@ - Additionally, all runtimes (including non-Node runtimes) can use `build.mode` to determine if HMR should be performed - Support `bun` package manager ([#7074](https://github.com/remix-run/remix/pull/7074)) - The `serverNodeBuiltinsPolyfill` option (along with the newly added `browserNodeBuiltinsPolyfill`) now supports defining global polyfills in addition to module polyfills ([#7269](https://github.com/remix-run/remix/pull/7269)) - - For example, to polyfill Node's `Buffer` global: ```js @@ -1540,7 +1520,6 @@ - Fix importing of PNGs, SVGs, and other assets from packages in `node_modules` ([#6813](https://github.com/remix-run/remix/pull/6813), [#7182](https://github.com/remix-run/remix/pull/7182)) - Decouple the `@remix-run/dev` package from the contents of the `@remix-run/css-bundle` package. ([#6982](https://github.com/remix-run/remix/pull/6982)) - - The contents of the `@remix-run/css-bundle` package are now entirely managed by the Remix compiler - Even though it's still recommended that your Remix dependencies all share the same version, this change ensures that there are no runtime errors when upgrading `@remix-run/dev` without upgrading `@remix-run/css-bundle` @@ -1549,7 +1528,6 @@ - Stop `remix dev` when `esbuild` is not running ([#7158](https://github.com/remix-run/remix/pull/7158)) - Do not interpret JSX in `.ts` files ([#7306](https://github.com/remix-run/remix/pull/7306)) - - While JSX is supported in `.js` files for compatibility with existing apps and libraries, `.ts` files should not contain JSX. By not interpreting `.ts` files as JSX, `.ts` files can contain single-argument type generics without needing a comma to disambiguate from JSX: @@ -1583,7 +1561,6 @@ - Kill app server when remix dev terminates ([#7280](https://github.com/remix-run/remix/pull/7280)) - Support dependencies that import polyfill packages for Node built-ins via a trailing slash (e.g. importing the `buffer` package with `var Buffer = require('buffer/').Buffer` as recommended in their README) ([#7198](https://github.com/remix-run/remix/pull/7198)) - - These imports were previously marked as external - This meant that they were left as dynamic imports in the client bundle and would throw a runtime error in the browser (e.g. `Dynamic require of "buffer/" is not supported`) @@ -1592,14 +1569,12 @@ - Restart dev server when Remix config changes ([#7269](https://github.com/remix-run/remix/pull/7269)) - Remove outdated ESM import warnings ([#6916](https://github.com/remix-run/remix/pull/6916)) - - Most of the time these warnings were false positives. - Instead, we now rely on built-in Node warnings for ESM imports. - Do not trigger rebuilds when `.DS_Store` changes ([#7172](https://github.com/remix-run/remix/pull/7172)) - Remove warnings for stabilized flags: ([#6905](https://github.com/remix-run/remix/pull/6905)) - - `unstable_cssSideEffectImports` - `unstable_cssModules` - `unstable_vanillaExtract` @@ -1649,7 +1624,6 @@ - Output esbuild metafiles for bundle analysis ([#6772](https://github.com/remix-run/remix/pull/6772)) Written to server build directory (`build/` by default): - - `metafile.css.json` - `metafile.js.json` (browser JS) - `metafile.server.json` (server JS) @@ -1747,7 +1721,6 @@ - built-in tls support ([#6483](https://github.com/remix-run/remix/pull/6483)) New options: - - `--tls-key` / `tlsKey`: TLS key - `--tls-cert` / `tlsCert`: TLS Certificate @@ -1881,7 +1854,6 @@ - restore color for app server output ([#6485](https://github.com/remix-run/remix/pull/6485)) - Fix route ranking bug with pathless layout route next to a sibling index route ([#4421](https://github.com/remix-run/remix/pull/4421)) - - Under the hood this is done by removing the trailing slash from all generated `path` values since the number of slash-delimited segments counts towards route ranking so the trailing slash incorrectly increases the score for routes - Support sibling pathless layout routes by removing pathless layout routes from the unique route path checks in conventional route generation since they inherently trigger duplicate paths ([#4421](https://github.com/remix-run/remix/pull/4421)) @@ -2019,7 +1991,6 @@ ``` The dev server will: - - force `NODE_ENV=development` and warn you if it was previously set to something else - rebuild your app whenever your Remix app code changes - restart your app server whenever rebuilds succeed @@ -2149,7 +2120,6 @@ - Added deprecation warning for `v2_normalizeFormMethod` ([#5863](https://github.com/remix-run/remix/pull/5863)) - Added a new `future.v2_normalizeFormMethod` flag to normalize the exposed `useNavigation().formMethod` as an uppercase HTTP method to align with the previous `useTransition` behavior as well as the `fetch()` behavior of normalizing to uppercase HTTP methods. ([#5815](https://github.com/remix-run/remix/pull/5815)) - - When `future.v2_normalizeFormMethod === false`, - `useNavigation().formMethod` is lowercase - `useFetcher().formMethod` is uppercase @@ -2224,7 +2194,6 @@ ### Patch Changes - Fixes flat route inconsistencies where `route.{ext}` wasn't always being treated like `index.{ext}` when used in a folder ([#5459](https://github.com/remix-run/remix/pull/5459)) - - Route conflict no longer throw errors and instead display a helpful warning that we're using the first one we found. ```log diff --git a/packages/react-router-dev/config/config.ts b/packages/react-router-dev/config/config.ts index da84bcd3f0..a13da57449 100644 --- a/packages/react-router-dev/config/config.ts +++ b/packages/react-router-dev/config/config.ts @@ -936,7 +936,7 @@ function findEntry( for (let ext of options?.extensions ?? entryExts) { let file = Path.resolve(currentDir, basename + ext); if (fs.existsSync(file)) { - return options?.absolute ?? false ? file : Path.relative(dir, file); + return (options?.absolute ?? false) ? file : Path.relative(dir, file); } } diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 3905414211..54a6f8838a 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -659,8 +659,8 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { let buildManifest = viteCommand === "build" - ? injectedPluginContext?.buildManifest ?? - (await getBuildManifest({ reactRouterConfig, rootDirectory })) + ? (injectedPluginContext?.buildManifest ?? + (await getBuildManifest({ reactRouterConfig, rootDirectory }))) : null; let environmentBuildContext: ResolvedEnvironmentBuildContext | null = @@ -1675,8 +1675,8 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir - : ctx.environmentBuildContext?.options.build?.outDir ?? - getServerBuildDirectory(ctx.reactRouterConfig); + : (ctx.environmentBuildContext?.options.build?.outDir ?? + getServerBuildDirectory(ctx.reactRouterConfig)); let ssrViteManifest = await loadViteManifest(serverBuildDirectory); let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest); @@ -1686,8 +1686,8 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { // SSR to the client build. let userSsrEmitAssets = (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi - ? viteUserConfig.environments?.ssr?.build?.ssrEmitAssets ?? - viteUserConfig.environments?.ssr?.build?.emitAssets + ? (viteUserConfig.environments?.ssr?.build?.ssrEmitAssets ?? + viteUserConfig.environments?.ssr?.build?.emitAssets) : null) ?? viteUserConfig.build?.ssrEmitAssets ?? false; diff --git a/packages/react-router-dom/CHANGELOG.md b/packages/react-router-dom/CHANGELOG.md index 3211bfcb00..8806a8d62d 100644 --- a/packages/react-router-dom/CHANGELOG.md +++ b/packages/react-router-dom/CHANGELOG.md @@ -145,7 +145,6 @@ ### Major Changes - Remove the original `defer` implementation in favor of using raw promises via single fetch and `turbo-stream`. This removes these exports from React Router: ([#11744](https://github.com/remix-run/react-router/pull/11744)) - - `defer` - `AbortedDeferredError` - `type TypedDeferredData` diff --git a/packages/react-router-express/CHANGELOG.md b/packages/react-router-express/CHANGELOG.md index f9003c0098..41dee6d12d 100644 --- a/packages/react-router-express/CHANGELOG.md +++ b/packages/react-router-express/CHANGELOG.md @@ -171,7 +171,6 @@ - Add `exports` field to all packages ([#11675](https://github.com/remix-run/react-router/pull/11675)) - node package no longer re-exports from react-router ([#11702](https://github.com/remix-run/react-router/pull/11702)) - Drop support for Node 18, update minimum Node vestion to 20 ([#12171](https://github.com/remix-run/react-router/pull/12171)) - - Remove `installGlobals()` as this should no longer be necessary ### Patch Changes @@ -224,7 +223,6 @@ ### Patch Changes - Use `req.originalUrl` instead of `req.url` so that Remix sees the full URL ([#8145](https://github.com/remix-run/remix/pull/8145)) - - Remix relies on the knowing the full URL to ensure that server and client code can function together, and does not support URL rewriting prior to the Remix handler - Updated dependencies: @@ -312,7 +310,6 @@ - Require Node >=18.0.0 ([#6939](https://github.com/remix-run/remix/pull/6939)) - For preparation of using Node's built in fetch implementation, installing the fetch globals is now a responsibility of the app server ([#7009](https://github.com/remix-run/remix/pull/7009)) - - If you are using `remix-serve`, nothing is required - If you are using your own app server, you will need to install the globals yourself @@ -323,7 +320,6 @@ ``` - `source-map-support` is now a responsibility of the app server ([#7009](https://github.com/remix-run/remix/pull/7009)) - - If you are using `remix-serve`, nothing is required - If you are using your own app server, you will need to install [`source-map-support`](https://www.npmjs.com/package/source-map-support) yourself. diff --git a/packages/react-router-express/server.ts b/packages/react-router-express/server.ts index fa67aaf4d7..1472b9a445 100644 --- a/packages/react-router-express/server.ts +++ b/packages/react-router-express/server.ts @@ -105,8 +105,8 @@ export function createRemixRequest( let port = Number.isSafeInteger(hostnamePort) ? hostnamePort : Number.isSafeInteger(hostPort) - ? hostPort - : ""; + ? hostPort + : ""; // Use req.hostname here as it respects the "trust proxy" setting let resolvedHost = `${req.hostname}${port ? `:${port}` : ""}`; // Use `req.originalUrl` so Remix is aware of the full path diff --git a/packages/react-router-node/CHANGELOG.md b/packages/react-router-node/CHANGELOG.md index fbdf183083..77afd089b2 100644 --- a/packages/react-router-node/CHANGELOG.md +++ b/packages/react-router-node/CHANGELOG.md @@ -148,7 +148,6 @@ - Remove single fetch future flag. ([#11522](https://github.com/remix-run/react-router/pull/11522)) - For Remix consumers migrating to React Router, the `crypto` global from the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is now required when using cookie and session APIs. This means that the following APIs are provided from `react-router` rather than platform-specific packages: ([#11837](https://github.com/remix-run/react-router/pull/11837)) - - `createCookie` - `createCookieSessionStorage` - `createMemorySessionStorage` @@ -157,7 +156,6 @@ For consumers running older versions of Node, the `installGlobals` function from `@remix-run/node` has been updated to define `globalThis.crypto`, using [Node's `require('node:crypto').webcrypto` implementation.](https://nodejs.org/api/webcrypto.html) Since platform-specific packages no longer need to implement this API, the following low-level APIs have been removed: - - `createCookieFactory` - `createSessionStorageFactory` - `createCookieSessionStorageFactory` @@ -170,7 +168,6 @@ - node package no longer re-exports from react-router ([#11702](https://github.com/remix-run/react-router/pull/11702)) - Drop support for Node 18, update minimum Node vestion to 20 ([#12171](https://github.com/remix-run/react-router/pull/12171)) - - Remove `installGlobals()` as this should no longer be necessary ### Patch Changes @@ -317,7 +314,6 @@ - Stop exporting the `fetch` API in favor of using the version in the global scope - which can be polyfilled via `installGlobals` ([#7293](https://github.com/remix-run/remix/pull/7293)) - Removed/adjusted types to prefer `unknown` over `any` and to align with underlying React Router types ([#7319](https://github.com/remix-run/remix/pull/7319), [#7354](https://github.com/remix-run/remix/pull/7354)): - - Renamed the `useMatches()` return type from `RouteMatch` to `UIMatch` - Renamed `LoaderArgs`/`ActionArgs` to `LoaderFunctionArgs`/`ActionFunctionArgs` - `AppData` changed from `any` to `unknown` @@ -329,11 +325,9 @@ - `AppData`/`RouteHandle` are no longer exported as they are just aliases for `unknown` - The route `meta` API now defaults to the new "V2 Meta" API ([#6958](https://github.com/remix-run/remix/pull/6958)) - - Please refer to the ([docs](https://remix.run/docs/en/2.0.0/route/meta) and [Preparing for V2](https://remix.run/docs/en/2.0.0/start/v2#route-meta) guide for more information. - For preparation of using Node's built in fetch implementation, installing the fetch globals is now a responsibility of the app server ([#7009](https://github.com/remix-run/remix/pull/7009)) - - If you are using `remix-serve`, nothing is required - If you are using your own app server, you will need to install the globals yourself @@ -344,7 +338,6 @@ ``` - `source-map-support` is now a responsibility of the app server ([#7009](https://github.com/remix-run/remix/pull/7009)) - - If you are using `remix-serve`, nothing is required - If you are using your own app server, you will need to install [`source-map-support`](https://www.npmjs.com/package/source-map-support) yourself. @@ -478,7 +471,6 @@ ### Minor Changes - We have made a few changes to the API for route module `meta` functions when using the `future.v2_meta` flag. **These changes are _only_ breaking for users who have opted in.** ([#5746](https://github.com/remix-run/remix/pull/5746)) - - `V2_HtmlMetaDescriptor` has been renamed to `V2_MetaDescriptor` - The `meta` function's arguments have been simplified - `parentsData` has been removed, as each route's loader data is available on the `data` property of its respective `match` object @@ -571,12 +563,10 @@ - Introduces the `defer()` API from `@remix-run/router` with support for server-rendering and HTTP streaming. This utility allows you to defer values returned from `loader` functions by returning promises instead of resolved values. This has been refered to as _"sending a promise over the wire"_. ([#4920](https://github.com/remix-run/remix/pull/4920)) Informational Resources: - - - Documentation Resources (better docs specific to Remix are in the works): - - - - diff --git a/packages/react-router-serve/CHANGELOG.md b/packages/react-router-serve/CHANGELOG.md index 1e56b236f7..77139f4fe7 100644 --- a/packages/react-router-serve/CHANGELOG.md +++ b/packages/react-router-serve/CHANGELOG.md @@ -192,7 +192,6 @@ ### Patch Changes - Update `express.static` configurations to support prerendering ([#11547](https://github.com/remix-run/react-router/pull/11547)) - - Assets in the `build/client/assets` folder are served as before, with a 1-year immutable `Cache-Control` header - Static files outside of assets, such as pre-rendered `.html` and `.data` files are not served with a specific `Cache-Control` header - `.data` files are served with `Content-Type: text/x-turbo` @@ -350,14 +349,12 @@ ### Major Changes - `remix-serve` now picks an open port if 3000 is taken ([#7278](https://github.com/remix-run/remix/pull/7278)) - - If `PORT` env var is set, `remix-serve` will use that port - Otherwise, `remix-serve` picks an open port (3000 unless that is already taken) - Integrate manual mode in `remix-serve` ([#7231](https://github.com/remix-run/remix/pull/7231)) - Remove undocumented `createApp` Node API ([#7229](https://github.com/remix-run/remix/pull/7229)) - - `remix-serve` is a CLI, not a library - Require Node >=18.0.0 ([#6939](https://github.com/remix-run/remix/pull/6939)) @@ -369,7 +366,6 @@ - Preserve dynamic imports in `remix-serve` for external bundle ([#7173](https://github.com/remix-run/remix/pull/7173)) - For preparation of using Node's built in fetch implementation, installing the fetch globals is now a responsibility of the app server ([#7009](https://github.com/remix-run/remix/pull/7009)) - - If you are using `remix-serve`, nothing is required - If you are using your own app server, you will need to install the globals yourself @@ -380,7 +376,6 @@ ``` - `source-map-support` is now a responsibility of the app server ([#7009](https://github.com/remix-run/remix/pull/7009)) - - If you are using `remix-serve`, nothing is required - If you are using your own app server, you will need to install [`source-map-support`](https://www.npmjs.com/package/source-map-support) yourself. @@ -568,12 +563,10 @@ - Introduces the `defer()` API from `@remix-run/router` with support for server-rendering and HTTP streaming. This utility allows you to defer values returned from `loader` functions by returning promises instead of resolved values. This has been refered to as _"sending a promise over the wire"_. ([#4920](https://github.com/remix-run/remix/pull/4920)) Informational Resources: - - - Documentation Resources (better docs specific to Remix are in the works): - - - - diff --git a/packages/react-router/CHANGELOG.md b/packages/react-router/CHANGELOG.md index 29c71685c6..a34ccfc5d6 100644 --- a/packages/react-router/CHANGELOG.md +++ b/packages/react-router/CHANGELOG.md @@ -124,7 +124,6 @@ ### Minor Changes - Added a new `react-router.config.ts` `routeDiscovery` option to configure Lazy Route Discovery behavior. ([#13451](https://github.com/remix-run/react-router/pull/13451)) - - By default, Lazy Route Discovery is enabled and makes manifest requests to the `/__manifest` path: - `routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" }` - You can modify the manifest path used: @@ -170,7 +169,6 @@ - Preserve status code if a `clientAction` throws a `data()` result in framework mode ([#13522](https://github.com/remix-run/react-router/pull/13522)) - Be defensive against leading double slashes in paths to avoid `Invalid URL` errors from the URL constructor ([#13510](https://github.com/remix-run/react-router/pull/13510)) - - Note we do not sanitize/normalize these paths - we only detect them so we can avoid the error that would be thrown by `new URL("//", window.location.origin)` - Remove `Navigator` declaration for `navigator.connection.saveData` to avoid messing with any other types beyond `saveData` in userland ([#13512](https://github.com/remix-run/react-router/pull/13512)) @@ -186,7 +184,6 @@ - UNSTABLE: Fix a few bugs with error bubbling in middleware use-cases ([#13538](https://github.com/remix-run/react-router/pull/13538)) - Short circuit post-processing on aborted `dataStrategy` requests ([#13521](https://github.com/remix-run/react-router/pull/13521)) - - This resolves non-user-facing console errors of the form `Cannot read properties of undefined (reading 'result')` ## 7.5.3 @@ -201,7 +198,6 @@ ### Patch Changes - Update Single Fetch to also handle the 204 redirects used in `?_data` requests in Remix v2 ([#13364](https://github.com/remix-run/react-router/pull/13364)) - - This allows applications to return a redirect on `.data` requests from outside the scope of React Router (i.e., an `express`/`hono` middleware) - ⚠️ Please note that doing so relies on implementation details that are subject to change without a SemVer major release - This is primarily done to ease upgrading to Single Fetch for existing Remix v2 applications, but the recommended way to handle this is redirecting from a route middleware @@ -239,7 +235,6 @@ - UNSTABLE: Add better error messaging when `getLoadContext` is not updated to return a `Map`" ([#13242](https://github.com/remix-run/react-router/pull/13242)) - Do not automatically add `null` to `staticHandler.query()` `context.loaderData` if routes do not have loaders ([#13223](https://github.com/remix-run/react-router/pull/13223)) - - This was a Remix v2 implementation detail inadvertently left in for React Router v7 - Now that we allow returning `undefined` from loaders, our prior check of `loaderData[routeId] !== undefined` was no longer sufficient and was changed to a `routeId in loaderData` check - these `null` values can cause issues for this new check - ⚠️ This could be a "breaking bug fix" for you if you are doing manual SSR with `createStaticHandler()`/``, and using `context.loaderData` to control `` hydration behavior on the client @@ -318,7 +313,6 @@ ### Minor Changes - Add `fetcherKey` as a parameter to `patchRoutesOnNavigation` ([#13061](https://github.com/remix-run/react-router/pull/13061)) - - In framework mode, Lazy Route Discovery will now detect manifest version mismatches after a new deploy - On navigations to undiscovered routes, this mismatch will trigger a document reload of the destination path - On `fetcher` calls to undiscovered routes, this mismatch will trigger a document reload of the current path @@ -554,7 +548,6 @@ ``` Similar to server-side requests, a fresh `context` will be created per navigation (or `fetcher` call). If you have initial data you'd like to populate in the context for every request, you can provide an `unstable_getContext` function at the root of your app: - - Library mode - `createBrowserRouter(routes, { unstable_getContext })` - Framework mode - `` @@ -611,7 +604,6 @@ - Don't apply Single Fetch revalidation de-optimization when in SPA mode since there is no server HTTP request ([#12948](https://github.com/remix-run/react-router/pull/12948)) - Properly handle revalidations to across a prerender/SPA boundary ([#13021](https://github.com/remix-run/react-router/pull/13021)) - - In "hybrid" applications where some routes are pre-rendered and some are served from a SPA fallback, we need to avoid making `.data` requests if the path wasn't pre-rendered because the request will 404 - We don't know all the pre-rendered paths client-side, however: - All `loader` data in `ssr:false` mode is static because it's generated at build time @@ -621,7 +613,6 @@ - This ensures that the route doesn't cause a `.data` request that would 404 after a submission - Error at build time in `ssr:false` + `prerender` apps for the edge case scenario of: ([#13021](https://github.com/remix-run/react-router/pull/13021)) - - A parent route has only a `loader` (does not have a `clientLoader`) - The parent route is pre-rendered - The parent route has children routes which are not prerendered @@ -634,7 +625,6 @@ - Add `unstable_SerializesTo` brand type for library authors to register types serializable by React Router's streaming format (`turbo-stream`) ([`ab5b05b02`](https://github.com/remix-run/react-router/commit/ab5b05b02f99f062edb3c536c392197c88eb6c77)) - Align dev server behavior with static file server behavior when `ssr:false` is set ([#12948](https://github.com/remix-run/react-router/pull/12948)) - - When no `prerender` config exists, only SSR down to the root `HydrateFallback` (SPA Mode) - When a `prerender` config exists but the current path is not prerendered, only SSR down to the root `HydrateFallback` (SPA Fallback) - Return a 404 on `.data` requests to non-pre-rendered paths @@ -642,7 +632,6 @@ - Improve prefetch performance of CSS side effects in framework mode ([#12889](https://github.com/remix-run/react-router/pull/12889)) - Disable Lazy Route Discovery for all `ssr:false` apps and not just "SPA Mode" because there is no runtime server to serve the search-param-configured `__manifest` requests ([#12894](https://github.com/remix-run/react-router/pull/12894)) - - We previously only disabled this for "SPA Mode" which is `ssr:false` and no `prerender` config but we realized it should apply to all `ssr:false` apps, including those prerendering multiple pages - In those `prerender` scenarios we would prerender the `/__manifest` file assuming the static file server would serve it but that makes some unneccesary assumptions about the static file server behaviors @@ -719,7 +708,6 @@ _No changes_ ### Major Changes - Remove the original `defer` implementation in favor of using raw promises via single fetch and `turbo-stream`. This removes these exports from React Router: ([#11744](https://github.com/remix-run/react-router/pull/11744)) - - `defer` - `AbortedDeferredError` - `type TypedDeferredData` @@ -747,7 +735,6 @@ _No changes_ - Remove `future.v7_normalizeFormMethod` future flag ([#11697](https://github.com/remix-run/react-router/pull/11697)) - For Remix consumers migrating to React Router, the `crypto` global from the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is now required when using cookie and session APIs. This means that the following APIs are provided from `react-router` rather than platform-specific packages: ([#11837](https://github.com/remix-run/react-router/pull/11837)) - - `createCookie` - `createCookieSessionStorage` - `createMemorySessionStorage` @@ -756,14 +743,12 @@ _No changes_ For consumers running older versions of Node, the `installGlobals` function from `@remix-run/node` has been updated to define `globalThis.crypto`, using [Node's `require('node:crypto').webcrypto` implementation.](https://nodejs.org/api/webcrypto.html) Since platform-specific packages no longer need to implement this API, the following low-level APIs have been removed: - - `createCookieFactory` - `createSessionStorageFactory` - `createCookieSessionStorageFactory` - `createMemorySessionStorageFactory` - Imports/Exports cleanup ([#11840](https://github.com/remix-run/react-router/pull/11840)) - - Removed the following exports that were previously public API from `@remix-run/router` - types - `AgnosticDataIndexRouteObject` @@ -800,7 +785,6 @@ _No changes_ - Remove `future.v7_prependBasename` from the ionternalized `@remix-run/router` package ([#11726](https://github.com/remix-run/react-router/pull/11726)) - Migrate Remix type generics to React Router ([#12180](https://github.com/remix-run/react-router/pull/12180)) - - These generics are provided for Remix v2 migration purposes - These generics and the APIs they exist on should be considered informally deprecated in favor of the new `Route.*` types - Anyone migrating from React Router v6 should probably not leverage these new generics and should migrate straight to the `Route.*` types @@ -840,11 +824,9 @@ _No changes_ - Remove `v7_relativeSplatPath` future flag ([#11695](https://github.com/remix-run/react-router/pull/11695)) - Drop support for Node 18, update minimum Node vestion to 20 ([#12171](https://github.com/remix-run/react-router/pull/12171)) - - Remove `installGlobals()` as this should no longer be necessary - Remove remaining future flags ([#11820](https://github.com/remix-run/react-router/pull/11820)) - - React Router `v7_skipActionErrorRevalidation` - Remix `v3_fetcherPersist`, `v3_relativeSplatPath`, `v3_throwAbortReason` @@ -853,7 +835,6 @@ _No changes_ - Remove `@remix-run/router` deprecated `detectErrorBoundary` option in favor of `mapRouteProperties` ([#11751](https://github.com/remix-run/react-router/pull/11751)) - Add `react-router/dom` subpath export to properly enable `react-dom` as an optional `peerDependency` ([#11851](https://github.com/remix-run/react-router/pull/11851)) - - This ensures that we don't blindly `import ReactDOM from "react-dom"` in `` in order to access `ReactDOM.flushSync()`, since that would break `createMemoryRouter` use cases in non-DOM environments - DOM environments should import from `react-router/dom` to get the proper component that makes `ReactDOM.flushSync()` available: - If you are using the Vite plugin, use this in your `entry.client.tsx`: @@ -917,7 +898,6 @@ _No changes_ ``` This initial implementation targets type inference for: - - `Params` : Path parameters from your routing config in `routes.ts` including file-based routing - `LoaderData` : Loader data from `loader` and/or `clientLoader` within your route module - `ActionData` : Action data from `action` and/or `clientAction` within your route module @@ -932,7 +912,6 @@ _No changes_ ``` Check out our docs for more: - - [_Explanations > Type Safety_](https://reactrouter.com/dev/guides/explanation/type-safety) - [_How-To > Setting up type safety_](https://reactrouter.com/dev/guides/how-to/setting-up-type-safety) @@ -957,7 +936,6 @@ _No changes_ - Replace `substr` with `substring` ([#12080](https://github.com/remix-run/react-router/pull/12080)) - Remove the deprecated `json` utility ([#12146](https://github.com/remix-run/react-router/pull/12146)) - - You can use [`Response.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static) if you still need to construct JSON responses in your app - Remove unneeded dependency on source-map ([#12275](https://github.com/remix-run/react-router/pull/12275)) @@ -1311,7 +1289,6 @@ No significant changes to this package were made in this release. [See the repo - Fix `useActionData` so it returns proper contextual action data and not _any_ action data in the tree ([#11023](https://github.com/remix-run/react-router/pull/11023)) - Fix bug in `useResolvedPath` that would cause `useResolvedPath(".")` in a splat route to lose the splat portion of the URL path. ([#10983](https://github.com/remix-run/react-router/pull/10983)) - - ⚠️ This fixes a quite long-standing bug specifically for `"."` paths inside a splat route which incorrectly dropped the splat portion of the URL. If you are relative routing via `"."` inside a splat route in your application you should double check that your logic is not relying on this buggy behavior and update accordingly. - Updated dependencies: @@ -1478,7 +1455,6 @@ No significant changes to this package were made in this release. [See the repo ### 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 diff --git a/packages/react-router/__tests__/dom/data-browser-router-legacy-formdata-test.tsx b/packages/react-router/__tests__/dom/data-browser-router-legacy-formdata-test.tsx index ddbe1b805f..78965ef004 100644 --- a/packages/react-router/__tests__/dom/data-browser-router-legacy-formdata-test.tsx +++ b/packages/react-router/__tests__/dom/data-browser-router-legacy-formdata-test.tsx @@ -48,9 +48,10 @@ function testDomRouter( let actionSpy = jest.fn(); actionSpy.mockReturnValue({}); async function getPayload() { - let formData = await actionSpy.mock.calls[ - actionSpy.mock.calls.length - 1 - ][0].request.formData(); + let formData = + await actionSpy.mock.calls[ + actionSpy.mock.calls.length - 1 + ][0].request.formData(); return new URLSearchParams(formData.entries()).toString(); } diff --git a/packages/react-router/__tests__/dom/data-browser-router-test.tsx b/packages/react-router/__tests__/dom/data-browser-router-test.tsx index 214aca19c0..5f15925fa0 100644 --- a/packages/react-router/__tests__/dom/data-browser-router-test.tsx +++ b/packages/react-router/__tests__/dom/data-browser-router-test.tsx @@ -3918,9 +3918,10 @@ function testDomRouter( let actionSpy = jest.fn(); actionSpy.mockReturnValue({}); async function getPayload() { - let formData = await actionSpy.mock.calls[ - actionSpy.mock.calls.length - 1 - ][0].request.formData(); + let formData = + await actionSpy.mock.calls[ + actionSpy.mock.calls.length - 1 + ][0].request.formData(); return new URLSearchParams(formData.entries()).toString(); } diff --git a/packages/react-router/__tests__/dom/nav-link-active-test.tsx b/packages/react-router/__tests__/dom/nav-link-active-test.tsx index bfb59cf96d..3c5e6d61ec 100644 --- a/packages/react-router/__tests__/dom/nav-link-active-test.tsx +++ b/packages/react-router/__tests__/dom/nav-link-active-test.tsx @@ -725,8 +725,8 @@ describe("NavLink using a data router", () => { isPending ? "some-pending-classname" : isActive - ? "some-active-classname" - : undefined + ? "some-active-classname" + : undefined } > Link to Bar @@ -780,8 +780,8 @@ describe("NavLink using a data router", () => { isPending ? { textTransform: "lowercase" } : isActive - ? { textTransform: "uppercase" } - : undefined + ? { textTransform: "uppercase" } + : undefined } > Link to Bar @@ -834,8 +834,8 @@ describe("NavLink using a data router", () => { isPending ? "Link to Bar (loading...)" : isActive - ? "Link to Bar (current)" - : "Link to Bar (idle)" + ? "Link to Bar (current)" + : "Link to Bar (idle)" } diff --git a/packages/react-router/__tests__/dom/ssr/components-test.tsx b/packages/react-router/__tests__/dom/ssr/components-test.tsx index f24c17c422..068b02bec3 100644 --- a/packages/react-router/__tests__/dom/ssr/components-test.tsx +++ b/packages/react-router/__tests__/dom/ssr/components-test.tsx @@ -22,7 +22,7 @@ type PrefetchEventHandlerProps = { }; function itPrefetchesPageLinks< - Props extends { to: any; prefetch?: any } & PrefetchEventHandlerProps + Props extends { to: any; prefetch?: any } & PrefetchEventHandlerProps, >(Component: React.ComponentType) { describe('prefetch="intent"', () => { let context = mockFrameworkContext({ diff --git a/packages/react-router/__tests__/router/utils/data-router-setup.ts b/packages/react-router/__tests__/router/utils/data-router-setup.ts index b097054049..15d919fc89 100644 --- a/packages/react-router/__tests__/router/utils/data-router-setup.ts +++ b/packages/react-router/__tests__/router/utils/data-router-setup.ts @@ -171,7 +171,7 @@ export function createDeferred() { export function createAsyncStub(): [ asyncStub: jest.Mock, - deferred: ReturnType + deferred: ReturnType, ] { let deferred = createDeferred(); let asyncStub = jest.fn(() => deferred.promise); @@ -644,8 +644,8 @@ export function setup({ typeof keyOrOpts === "object" ? keyOrOpts : typeof routeIdOrOpts === "object" - ? routeIdOrOpts - : opts; + ? routeIdOrOpts + : opts; invariant(currentRouter, "No currentRouter available"); // @ts-expect-error diff --git a/packages/react-router/lib/components.tsx b/packages/react-router/lib/components.tsx index 769dc28bf1..9cdf4790d8 100644 --- a/packages/react-router/lib/components.tsx +++ b/packages/react-router/lib/components.tsx @@ -1089,8 +1089,8 @@ class AwaitErrorBoundary extends React.Component< "_error" in promise ? AwaitRenderStatus.error : "_data" in promise - ? AwaitRenderStatus.success - : AwaitRenderStatus.pending; + ? AwaitRenderStatus.success + : AwaitRenderStatus.pending; } else { // Raw (untracked) promise - track it status = AwaitRenderStatus.pending; diff --git a/packages/react-router/lib/context.ts b/packages/react-router/lib/context.ts index 9ff5c96891..a34eac6ecb 100644 --- a/packages/react-router/lib/context.ts +++ b/packages/react-router/lib/context.ts @@ -73,7 +73,7 @@ export type DataRouteObject = RouteObject & { export interface RouteMatch< ParamKey extends string = string, - RouteObjectType extends RouteObject = RouteObject + RouteObjectType extends RouteObject = RouteObject, > extends AgnosticRouteMatch {} export interface DataRouteMatch extends RouteMatch {} diff --git a/packages/react-router/lib/dom/ssr/components.tsx b/packages/react-router/lib/dom/ssr/components.tsx index 44aac97e7b..c9a697a277 100644 --- a/packages/react-router/lib/dom/ssr/components.tsx +++ b/packages/react-router/lib/dom/ssr/components.tsx @@ -177,7 +177,7 @@ export function usePrefetchBehavior( } export function composeEventHandlers< - EventType extends React.SyntheticEvent | Event + EventType extends React.SyntheticEvent | Event, >( theirHandler: ((event: EventType) => any) | undefined, ourHandler: (event: EventType) => any @@ -513,8 +513,8 @@ export function Meta() { error, }) : Array.isArray(routeModule.meta) - ? [...routeModule.meta] - : routeModule.meta; + ? [...routeModule.meta] + : routeModule.meta; } else if (leafMeta) { // We only assign the route's meta to the nearest leaf if there is no meta // export in the route. The meta function may return a falsy value which diff --git a/packages/react-router/lib/dom/ssr/errorBoundaries.tsx b/packages/react-router/lib/dom/ssr/errorBoundaries.tsx index 9554b59135..76c2057d35 100644 --- a/packages/react-router/lib/dom/ssr/errorBoundaries.tsx +++ b/packages/react-router/lib/dom/ssr/errorBoundaries.tsx @@ -110,8 +110,8 @@ export function RemixRootDefaultErrorBoundary({ error == null ? "Unknown Error" : typeof error === "object" && "toString" in error - ? error.toString() - : JSON.stringify(error); + ? error.toString() + : JSON.stringify(error); errorInstance = new Error(errorString); } diff --git a/packages/react-router/lib/dom/ssr/routeModules.ts b/packages/react-router/lib/dom/ssr/routeModules.ts index 3239ca6c0c..932abf1bb7 100644 --- a/packages/react-router/lib/dom/ssr/routeModules.ts +++ b/packages/react-router/lib/dom/ssr/routeModules.ts @@ -126,7 +126,7 @@ export interface LinksFunction { export interface MetaMatch< RouteId extends string = string, - Loader extends LoaderFunction | ClientLoaderFunction | unknown = unknown + Loader extends LoaderFunction | ClientLoaderFunction | unknown = unknown, > { id: RouteId; pathname: DataRouteMatch["pathname"]; @@ -143,7 +143,7 @@ export type MetaMatches< MatchLoaders extends Record< string, LoaderFunction | ClientLoaderFunction | unknown - > = Record + > = Record, > = Array< { [K in keyof MatchLoaders]: MetaMatch< @@ -158,7 +158,7 @@ export interface MetaArgs< MatchLoaders extends Record< string, LoaderFunction | ClientLoaderFunction | unknown - > = Record + > = Record, > { data: | (Loader extends LoaderFunction | ClientLoaderFunction @@ -226,7 +226,7 @@ export interface MetaFunction< MatchLoaders extends Record< string, LoaderFunction | ClientLoaderFunction | unknown - > = Record + > = Record, > { (args: MetaArgs): MetaDescriptor[] | undefined; } diff --git a/packages/react-router/lib/dom/ssr/routes.tsx b/packages/react-router/lib/dom/ssr/routes.tsx index fca93b2953..4dc28fa336 100644 --- a/packages/react-router/lib/dom/ssr/routes.tsx +++ b/packages/react-router/lib/dom/ssr/routes.tsx @@ -77,13 +77,13 @@ function getRouteComponents( routeModule.HydrateFallback && (!isSpaMode || route.id === "root") ? routeModule.HydrateFallback : route.id === "root" - ? RemixRootDefaultHydrateFallback - : undefined; + ? RemixRootDefaultHydrateFallback + : undefined; let ErrorBoundary = routeModule.ErrorBoundary ? routeModule.ErrorBoundary : route.id === "root" - ? () => - : undefined; + ? () => + : undefined; if (route.id === "root" && routeModule.Layout) { return { diff --git a/packages/react-router/lib/dom/ssr/single-fetch.tsx b/packages/react-router/lib/dom/ssr/single-fetch.tsx index c1742be90b..17bbe51c17 100644 --- a/packages/react-router/lib/dom/ssr/single-fetch.tsx +++ b/packages/react-router/lib/dom/ssr/single-fetch.tsx @@ -686,7 +686,7 @@ export function decodeViaTurboStream( let [name, message, stack] = rest as [ string, string, - string | undefined + string | undefined, ]; let Constructor = Error; // @ts-expect-error @@ -703,7 +703,7 @@ export function decodeViaTurboStream( let [data, status, statusText] = rest as [ unknown, number, - string | undefined + string | undefined, ]; return { value: new ErrorResponseImpl(status, statusText, data), diff --git a/packages/react-router/lib/hooks.tsx b/packages/react-router/lib/hooks.tsx index 7d2eef2740..96529262cc 100644 --- a/packages/react-router/lib/hooks.tsx +++ b/packages/react-router/lib/hooks.tsx @@ -156,7 +156,7 @@ export function useNavigationType(): NavigationType { */ export function useMatch< ParamKey extends ParamParseKey, - Path extends string + Path extends string, >(pattern: PathPattern | Path): PathMatch | null { invariant( useInRouterContext(), @@ -341,7 +341,7 @@ export function useOutlet(context?: unknown): React.ReactElement | null { @category Hooks */ export function useParams< - ParamsOrKey extends string | Record = string + ParamsOrKey extends string | Record = string, >(): Readonly< [ParamsOrKey] extends [string] ? Params : Partial > { @@ -610,8 +610,8 @@ function DefaultErrorComponent() { let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error - ? error.message - : JSON.stringify(error); + ? error.message + : JSON.stringify(error); let stack = error instanceof Error ? error.stack : null; let lightgrey = "rgba(200,200,200, 0.5)"; let preStyles = { padding: "0.5rem", backgroundColor: lightgrey }; @@ -848,82 +848,87 @@ export function _renderMatches( } } - return renderedMatches.reduceRight((outlet, match, index) => { - // Only data routers handle errors/fallbacks - let error: any; - let shouldRenderHydrateFallback = false; - let errorElement: React.ReactNode | null = null; - let hydrateFallbackElement: React.ReactNode | null = null; - if (dataRouterState) { - error = errors && match.route.id ? errors[match.route.id] : undefined; - errorElement = match.route.errorElement || defaultErrorElement; - - if (renderFallback) { - if (fallbackIndex < 0 && index === 0) { - warningOnce( - "route-fallback", - false, - "No `HydrateFallback` element provided to render during initial hydration" - ); - shouldRenderHydrateFallback = true; - hydrateFallbackElement = null; - } else if (fallbackIndex === index) { - shouldRenderHydrateFallback = true; - hydrateFallbackElement = match.route.hydrateFallbackElement || null; + return renderedMatches.reduceRight( + (outlet, match, index) => { + // Only data routers handle errors/fallbacks + let error: any; + let shouldRenderHydrateFallback = false; + let errorElement: React.ReactNode | null = null; + let hydrateFallbackElement: React.ReactNode | null = null; + if (dataRouterState) { + error = errors && match.route.id ? errors[match.route.id] : undefined; + errorElement = match.route.errorElement || defaultErrorElement; + + if (renderFallback) { + if (fallbackIndex < 0 && index === 0) { + warningOnce( + "route-fallback", + false, + "No `HydrateFallback` element provided to render during initial hydration" + ); + shouldRenderHydrateFallback = true; + hydrateFallbackElement = null; + } else if (fallbackIndex === index) { + shouldRenderHydrateFallback = true; + hydrateFallbackElement = match.route.hydrateFallbackElement || null; + } } } - } - let matches = parentMatches.concat(renderedMatches.slice(0, index + 1)); - let getChildren = () => { - let children: React.ReactNode; - if (error) { - children = errorElement; - } else if (shouldRenderHydrateFallback) { - children = hydrateFallbackElement; - } else if (match.route.Component) { - // Note: This is a de-optimized path since React won't re-use the - // ReactElement since it's identity changes with each new - // React.createElement call. We keep this so folks can use - // `` in `` but generally `Component` - // usage is only advised in `RouterProvider` when we can convert it to - // `element` ahead of time. - children = ; - } else if (match.route.element) { - children = match.route.element; - } else { - children = outlet; - } + let matches = parentMatches.concat(renderedMatches.slice(0, index + 1)); + let getChildren = () => { + let children: React.ReactNode; + if (error) { + children = errorElement; + } else if (shouldRenderHydrateFallback) { + children = hydrateFallbackElement; + } else if (match.route.Component) { + // Note: This is a de-optimized path since React won't re-use the + // ReactElement since it's identity changes with each new + // React.createElement call. We keep this so folks can use + // `` in `` but generally `Component` + // usage is only advised in `RouterProvider` when we can convert it to + // `element` ahead of time. + children = ; + } else if (match.route.element) { + children = match.route.element; + } else { + children = outlet; + } - return ( - + ); + }; + // Only wrap in an error boundary within data router usages when we have an + // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to + // an ancestor ErrorBoundary/errorElement + return dataRouterState && + (match.route.ErrorBoundary || + match.route.errorElement || + index === 0) ? ( + + ) : ( + getChildren() ); - }; - // Only wrap in an error boundary within data router usages when we have an - // ErrorBoundary/errorElement on this route. Otherwise let it bubble up to - // an ancestor ErrorBoundary/errorElement - return dataRouterState && - (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? ( - - ) : ( - getChildren() - ); - }, null as React.ReactElement | null); + }, + null as React.ReactElement | null + ); } enum DataRouterHook { diff --git a/packages/react-router/lib/router/router.ts b/packages/react-router/lib/router/router.ts index 619f4b2f3a..e124052c89 100644 --- a/packages/react-router/lib/router/router.ts +++ b/packages/react-router/lib/router/router.ts @@ -838,8 +838,8 @@ export function createRouter(init: RouterInit): Router { const routerWindow = init.window ? init.window : typeof window !== "undefined" - ? window - : undefined; + ? window + : undefined; const isBrowser = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && @@ -2913,9 +2913,8 @@ export function createRouter(init: RouterInit): Router { ), }; } else { - dataResults[routeId] = await convertDataStrategyResultToDataResult( - result - ); + dataResults[routeId] = + await convertDataStrategyResultToDataResult(result); } } @@ -3544,8 +3543,8 @@ export function createStaticHandler( Promise.resolve(ctx) ) : respond - ? respond(ctx) - : ctx; + ? respond(ctx) + : ctx; }; // SSR supports HEAD requests while SPA doesn't @@ -4146,8 +4145,8 @@ export function createStaticHandler( statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null - ? result.statusCode - : 500, + ? result.statusCode + : 500, actionData: null, actionHeaders: { ...(result.headers @@ -4209,8 +4208,8 @@ export function createStaticHandler( statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null - ? result.statusCode - : 500, + ? result.statusCode + : 500, actionData: null, actionHeaders: { ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}), @@ -4586,13 +4585,13 @@ function normalizeNavigateOptions( typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || - opts.body instanceof URLSearchParams - ? // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data - Array.from(opts.body.entries()).reduce( - (acc, [name, value]) => `${acc}${name}=${value}\n`, - "" - ) - : String(opts.body); + opts.body instanceof URLSearchParams + ? // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data + Array.from(opts.body.entries()).reduce( + (acc, [name, value]) => `${acc}${name}=${value}\n`, + "" + ) + : String(opts.body); return { path, diff --git a/packages/react-router/lib/router/utils.ts b/packages/react-router/lib/router/utils.ts index c3844dc8c0..39f45abe06 100644 --- a/packages/react-router/lib/router/utils.ts +++ b/packages/react-router/lib/router/utils.ts @@ -376,14 +376,14 @@ export interface DataStrategyResult { } export interface DataStrategyFunction { - (args: DataStrategyFunctionArgs): Promise< - Record - >; + ( + args: DataStrategyFunctionArgs + ): Promise>; } export type AgnosticPatchRoutesOnNavigationFunctionArgs< O extends AgnosticRouteObject = AgnosticRouteObject, - M extends AgnosticRouteMatch = AgnosticRouteMatch + M extends AgnosticRouteMatch = AgnosticRouteMatch, > = { signal: AbortSignal; path: string; @@ -394,7 +394,7 @@ export type AgnosticPatchRoutesOnNavigationFunctionArgs< export type AgnosticPatchRoutesOnNavigationFunction< O extends AgnosticRouteObject = AgnosticRouteObject, - M extends AgnosticRouteMatch = AgnosticRouteMatch + M extends AgnosticRouteMatch = AgnosticRouteMatch, > = ( opts: AgnosticPatchRoutesOnNavigationFunctionArgs ) => MaybePromise; @@ -560,7 +560,7 @@ type ParamChar = Regex_w | "-"; // Emulates regex `+` type RegexMatchPlus< CharPattern extends string, - T extends string + T extends string, > = T extends `${infer First}${infer Rest}` ? First extends CharPattern ? RegexMatchPlus extends never @@ -575,22 +575,22 @@ type _PathParam = Path extends `${infer L}/${infer R}` ? _PathParam | _PathParam : // find params after `:` - Path extends `:${infer Param}` - ? Param extends `${infer Optional}?${string}` - ? RegexMatchPlus - : RegexMatchPlus - : // otherwise, there aren't any params present - never; + Path extends `:${infer Param}` + ? Param extends `${infer Optional}?${string}` + ? RegexMatchPlus + : RegexMatchPlus + : // otherwise, there aren't any params present + never; export type PathParam = // check if path is just a wildcard Path extends "*" | "/*" ? "*" : // look for wildcard at the end of the path - Path extends `${infer Rest}/*` - ? "*" | _PathParam - : // look for params in the absence of wildcards - _PathParam; + Path extends `${infer Rest}/*` + ? "*" | _PathParam + : // look for params in the absence of wildcards + _PathParam; // eslint-disable-next-line @typescript-eslint/no-unused-vars type _tests = [ @@ -601,7 +601,7 @@ type _tests = [ Expect, "a" | "b">>, Expect, "a" | "c" | "*">>, Expect, "lang">>, - Expect, "lang">> + Expect, "lang">>, ]; // Attempt to parse the given string segment. If it fails, then just return the @@ -623,7 +623,7 @@ export type Params = { */ export interface AgnosticRouteMatch< ParamKey extends string = string, - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, > { /** * The names and values of dynamic parameters in the URL. @@ -712,7 +712,7 @@ export function convertRoutesToDataRoutes( * @category Utils */ export function matchRoutes< - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, >( routes: RouteObjectType[], locationArg: Partial | string, @@ -722,7 +722,7 @@ export function matchRoutes< } export function matchRoutesImpl< - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, >( routes: RouteObjectType[], locationArg: Partial | string, @@ -788,7 +788,7 @@ export function convertRouteMatchToUiMatch( } interface RouteMeta< - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, > { relativePath: string; caseSensitive: boolean; @@ -797,7 +797,7 @@ interface RouteMeta< } interface RouteBranch< - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, > { path: string; score: number; @@ -805,7 +805,7 @@ interface RouteBranch< } function flattenRoutes< - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, >( routes: RouteObjectType[], branches: RouteBranch[] = [], @@ -976,8 +976,8 @@ function computeScore(path: string, index: boolean | undefined): number { (paramRe.test(segment) ? dynamicSegmentValue : segment === "" - ? emptySegmentValue - : staticSegmentValue), + ? emptySegmentValue + : staticSegmentValue), initialScore ); } @@ -999,7 +999,7 @@ function compareIndexes(a: number[], b: number[]): number { function matchRouteBranch< ParamKey extends string = string, - RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject, >( branch: RouteBranch, pathname: string, @@ -1177,7 +1177,7 @@ type Mutable = { */ export function matchPath< ParamKey extends ParamParseKey, - Path extends string + Path extends string, >( pattern: PathPattern | Path, pathname: string @@ -1411,7 +1411,7 @@ function getInvalidPathError( * */ export function getPathContributingMatches< - T extends AgnosticRouteMatch = AgnosticRouteMatch + T extends AgnosticRouteMatch = AgnosticRouteMatch, >(matches: T[]) { return matches.filter( (match, index) => @@ -1422,7 +1422,7 @@ export function getPathContributingMatches< // Return the array of pathnames for the current route matches - used to // generate the routePathnames input for resolveTo() export function getResolveToMatches< - T extends AgnosticRouteMatch = AgnosticRouteMatch + T extends AgnosticRouteMatch = AgnosticRouteMatch, >(matches: T[]) { let pathMatches = getPathContributingMatches(matches); @@ -1536,8 +1536,8 @@ export const normalizeSearch = (search: string): string => !search || search === "?" ? "" : search.startsWith("?") - ? search - : "?" + search; + ? search + : "?" + search; /** * @private diff --git a/packages/react-router/lib/rsc/browser.tsx b/packages/react-router/lib/rsc/browser.tsx index 6646faf86c..43a27286cf 100644 --- a/packages/react-router/lib/rsc/browser.tsx +++ b/packages/react-router/lib/rsc/browser.tsx @@ -672,10 +672,10 @@ function createRouteFromServerManifest( }, }) : match.hasAction - ? (_, singleFetch) => callSingleFetch(singleFetch) - : () => { - throw noActionDefinedError("action", match.id); - }, + ? (_, singleFetch) => callSingleFetch(singleFetch) + : () => { + throw noActionDefinedError("action", match.id); + }, path: match.path, shouldRevalidate: match.shouldRevalidate, // We always have a "loader" in this RSC world since even if we don't diff --git a/packages/react-router/lib/rsc/errorBoundaries.tsx b/packages/react-router/lib/rsc/errorBoundaries.tsx index 4a1fcb4f44..65e8cadda3 100644 --- a/packages/react-router/lib/rsc/errorBoundaries.tsx +++ b/packages/react-router/lib/rsc/errorBoundaries.tsx @@ -139,8 +139,8 @@ function RSCDefaultRootErrorBoundaryImpl({ error == null ? "Unknown Error" : typeof error === "object" && "toString" in error - ? error.toString() - : JSON.stringify(error); + ? error.toString() + : JSON.stringify(error); errorInstance = new Error(errorString); } diff --git a/packages/react-router/lib/rsc/server.rsc.ts b/packages/react-router/lib/rsc/server.rsc.ts index e226732507..0a1e1f9efb 100644 --- a/packages/react-router/lib/rsc/server.rsc.ts +++ b/packages/react-router/lib/rsc/server.rsc.ts @@ -890,11 +890,11 @@ async function getRSCRouteMatch( }) ) : match.route.id === "root" - ? // FIXME: This should use the `RemixRootDefaultErrorBoundary` but that - // currently uses a hook internally so it fails during RSC. Restructure - // so it can be used safely in an RSC render pass. - React.createElement("p", null, "Loading!") - : undefined; + ? // FIXME: This should use the `RemixRootDefaultErrorBoundary` but that + // currently uses a hook internally so it fails during RSC. Restructure + // so it can be used safely in an RSC render pass. + React.createElement("p", null, "Loading!") + : undefined; return { clientAction: (match.route as any).clientAction, diff --git a/packages/react-router/lib/server-runtime/build.ts b/packages/react-router/lib/server-runtime/build.ts index c12b4ab60e..5816e1843d 100644 --- a/packages/react-router/lib/server-runtime/build.ts +++ b/packages/react-router/lib/server-runtime/build.ts @@ -56,9 +56,10 @@ export interface HandleDocumentRequestFunction { } export interface HandleDataRequestFunction { - (response: Response, args: LoaderFunctionArgs | ActionFunctionArgs): - | Promise - | Response; + ( + response: Response, + args: LoaderFunctionArgs | ActionFunctionArgs + ): Promise | Response; } export interface HandleErrorFunction { diff --git a/packages/react-router/lib/server-runtime/sessions.ts b/packages/react-router/lib/server-runtime/sessions.ts index 1c29de5c99..4f1215ef3e 100644 --- a/packages/react-router/lib/server-runtime/sessions.ts +++ b/packages/react-router/lib/server-runtime/sessions.ts @@ -92,7 +92,7 @@ export type CreateSessionFunction = ( */ export const createSession: CreateSessionFunction = < Data = SessionData, - FlashData = Data + FlashData = Data, >( initialData: Partial = {}, id = "" @@ -207,7 +207,7 @@ export interface SessionStorage { */ export interface SessionIdStorageStrategy< Data = SessionData, - FlashData = Data + FlashData = Data, > { /** * The Cookie used to store the session id, or options used to automatically @@ -274,8 +274,8 @@ export function createSessionStorage({ options?.maxAge != null ? new Date(Date.now() + options.maxAge * 1000) : options?.expires != null - ? options.expires - : cookie.expires; + ? options.expires + : cookie.expires; if (id) { await updateData(id, data, expires); diff --git a/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts b/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts index fbfe5ad046..7111ccf480 100644 --- a/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts +++ b/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts @@ -25,7 +25,7 @@ interface CookieSessionStorageOptions { */ export function createCookieSessionStorage< Data = SessionData, - FlashData = Data + FlashData = Data, >({ cookie: cookieArg }: CookieSessionStorageOptions = {}): SessionStorage< Data, FlashData diff --git a/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts b/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts index b1f48fbfeb..efabc5fc99 100644 --- a/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts +++ b/packages/react-router/lib/server-runtime/sessions/memoryStorage.ts @@ -23,7 +23,7 @@ interface MemorySessionStorageOptions { */ export function createMemorySessionStorage< Data = SessionData, - FlashData = Data + FlashData = Data, >({ cookie }: MemorySessionStorageOptions = {}): SessionStorage< Data, FlashData diff --git a/packages/react-router/lib/types/route-data.ts b/packages/react-router/lib/types/route-data.ts index e4b7450a7c..94f2f246e4 100644 --- a/packages/react-router/lib/types/route-data.ts +++ b/packages/react-router/lib/types/route-data.ts @@ -140,7 +140,7 @@ export type SerializeFrom = T extends (...args: infer Args) => unknown ? Args extends [ | ClientLoaderFunctionArgs | ClientActionFunctionArgs - | ClientDataFunctionArgs + | ClientDataFunctionArgs, ] ? ClientDataFrom : ServerDataFrom @@ -345,5 +345,5 @@ type __tests = [ | { a: string; b: Date; c: undefined } | { d: string; e: Date; f: () => boolean } > - > + >, ]; diff --git a/packages/react-router/lib/types/serializes-to.ts b/packages/react-router/lib/types/serializes-to.ts index fe627293b7..9d70a488b5 100644 --- a/packages/react-router/lib/types/serializes-to.ts +++ b/packages/react-router/lib/types/serializes-to.ts @@ -17,5 +17,5 @@ type __tests = [ Record extends unstable_SerializesTo ? true : false, false > - > + >, ]; diff --git a/packages/react-router/vendor/turbo-stream-v2/unflatten.ts b/packages/react-router/vendor/turbo-stream-v2/unflatten.ts index 21b75f746f..2e686d8657 100644 --- a/packages/react-router/vendor/turbo-stream-v2/unflatten.ts +++ b/packages/react-router/vendor/turbo-stream-v2/unflatten.ts @@ -25,8 +25,8 @@ const globalObj = ( typeof window !== "undefined" ? window : typeof globalThis !== "undefined" - ? globalThis - : undefined + ? globalThis + : undefined ) as Record | undefined; export function unflatten(this: ThisDecode, parsed: unknown): unknown { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf274ca4de..510a30d4e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,8 +118,8 @@ importers: specifier: ^6.1.0 version: 6.1.0 prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.6.2 + version: 3.6.2 prompts: specifier: ^2.4.2 version: 2.4.2 @@ -8382,6 +8382,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -18045,6 +18050,8 @@ snapshots: prettier@2.8.8: {} + prettier@3.6.2: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 diff --git a/prettier.config.js b/prettier.config.js index 6588ba1fea..161d43d9f7 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -1,4 +1,6 @@ /** * @type {import('prettier').Options} */ -module.exports = {}; +module.exports = { + trailingComma: "es5", +}; diff --git a/tutorials/address-book/app/app.css b/tutorials/address-book/app/app.css index 7251e61431..a9485f3e65 100644 --- a/tutorials/address-book/app/app.css +++ b/tutorials/address-book/app/app.css @@ -8,16 +8,16 @@ html { } body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } html, @@ -35,7 +35,9 @@ button { border: none; border-radius: 8px; padding: 0.5rem 0.75rem; - box-shadow: 0 0px 1px hsla(0, 0%, 0%, 0.2), 0 1px 2px hsla(0, 0%, 0%, 0.2); + box-shadow: + 0 0px 1px hsla(0, 0%, 0%, 0.2), + 0 1px 2px hsla(0, 0%, 0%, 0.2); background-color: white; line-height: 1.5; margin: 0; @@ -48,7 +50,9 @@ button { textarea:hover, input:hover, button:hover { - box-shadow: 0 0px 1px hsla(0, 0%, 0%, 0.6), 0 1px 2px hsla(0, 0%, 0%, 0.2); + box-shadow: + 0 0px 1px hsla(0, 0%, 0%, 0.6), + 0 1px 2px hsla(0, 0%, 0%, 0.2); } button:active {