diff --git a/docs/data/toolpad/core/components/app-provider/app-provider.md b/docs/data/toolpad/core/components/app-provider/app-provider.md index 20e2d4129e5..29e14a55308 100644 --- a/docs/data/toolpad/core/components/app-provider/app-provider.md +++ b/docs/data/toolpad/core/components/app-provider/app-provider.md @@ -26,22 +26,22 @@ In the following example, an `AppProvider` component wrapping the page provides ## Next.js -The `AppProvider` for Next.js applications includes some Next.js integrations out-of-the-box. +The `NextAppProvider` includes some Next.js integrations out-of-the-box. -By using the specific `AppProvider` for Next.js you do not have to manually configure the integration between some Toolpad features and the corresponding Next.js features (such as routing), making the integration automatic and seamless. +By using the specific `NextAppProvider` you do not have to manually configure the integration between some Toolpad features and the corresponding Next.js features (such as routing), making the integration automatic and seamless. ```tsx -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; ``` ### Next.js App Router -When using the **Next.js App Router**, the most typical file where to import and use `AppProvider` will be at the top level `layout.tsx` file that defines the layout for all the application pages. +When using the **Next.js App Router**, the most typical file where to import and use `NextAppProvider` is the top level `layout.tsx` file that defines the layout for all the application pages. ```tsx // app/layout.tsx -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; export default function Layout(props) { const { children } = props; @@ -49,7 +49,7 @@ export default function Layout(props) { return ( - {children} + {children} ); @@ -58,32 +58,32 @@ export default function Layout(props) { ### Next.js Pages Router -When using the **Next.js Pages Router**, the most typical file where to import and use `AppProvider` in order to wrap every page in the application will be the `pages/_app.tsx` file. +When using the **Next.js Pages Router**, the most typical file where to import and use `NextAppProvider` in order to wrap every page in the application is the `pages/_app.tsx` file. ```tsx // pages/_app.tsx -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; export default function App(props) { const { Component, pageProps } = props; return ( - + - + ); } ``` ## Client-side routing -The `AppProvider` for React Router includes routing out-of-the-box for projects using [react-router-dom](https://www.npmjs.com/package/react-router-dom). +The `ReactRouterAppProvider` includes routing out-of-the-box for projects using [react-router](https://www.npmjs.com/package/react-router). -This specific `AppProvider` is recommended when building single-page applications with tools such as [Vite](https://vite.dev/), as you do not have to manually configure your app routing, making the integration automatic and seamless. +This specific `ReactRouterAppProvider` is recommended when building single-page applications with tools such as [Vite](https://vite.dev/), as you do not have to manually configure your app routing, making the integration automatic and seamless. ```tsx -import { AppProvider } from '@toolpad/core/react-router-dom'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; ``` ## Theming diff --git a/docs/data/toolpad/core/integrations/ReactRouter.js b/docs/data/toolpad/core/integrations/ReactRouter.js index 87b5dea39d9..8498907f251 100644 --- a/docs/data/toolpad/core/integrations/ReactRouter.js +++ b/docs/data/toolpad/core/integrations/ReactRouter.js @@ -4,8 +4,8 @@ import { createTheme } from '@mui/material/styles'; import Typography from '@mui/material/Typography'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { createMemoryRouter, RouterProvider, Outlet } from 'react-router-dom'; -import { AppProvider } from '@toolpad/core/react-router-dom'; +import { createMemoryRouter, RouterProvider, Outlet } from 'react-router'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; @@ -67,14 +67,14 @@ function App(props) { const { window } = props; return ( - - + ); } diff --git a/docs/data/toolpad/core/integrations/ReactRouter.tsx b/docs/data/toolpad/core/integrations/ReactRouter.tsx index dc2df442938..e84f94173e4 100644 --- a/docs/data/toolpad/core/integrations/ReactRouter.tsx +++ b/docs/data/toolpad/core/integrations/ReactRouter.tsx @@ -3,8 +3,8 @@ import { createTheme } from '@mui/material/styles'; import Typography from '@mui/material/Typography'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { createMemoryRouter, RouterProvider, Outlet } from 'react-router-dom'; -import { AppProvider } from '@toolpad/core/react-router-dom'; +import { createMemoryRouter, RouterProvider, Outlet } from 'react-router'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import type { Navigation } from '@toolpad/core/AppProvider'; @@ -67,14 +67,14 @@ function App(props: { window?: Window }) { const { window } = props; return ( - - + ); } diff --git a/docs/data/toolpad/core/integrations/nextjs-approuter.md b/docs/data/toolpad/core/integrations/nextjs-approuter.md index 8784c51e707..993f6964071 100644 --- a/docs/data/toolpad/core/integrations/nextjs-approuter.md +++ b/docs/data/toolpad/core/integrations/nextjs-approuter.md @@ -26,12 +26,12 @@ yarn add install @mui/material-nextjs @emotion/cache -## Wrap your application with `AppProvider` +## Wrap your application with `NextAppProvider` -In your root layout file (for example, `app/layout.tsx`), wrap your application with the `AppProvider`: +In your root layout file (for example, `app/layout.tsx`), wrap your application with the `NextAppProvider`: ```tsx title="app/layout.tsx" -import { AppProvider } from '@toolpad/core/AppProvider'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import LinearProgress from '@mui/material/LinearProgress'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; @@ -39,16 +39,16 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( }> - + {children} - + ); } ``` -You can find details on the `AppProvider` props on the [AppProvider](/toolpad/core/react-app-provider/) page. +You can find details on the `NextAppProvider` props on the [AppProvider](/toolpad/core/react-app-provider/) page. :::info The `AppRouterCacheProvider` component is not required to use Toolpad Core, but it's recommended to use it to ensure that the styles are appended to the `` and not rendering in the ``. diff --git a/docs/data/toolpad/core/integrations/nextjs-pagesrouter.md b/docs/data/toolpad/core/integrations/nextjs-pagesrouter.md index c6e8171d805..6eac0cbe05d 100644 --- a/docs/data/toolpad/core/integrations/nextjs-pagesrouter.md +++ b/docs/data/toolpad/core/integrations/nextjs-pagesrouter.md @@ -26,13 +26,13 @@ yarn add install @mui/material-nextjs @emotion/cache -## Wrap your application with `AppProvider` +## Wrap your application with `NextAppProvider` -In your root layout file (for example, `pages/_app.tsx`), wrap your application with the `AppProvider`: +In your root layout file (for example, `pages/_app.tsx`), wrap your application with the `NextAppProvider`: ```tsx title="pages/_app.tsx" import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { PageContainer } from '@toolpad/core/PageContainer'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import Head from 'next/head'; @@ -63,13 +63,13 @@ export default function App({ Component }: { Component: React.ElementType }) { - + - + ); } @@ -221,7 +221,7 @@ Modify `_app.tsx` to include the `authentication` prop and other helpers: ```tsx title="pages/_app.tsx" import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import Head from 'next/head'; @@ -294,14 +294,14 @@ function AppLayout({ children }: { children: React.ReactNode }) { - {children} - + ); } diff --git a/docs/data/toolpad/core/integrations/react-router.md b/docs/data/toolpad/core/integrations/react-router.md index e0fd48b0d82..0ba513f938e 100644 --- a/docs/data/toolpad/core/integrations/react-router.md +++ b/docs/data/toolpad/core/integrations/react-router.md @@ -1,21 +1,21 @@ --- -title: React router - Integration +title: React Router - Integration --- # React Router

To integrate Toolpad Core into a single-page app (with Vite, for example) using React Router, follow these steps.

-## Wrap all your pages in an `AppProvider` +## Wrap all your pages in a `ReactRouterAppProvider` -In your router configuration (e.g.: `src/main.tsx`), use a shared component or element (e.g.: `src/App.tsx`) as a root **layout route** that wraps the whole application with the `AppProvider` from `@toolpad/core/react-router-dom`. +In your router configuration (for example `src/main.tsx`), use a shared component or element (for example `src/App.tsx`) as a root **layout route** that wraps the whole application with the `ReactRouterAppProvider` from `@toolpad/core/react-router`. -You must use the `` component from `react-router-dom` in this root layout element or component. +You must use the `` component from `react-router` in this root layout element or component. ```tsx title="src/main.tsx" import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router'; import App from './App'; import DashboardPage from './pages'; import OrdersPage from './pages/orders'; @@ -37,8 +37,8 @@ ReactDOM.createRoot(document.getElementById('root')!).render( import * as React from 'react'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { AppProvider } from '@toolpad/core/react-router-dom'; -import { Outlet } from 'react-router-dom'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; +import { Outlet } from 'react-router'; import type { Navigation } from '@toolpad/core'; const NAVIGATION: Navigation = [ @@ -63,20 +63,20 @@ const BRANDING = { export default function App() { return ( - + - + ); } ``` ## Create a dashboard layout -Create a layout file for your dashboard pages (e.g.: `src/layouts/dashboard.tsx`), to also be used as a layout route with the `` component from `react-router-dom`: +Create a layout file for your dashboard pages (for example `src/layouts/dashboard.tsx`), to also be used as a layout route with the `` component from `react-router`: ```tsx title="src/layouts/dashboard.tsx" import * as React from 'react'; -import { Outlet } from 'react-router-dom'; +import { Outlet } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; @@ -93,7 +93,7 @@ export default function Layout() { The [`DashboardLayout`](/toolpad/core/react-dashboard-layout/) component provides a consistent layout for your dashboard pages, including a sidebar, navigation, and header. The [`PageContainer`](/toolpad/core/react-page-container/) component is used to wrap the page content, and provides breadcrumbs for navigation. -You can then add this layout component to your React Router configuration (e.g.: `src/main.tsx`), as a child of the root layout route created above. +You can then add this layout component to your React Router configuration (for example `src/main.tsx`), as a child of the root layout route created above. ```tsx title="src/main.tsx" import Layout from './layouts/dashboard'; @@ -115,7 +115,7 @@ const router = createBrowserRouter([ ## Create pages -Create a dashboard page (e.g.: `src/pages/index.tsx`) and an orders page (`src/pages/orders.tsx`). +Create a dashboard page (for example `src/pages/index.tsx`) and an orders page (`src/pages/orders.tsx`). ```tsx title="src/pages/index.tsx" import * as React from 'react'; @@ -135,7 +135,7 @@ export default function OrdersPage() { } ``` -You can then add these page components as routes to your React Router configuration (e.g.: `src/main.tsx`). By adding them as children of the layout route created above, they are automatically wrapped with that dashboard layout: +You can then add these page components as routes to your React Router configuration (for example `src/main.tsx`). By adding them as children of the layout route created above, they are automatically wrapped with that dashboard layout: ```tsx title="src/main.tsx" import DashboardPage from './pages'; @@ -205,8 +205,8 @@ export function useSession() { import * as React from 'react'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { AppProvider } from '@toolpad/core/react-router-dom'; -import { Outlet, useNavigate } from 'react-router-dom'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; +import { Outlet, useNavigate } from 'react-router'; import type { Navigation, Session } from '@toolpad/core'; import { SessionContext } from './SessionContext'; @@ -250,14 +250,14 @@ export default function App() { return ( - - + ); } @@ -267,7 +267,7 @@ export default function App() { ```tsx title="src/layouts/dashboard.tsx" import * as React from 'react'; -import { Outlet, Navigate, useLocation } from 'react-router-dom'; +import { Outlet, Navigate, useLocation } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import { useSession } from '../SessionContext'; @@ -302,7 +302,7 @@ You can protect any page or groups of pages through this mechanism. import * as React from 'react'; import { SignInPage } from '@toolpad/core/SignInPage'; import type { Session } from '@toolpad/core/AppProvider'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate } from 'react-router'; import { useSession } from '../SessionContext'; const fakeAsyncGetSession = async (formData: any): Promise => { @@ -354,7 +354,7 @@ export default function SignIn() { ```tsx title="src/main.tsx" import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router'; import App from './App'; import Layout from './layouts/dashboard'; import DashboardPage from './pages'; diff --git a/docs/data/toolpad/core/introduction/base-concepts.md b/docs/data/toolpad/core/introduction/base-concepts.md index be319e433ee..ae008ad48dc 100644 --- a/docs/data/toolpad/core/introduction/base-concepts.md +++ b/docs/data/toolpad/core/introduction/base-concepts.md @@ -67,9 +67,9 @@ You can pass the router implementation to the `AppProvider` component using the ::: :::success -If you are using Next.js, use the `AppProvider` exported from `@toolpad/core/nextjs`. +If you are using Next.js, use the `NextAppProvider` exported from `@toolpad/core/nextjs`. -If you are building a single-page application (with [Vite](https://vite.dev/), for example) using React Router for routing, use the `AppProvider` exported from `@toolpad/core/react-router-dom`. +If you are building a single-page application (with [Vite](https://vite.dev/), for example) using React Router for routing, use the `ReactRouterAppProvider` exported from `@toolpad/core/react-router`. This automatically sets up the router for you, so that you don't need to pass the `router` prop. ::: diff --git a/docs/package.json b/docs/package.json index 4bba7ccf7ae..afffad15a6b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -77,7 +77,7 @@ "react-dom": "18.3.1", "react-hook-form": "7.53.2", "react-is": "18.3.1", - "react-router": "6.26.2", + "react-router": "7.1.0", "react-router-dom": "6.26.2", "react-runner": "1.0.5", "react-simple-code-editor": "0.14.1", diff --git a/docs/pages/toolpad/core/api/app-provider.json b/docs/pages/toolpad/core/api/app-provider.json index bb6ac8cd868..6918852f106 100644 --- a/docs/pages/toolpad/core/api/app-provider.json +++ b/docs/pages/toolpad/core/api/app-provider.json @@ -39,7 +39,7 @@ "name": "AppProvider", "imports": [ "import { AppProvider } from '@toolpad/core/AppProvider';", - "import { AppProvider } from '@toolpad/core';\nimport { AppProvider } from '@toolpad/core/nextjs'; // Next.js\nimport { AppProvider } from '@toolpad/core/react-router-dom'; // React Router" + "import { AppProvider } from '@toolpad/core';\nimport { NextAppProvider } from '@toolpad/core/nextjs'; // Next.js\nimport { ReactRouterAppProvider } from '@toolpad/core/react-router'; // React Router" ], "classes": [], "spread": true, diff --git a/examples/core/auth-nextjs-email/src/app/layout.tsx b/examples/core/auth-nextjs-email/src/app/layout.tsx index aee998fac8f..cfc6d97e016 100644 --- a/examples/core/auth-nextjs-email/src/app/layout.tsx +++ b/examples/core/auth-nextjs-email/src/app/layout.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; @@ -41,14 +41,14 @@ export default async function RootLayout(props: { children: React.ReactNode }) { - {props.children} - + diff --git a/examples/core/auth-nextjs-pages-nextauth-4/src/pages/_app.tsx b/examples/core/auth-nextjs-pages-nextauth-4/src/pages/_app.tsx index b8e40df7033..c5247a06bd5 100644 --- a/examples/core/auth-nextjs-pages-nextauth-4/src/pages/_app.tsx +++ b/examples/core/auth-nextjs-pages-nextauth-4/src/pages/_app.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import Head from 'next/head'; import { useRouter } from 'next/router'; @@ -72,14 +72,14 @@ function AppLayout({ children }: { children: React.ReactNode }) { - {children} - + ); } diff --git a/examples/core/auth-nextjs-pages/src/pages/_app.tsx b/examples/core/auth-nextjs-pages/src/pages/_app.tsx index e2642586973..0a1f564cb66 100644 --- a/examples/core/auth-nextjs-pages/src/pages/_app.tsx +++ b/examples/core/auth-nextjs-pages/src/pages/_app.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import Head from 'next/head'; @@ -71,14 +71,14 @@ function AppLayout({ children }: { children: React.ReactNode }) { - {children} - + ); } diff --git a/examples/core/auth-nextjs-passkey/src/app/layout.tsx b/examples/core/auth-nextjs-passkey/src/app/layout.tsx index 016a1662c3c..b91589627b4 100644 --- a/examples/core/auth-nextjs-passkey/src/app/layout.tsx +++ b/examples/core/auth-nextjs-passkey/src/app/layout.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; @@ -40,14 +40,14 @@ export default async function RootLayout(props: { children: React.ReactNode }) { - {props.children} - + diff --git a/examples/core/auth-nextjs-themed/app/layout.tsx b/examples/core/auth-nextjs-themed/app/layout.tsx index fbf6fb8f44d..3fceadb73cb 100644 --- a/examples/core/auth-nextjs-themed/app/layout.tsx +++ b/examples/core/auth-nextjs-themed/app/layout.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; @@ -36,14 +36,14 @@ export default async function RootLayout({ children }: Readonly<{ children: Reac - {children} - + diff --git a/examples/core/auth-nextjs/src/app/layout.tsx b/examples/core/auth-nextjs/src/app/layout.tsx index 6ec47c8dfc5..ed6df4dbcc3 100644 --- a/examples/core/auth-nextjs/src/app/layout.tsx +++ b/examples/core/auth-nextjs/src/app/layout.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; @@ -40,14 +40,14 @@ export default async function RootLayout(props: { children: React.ReactNode }) { - {props.children} - + diff --git a/examples/core/auth-vite/package.json b/examples/core/auth-vite/package.json index cb0751eb5c6..d1d1bc8abd1 100644 --- a/examples/core/auth-vite/package.json +++ b/examples/core/auth-vite/package.json @@ -15,7 +15,7 @@ "@toolpad/core": "latest", "react": "^18", "react-dom": "^18", - "react-router-dom": "^6" + "react-router": "^7" }, "devDependencies": { "@types/react": "^18", diff --git a/examples/core/auth-vite/src/App.tsx b/examples/core/auth-vite/src/App.tsx index 075aa3c62c1..1a54541e4ff 100644 --- a/examples/core/auth-vite/src/App.tsx +++ b/examples/core/auth-vite/src/App.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { AppProvider } from '@toolpad/core/react-router-dom'; -import { Outlet, useNavigate } from 'react-router-dom'; -import type { Navigation, Session } from '@toolpad/core'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; +import { Outlet, useNavigate } from 'react-router'; +import type { Navigation, Session } from '@toolpad/core/AppProvider'; import { SessionContext } from './SessionContext'; const NAVIGATION: Navigation = [ @@ -43,14 +43,14 @@ export default function App() { return ( - - + ); } diff --git a/examples/core/auth-vite/src/layouts/dashboard.tsx b/examples/core/auth-vite/src/layouts/dashboard.tsx index 39b681178b6..03a99900aa0 100644 --- a/examples/core/auth-vite/src/layouts/dashboard.tsx +++ b/examples/core/auth-vite/src/layouts/dashboard.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Outlet, Navigate, useLocation } from 'react-router-dom'; +import { Outlet, Navigate, useLocation } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import { useSession } from '../SessionContext'; diff --git a/examples/core/auth-vite/src/main.tsx b/examples/core/auth-vite/src/main.tsx index ceee289fe2c..d5929bec598 100644 --- a/examples/core/auth-vite/src/main.tsx +++ b/examples/core/auth-vite/src/main.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router'; import App from './App'; import Layout from './layouts/dashboard'; import DashboardPage from './pages'; diff --git a/examples/core/auth-vite/src/pages/signIn.tsx b/examples/core/auth-vite/src/pages/signIn.tsx index f01c9e9993a..17008f42546 100644 --- a/examples/core/auth-vite/src/pages/signIn.tsx +++ b/examples/core/auth-vite/src/pages/signIn.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { SignInPage } from '@toolpad/core/SignInPage'; import type { Session } from '@toolpad/core/AppProvider'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate } from 'react-router'; import { useSession } from '../SessionContext'; const fakeAsyncGetSession = async (formData: any): Promise => { diff --git a/examples/core/firebase-vite/package.json b/examples/core/firebase-vite/package.json index 029bb677f2b..196dfc54160 100644 --- a/examples/core/firebase-vite/package.json +++ b/examples/core/firebase-vite/package.json @@ -23,7 +23,7 @@ "@toolpad/core": "latest", "react": "^18", "react-dom": "^18", - "react-router-dom": "^6" + "react-router": "^7" }, "devDependencies": { "@types/react": "^18", diff --git a/examples/core/firebase-vite/src/App.tsx b/examples/core/firebase-vite/src/App.tsx index 617a1d0b0c6..c3a9b09aec3 100644 --- a/examples/core/firebase-vite/src/App.tsx +++ b/examples/core/firebase-vite/src/App.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { Outlet } from 'react-router-dom'; +import { Outlet } from 'react-router'; import type { User } from 'firebase/auth'; -import { AppProvider } from '@toolpad/core/react-router-dom'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; import type { Navigation, Authentication } from '@toolpad/core/AppProvider'; import { firebaseSignOut, signInWithGoogle, onAuthStateChanged } from './firebase/auth'; import SessionContext, { type Session } from './SessionContext'; @@ -67,7 +67,7 @@ export default function App() { }, []); return ( - - + ); } diff --git a/examples/core/firebase-vite/src/layouts/dashboard.tsx b/examples/core/firebase-vite/src/layouts/dashboard.tsx index 96c8db7ca97..07e4183641b 100644 --- a/examples/core/firebase-vite/src/layouts/dashboard.tsx +++ b/examples/core/firebase-vite/src/layouts/dashboard.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import LinearProgress from '@mui/material/LinearProgress'; -import { Outlet, Navigate, useLocation } from 'react-router-dom'; +import { Outlet, Navigate, useLocation } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import { Account } from '@toolpad/core/Account'; diff --git a/examples/core/firebase-vite/src/main.tsx b/examples/core/firebase-vite/src/main.tsx index 1ccc9f6b4f5..a806e8e3b68 100644 --- a/examples/core/firebase-vite/src/main.tsx +++ b/examples/core/firebase-vite/src/main.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router'; import App from './App'; import Layout from './layouts/dashboard'; import DashboardPage from './pages'; diff --git a/examples/core/firebase-vite/src/pages/signin.tsx b/examples/core/firebase-vite/src/pages/signin.tsx index 47f34565c7a..32e8bdc8e34 100644 --- a/examples/core/firebase-vite/src/pages/signin.tsx +++ b/examples/core/firebase-vite/src/pages/signin.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import Alert from '@mui/material/Alert'; import LinearProgress from '@mui/material/LinearProgress'; import { SignInPage } from '@toolpad/core/SignInPage'; -import { Navigate, useNavigate } from 'react-router-dom'; +import { Navigate, useNavigate } from 'react-router'; import { useSession, type Session } from '../SessionContext'; import { signInWithGoogle, signInWithGithub, signInWithCredentials } from '../firebase/auth'; diff --git a/examples/core/tutorial/app/layout.tsx b/examples/core/tutorial/app/layout.tsx index 06dd5f497d2..490c41047c0 100644 --- a/examples/core/tutorial/app/layout.tsx +++ b/examples/core/tutorial/app/layout.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; @@ -30,9 +30,9 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac }> - + {children} - + diff --git a/examples/core/vite/package.json b/examples/core/vite/package.json index afe44cc4cf7..3008c9ec588 100644 --- a/examples/core/vite/package.json +++ b/examples/core/vite/package.json @@ -15,7 +15,7 @@ "@toolpad/core": "latest", "react": "^18", "react-dom": "^18", - "react-router-dom": "^6" + "react-router": "^7" }, "devDependencies": { "@types/react": "^18", diff --git a/examples/core/vite/src/App.tsx b/examples/core/vite/src/App.tsx index 2c6147c8788..ea7cb04796c 100644 --- a/examples/core/vite/src/App.tsx +++ b/examples/core/vite/src/App.tsx @@ -1,8 +1,9 @@ import * as React from 'react'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { Outlet } from 'react-router-dom'; -import { AppProvider, type Navigation } from '@toolpad/core/react-router-dom'; +import { Outlet } from 'react-router'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; +import type { Navigation } from '@toolpad/core/AppProvider'; const NAVIGATION: Navigation = [ { @@ -26,8 +27,8 @@ const BRANDING = { export default function App() { return ( - + - + ); } diff --git a/examples/core/vite/src/layouts/dashboard.tsx b/examples/core/vite/src/layouts/dashboard.tsx index c540feb6e0f..84b8584f7c6 100644 --- a/examples/core/vite/src/layouts/dashboard.tsx +++ b/examples/core/vite/src/layouts/dashboard.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Outlet } from 'react-router-dom'; +import { Outlet } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; diff --git a/examples/core/vite/src/main.tsx b/examples/core/vite/src/main.tsx index 882c91c0bff..cee7678c361 100644 --- a/examples/core/vite/src/main.tsx +++ b/examples/core/vite/src/main.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router'; import App from './App'; import Layout from './layouts/dashboard'; import DashboardPage from './pages'; diff --git a/packages/create-toolpad-app/src/templates/nextjs-app/rootLayout.ts b/packages/create-toolpad-app/src/templates/nextjs-app/rootLayout.ts index 2ada7023096..b0c9aed2ad5 100644 --- a/packages/create-toolpad-app/src/templates/nextjs-app/rootLayout.ts +++ b/packages/create-toolpad-app/src/templates/nextjs-app/rootLayout.ts @@ -4,7 +4,7 @@ const rootLayout: Template = (options) => { const authEnabled = options.auth; return `import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; @@ -59,7 +59,7 @@ export default ${authEnabled ? 'async ' : ''}function RootLayout(props: { childr ${authEnabled ? '' : ''} ${authEnabled ? '' : '}>'} - {props.children} - + ${authEnabled ? '' : ''} ${authEnabled ? '' : ''} diff --git a/packages/create-toolpad-app/src/templates/nextjs-pages/app.ts b/packages/create-toolpad-app/src/templates/nextjs-pages/app.ts index 4f4f24b9092..8689e8b9b6b 100644 --- a/packages/create-toolpad-app/src/templates/nextjs-pages/app.ts +++ b/packages/create-toolpad-app/src/templates/nextjs-pages/app.ts @@ -4,7 +4,7 @@ const app: Template = (options) => { const authEnabled = options.auth; return `import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; import Head from 'next/head'; @@ -104,7 +104,7 @@ function AppLayout({ children }: { children: React.ReactNode }) { - {children} - + ); } diff --git a/packages/toolpad-core/package.json b/packages/toolpad-core/package.json index 0ac7906f86c..cb1d58451f0 100644 --- a/packages/toolpad-core/package.json +++ b/packages/toolpad-core/package.json @@ -76,7 +76,7 @@ "next": "^15.1.2", "next-router-mock": "^0.9.13", "playwright": "^1.47.2", - "react-router-dom": "6.26.2", + "react-router": "7.1.0", "sinon": "^19.0.2", "vitest": "2.1.8" }, @@ -85,13 +85,13 @@ "@mui/material": "5 - 6", "next": "^14 || ^15", "react": "^18", - "react-router-dom": "^6" + "react-router": "^7" }, "peerDependenciesMeta": { "next": { "optional": true }, - "react-router-dom": { + "react-router": { "optional": true } }, diff --git a/packages/toolpad-core/src/nextjs/AppProvider.tsx b/packages/toolpad-core/src/nextjs/AppProvider.tsx deleted file mode 100644 index 6555738697b..00000000000 --- a/packages/toolpad-core/src/nextjs/AppProvider.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; -import * as React from 'react'; -import { useRouter } from 'next/compat/router'; -import { AppProviderNextApp } from './AppProviderNextApp'; -import { AppProviderNextPages } from './AppProviderNextPages'; -import type { AppProviderProps } from '../AppProvider'; - -/** - * @ignore - internal component. - */ -function AppProvider(props: AppProviderProps) { - const router = useRouter(); - const AppProviderComponent = router ? AppProviderNextPages : AppProviderNextApp; - return ; -} - -export { AppProvider }; diff --git a/packages/toolpad-core/src/nextjs/AppProvider.test.tsx b/packages/toolpad-core/src/nextjs/NextAppProvider.test.tsx similarity index 90% rename from packages/toolpad-core/src/nextjs/AppProvider.test.tsx rename to packages/toolpad-core/src/nextjs/NextAppProvider.test.tsx index c171a039395..ba23bedc3d0 100644 --- a/packages/toolpad-core/src/nextjs/AppProvider.test.tsx +++ b/packages/toolpad-core/src/nextjs/NextAppProvider.test.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { describe, test, expect, vi } from 'vitest'; import { render, screen } from '@testing-library/react'; -import { AppProvider } from './AppProvider'; +import { NextAppProvider } from './NextAppProvider'; import { Router } from '../AppProvider'; vi.mock('next/navigation', () => { @@ -39,7 +39,7 @@ function RouterTest({ children }: RouterTestProps) { }; }, [pathname]); - return {children}; + return {children}; } describe('Nextjs AppProvider', () => { diff --git a/packages/toolpad-core/src/nextjs/NextAppProvider.tsx b/packages/toolpad-core/src/nextjs/NextAppProvider.tsx new file mode 100644 index 00000000000..ccfdbfead70 --- /dev/null +++ b/packages/toolpad-core/src/nextjs/NextAppProvider.tsx @@ -0,0 +1,19 @@ +'use client'; +import * as React from 'react'; +import { useRouter } from 'next/compat/router'; +import { NextAppProviderApp } from './NextAppProviderApp'; +import { NextAppProviderPages } from './NextAppProviderPages'; +import type { AppProviderProps } from '../AppProvider'; + +function NextAppProvider(props: AppProviderProps) { + const router = useRouter(); + const AppProvider = router ? NextAppProviderPages : NextAppProviderApp; + return ; +} + +export { + NextAppProvider, + /** TODO: Old usage, remove export from v0.14.0 */ + /** @deprecated Import `NextAppProvider` instead. */ + NextAppProvider as AppProvider, +}; diff --git a/packages/toolpad-core/src/nextjs/AppProviderNextApp.tsx b/packages/toolpad-core/src/nextjs/NextAppProviderApp.tsx similarity index 93% rename from packages/toolpad-core/src/nextjs/AppProviderNextApp.tsx rename to packages/toolpad-core/src/nextjs/NextAppProviderApp.tsx index 64b59b936e9..f01b51a653d 100644 --- a/packages/toolpad-core/src/nextjs/AppProviderNextApp.tsx +++ b/packages/toolpad-core/src/nextjs/NextAppProviderApp.tsx @@ -6,7 +6,7 @@ import type { AppProviderProps, Navigate, Router } from '../AppProvider'; /** * @ignore - internal component. */ -export function AppProviderNextApp(props: AppProviderProps) { +export function NextAppProviderApp(props: AppProviderProps) { const pathname = usePathname(); const searchParams = useSearchParams(); const { push, replace } = useRouter(); diff --git a/packages/toolpad-core/src/nextjs/AppProviderNextPages.tsx b/packages/toolpad-core/src/nextjs/NextAppProviderPages.tsx similarity index 95% rename from packages/toolpad-core/src/nextjs/AppProviderNextPages.tsx rename to packages/toolpad-core/src/nextjs/NextAppProviderPages.tsx index 14763fbd2f7..c26f6c9fc0d 100644 --- a/packages/toolpad-core/src/nextjs/AppProviderNextPages.tsx +++ b/packages/toolpad-core/src/nextjs/NextAppProviderPages.tsx @@ -7,7 +7,7 @@ import type { AppProviderProps, Navigate, Router } from '../AppProvider'; /** * @ignore - internal component. */ -export function AppProviderNextPages(props: AppProviderProps) { +export function NextAppProviderPages(props: AppProviderProps) { const { push, replace, asPath, query } = useRouter(); const search = React.useMemo(() => { diff --git a/packages/toolpad-core/src/nextjs/index.tsx b/packages/toolpad-core/src/nextjs/index.tsx index bd2c0cdccb2..c1b8b9cdcbf 100644 --- a/packages/toolpad-core/src/nextjs/index.tsx +++ b/packages/toolpad-core/src/nextjs/index.tsx @@ -1 +1 @@ -export * from './AppProvider'; +export * from './NextAppProvider'; diff --git a/packages/toolpad-core/src/react-router-dom/index.tsx b/packages/toolpad-core/src/react-router-dom/index.tsx deleted file mode 100644 index bd2c0cdccb2..00000000000 --- a/packages/toolpad-core/src/react-router-dom/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './AppProvider'; diff --git a/packages/toolpad-core/src/react-router-dom/AppProvider.test.tsx b/packages/toolpad-core/src/react-router/ReactRouterAppProvider.test.tsx similarity index 70% rename from packages/toolpad-core/src/react-router-dom/AppProvider.test.tsx rename to packages/toolpad-core/src/react-router/ReactRouterAppProvider.test.tsx index bde0bfc7743..a63e5959264 100644 --- a/packages/toolpad-core/src/react-router-dom/AppProvider.test.tsx +++ b/packages/toolpad-core/src/react-router/ReactRouterAppProvider.test.tsx @@ -5,15 +5,15 @@ import * as React from 'react'; import { describe, test, expect } from 'vitest'; import { render, screen } from '@testing-library/react'; -import { BrowserRouter } from 'react-router-dom'; -import { AppProvider } from './AppProvider'; +import { BrowserRouter } from 'react-router'; +import { ReactRouterAppProvider } from './ReactRouterAppProvider'; describe('React Router AppProvider', () => { test('renders content correctly', async () => { // placeholder test render( - Hello + Hello , ); diff --git a/packages/toolpad-core/src/react-router-dom/AppProvider.tsx b/packages/toolpad-core/src/react-router/ReactRouterAppProvider.tsx similarity index 65% rename from packages/toolpad-core/src/react-router-dom/AppProvider.tsx rename to packages/toolpad-core/src/react-router/ReactRouterAppProvider.tsx index 8977c032337..afb1fdaf89a 100644 --- a/packages/toolpad-core/src/react-router-dom/AppProvider.tsx +++ b/packages/toolpad-core/src/react-router/ReactRouterAppProvider.tsx @@ -1,17 +1,9 @@ 'use client'; import * as React from 'react'; -import { useSearchParams, useLocation, useNavigate } from 'react-router-dom'; -import { - AppProvider as AppProviderComponent, - type AppProviderProps, - Navigate, - Router, -} from '../AppProvider'; +import { useSearchParams, useLocation, useNavigate } from 'react-router'; +import { AppProvider, type AppProviderProps, Navigate, Router } from '../AppProvider/AppProvider'; -/** - * @ignore - internal component. - */ -function AppProvider(props: AppProviderProps) { +function ReactRouterAppProvider(props: AppProviderProps) { const { pathname } = useLocation(); const [searchParams] = useSearchParams(); const navigate = useNavigate(); @@ -38,7 +30,12 @@ function AppProvider(props: AppProviderProps) { [pathname, searchParams, navigateImpl], ); - return ; + return ; } -export { AppProvider }; +export { + ReactRouterAppProvider, + /** TODO: Old usage, remove export from v0.14.0 */ + /** @deprecated Import `ReactRouterAppProvider` instead. */ + ReactRouterAppProvider as AppProvider, +}; diff --git a/packages/toolpad-core/src/react-router/index.tsx b/packages/toolpad-core/src/react-router/index.tsx new file mode 100644 index 00000000000..24a972e324c --- /dev/null +++ b/packages/toolpad-core/src/react-router/index.tsx @@ -0,0 +1 @@ +export * from './ReactRouterAppProvider'; diff --git a/packages/toolpad-studio/package.json b/packages/toolpad-studio/package.json index aa3f5ddd217..584b0b27919 100644 --- a/packages/toolpad-studio/package.json +++ b/packages/toolpad-studio/package.json @@ -134,7 +134,7 @@ "react-inspector": "6.0.2", "react-is": "18.3.1", "react-resizable-panels": "2.1.7", - "react-router-dom": "6.26.2", + "react-router": "7.1.0", "semver": "7.6.3", "serialize-javascript": "6.0.2", "superjson": "2.0.0", diff --git a/packages/toolpad-studio/src/runtime/AppLayout.tsx b/packages/toolpad-studio/src/runtime/AppLayout.tsx index 7c25b46db1b..259375923f3 100644 --- a/packages/toolpad-studio/src/runtime/AppLayout.tsx +++ b/packages/toolpad-studio/src/runtime/AppLayout.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { Box, useTheme } from '@mui/material'; -import { useNavigate, useSearchParams } from 'react-router-dom'; +import { useNavigate, useSearchParams } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; -import { AppProvider } from '@toolpad/core/react-router-dom'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; import { AuthContext } from './useAuth'; const TOOLPAD_DISPLAY_MODE_URL_PARAM = 'toolpad-display'; @@ -83,7 +83,7 @@ export function AppLayout({ ); return ( - + ); } diff --git a/packages/toolpad-studio/src/runtime/PreviewHeader.tsx b/packages/toolpad-studio/src/runtime/PreviewHeader.tsx index e411ab74638..4525e741b18 100644 --- a/packages/toolpad-studio/src/runtime/PreviewHeader.tsx +++ b/packages/toolpad-studio/src/runtime/PreviewHeader.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Button, Typography, Box, useTheme, Alert, ButtonProps } from '@mui/material'; import EditIcon from '@mui/icons-material/Edit'; -import { Link, useMatch } from 'react-router-dom'; +import { Link, useMatch } from 'react-router'; import { useAppHost } from '@toolpad/studio-runtime'; function OpenInEditorButton({ diff --git a/packages/toolpad-studio/src/runtime/SignInPage.tsx b/packages/toolpad-studio/src/runtime/SignInPage.tsx index 501eca11604..23abeb6d71f 100644 --- a/packages/toolpad-studio/src/runtime/SignInPage.tsx +++ b/packages/toolpad-studio/src/runtime/SignInPage.tsx @@ -13,7 +13,7 @@ import GitHubIcon from '@mui/icons-material/GitHub'; import PasswordIcon from '@mui/icons-material/Password'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { LoadingButton } from '@mui/lab'; -import { useSearchParams } from 'react-router-dom'; +import { useSearchParams } from 'react-router'; import { useForm, Controller, SubmitHandler } from 'react-hook-form'; import { AuthProvider, AuthContext } from './useAuth'; import productIconDark from '../../public/product-icon-dark.svg'; diff --git a/packages/toolpad-studio/src/runtime/ToolpadApp.tsx b/packages/toolpad-studio/src/runtime/ToolpadApp.tsx index 7f095315a08..c47c37b1269 100644 --- a/packages/toolpad-studio/src/runtime/ToolpadApp.tsx +++ b/packages/toolpad-studio/src/runtime/ToolpadApp.tsx @@ -58,7 +58,7 @@ import { useParams, Outlet, BrowserRouter, -} from 'react-router-dom'; +} from 'react-router'; import { ErrorBoundary, FallbackProps } from 'react-error-boundary'; import ErrorIcon from '@mui/icons-material/Error'; import { getBrowserRuntime } from '@toolpad/studio-runtime/jsBrowserRuntime'; diff --git a/packages/toolpad-studio/src/runtime/useAuth.ts b/packages/toolpad-studio/src/runtime/useAuth.ts index 2800acea214..468e426d1db 100644 --- a/packages/toolpad-studio/src/runtime/useAuth.ts +++ b/packages/toolpad-studio/src/runtime/useAuth.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import * as appDom from '@toolpad/studio-runtime/appDom'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router'; import { useAppHost } from '@toolpad/studio-runtime'; const AUTH_API_PATH = '/api/auth'; diff --git a/packages/toolpad-studio/src/toolpad/AppEditor/index.tsx b/packages/toolpad-studio/src/toolpad/AppEditor/index.tsx index b208290d3e4..da33e1199d7 100644 --- a/packages/toolpad-studio/src/toolpad/AppEditor/index.tsx +++ b/packages/toolpad-studio/src/toolpad/AppEditor/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { styled } from '@mui/material'; -import { useNavigate, useLocation } from 'react-router-dom'; +import { useNavigate, useLocation } from 'react-router'; import PageEditor from './PageEditor'; import { useAppState } from '../AppState'; import AppEditorShell from './AppEditorShell'; diff --git a/packages/toolpad-studio/src/toolpad/AppState.tsx b/packages/toolpad-studio/src/toolpad/AppState.tsx index bc849b0cb8c..82ee78b5508 100644 --- a/packages/toolpad-studio/src/toolpad/AppState.tsx +++ b/packages/toolpad-studio/src/toolpad/AppState.tsx @@ -3,7 +3,7 @@ import { NodeHashes, NodeId } from '@toolpad/studio-runtime'; import { createProvidedContext } from '@toolpad/utils/react'; import invariant from 'invariant'; import { debounce, DebouncedFunc } from 'lodash-es'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router'; import { mapValues } from '@toolpad/utils/collections'; import useDebouncedHandler from '@toolpad/utils/hooks/useDebouncedHandler'; import useEventCallback from '@mui/utils/useEventCallback'; diff --git a/packages/toolpad-studio/src/toolpad/Toolpad.tsx b/packages/toolpad-studio/src/toolpad/Toolpad.tsx index 92a14a7c510..4c2b21f4def 100644 --- a/packages/toolpad-studio/src/toolpad/Toolpad.tsx +++ b/packages/toolpad-studio/src/toolpad/Toolpad.tsx @@ -1,7 +1,7 @@ import { CircularProgress, Box, styled, CssBaseline, Button, Stack, Tooltip } from '@mui/material'; import * as React from 'react'; import { ErrorBoundary, FallbackProps } from 'react-error-boundary'; -import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom'; +import { BrowserRouter, Routes, Route, useLocation } from 'react-router'; import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import CloudDoneIcon from '@mui/icons-material/CloudDone'; import SyncIcon from '@mui/icons-material/Sync'; diff --git a/packages/toolpad-studio/src/toolpad/ToolpadShell/ToolpadNavigation.tsx b/packages/toolpad-studio/src/toolpad/ToolpadShell/ToolpadNavigation.tsx index 9785f3729c6..a8988916c17 100644 --- a/packages/toolpad-studio/src/toolpad/ToolpadShell/ToolpadNavigation.tsx +++ b/packages/toolpad-studio/src/toolpad/ToolpadShell/ToolpadNavigation.tsx @@ -11,7 +11,7 @@ import { IconButton, Tooltip, } from '@mui/material'; -import { Link, matchPath, useLocation } from 'react-router-dom'; +import { Link, matchPath, useLocation } from 'react-router'; const DRAWER_WIDTH = 44; // px diff --git a/packages/toolpad-studio/src/utils/domView.ts b/packages/toolpad-studio/src/utils/domView.ts index 4dc75658206..76d1e8380f0 100644 --- a/packages/toolpad-studio/src/utils/domView.ts +++ b/packages/toolpad-studio/src/utils/domView.ts @@ -1,5 +1,5 @@ import { NodeId } from '@toolpad/studio-runtime'; -import { matchPath } from 'react-router-dom'; +import { matchPath } from 'react-router'; import { QueryNode, FetchMode } from '@toolpad/studio-runtime/appDom'; export type QueryMeta = { diff --git a/playground/nextjs-pages/src/pages/_app.tsx b/playground/nextjs-pages/src/pages/_app.tsx index 4efcb23d5d7..f6e5e6da068 100644 --- a/playground/nextjs-pages/src/pages/_app.tsx +++ b/playground/nextjs-pages/src/pages/_app.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { PageContainer } from '@toolpad/core/PageContainer'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import Head from 'next/head'; @@ -72,14 +72,14 @@ function AppLayout({ children }: { children: React.ReactNode }) { - {children} - + ); } diff --git a/playground/nextjs/src/app/layout.tsx b/playground/nextjs/src/app/layout.tsx index 670a4c390dc..5944077d7f6 100644 --- a/playground/nextjs/src/app/layout.tsx +++ b/playground/nextjs/src/app/layout.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { AppProvider } from '@toolpad/core/nextjs'; +import { NextAppProvider } from '@toolpad/core/nextjs'; import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; @@ -41,14 +41,14 @@ export default async function RootLayout(props: { children: React.ReactNode }) { - {props.children} - + diff --git a/playground/vite/package.json b/playground/vite/package.json index 10333ecb496..a1c97054815 100644 --- a/playground/vite/package.json +++ b/playground/vite/package.json @@ -18,7 +18,7 @@ "@vitejs/plugin-react": "4.3.4", "react": "18.3.1", "react-dom": "18.3.1", - "react-router-dom": "6.26.2", + "react-router": "7.1.0", "vite": "5.4.11" } } diff --git a/playground/vite/src/App.tsx b/playground/vite/src/App.tsx index 2c6147c8788..ea7cb04796c 100644 --- a/playground/vite/src/App.tsx +++ b/playground/vite/src/App.tsx @@ -1,8 +1,9 @@ import * as React from 'react'; import DashboardIcon from '@mui/icons-material/Dashboard'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { Outlet } from 'react-router-dom'; -import { AppProvider, type Navigation } from '@toolpad/core/react-router-dom'; +import { Outlet } from 'react-router'; +import { ReactRouterAppProvider } from '@toolpad/core/react-router'; +import type { Navigation } from '@toolpad/core/AppProvider'; const NAVIGATION: Navigation = [ { @@ -26,8 +27,8 @@ const BRANDING = { export default function App() { return ( - + - + ); } diff --git a/playground/vite/src/layouts/dashboard.tsx b/playground/vite/src/layouts/dashboard.tsx index c540feb6e0f..84b8584f7c6 100644 --- a/playground/vite/src/layouts/dashboard.tsx +++ b/playground/vite/src/layouts/dashboard.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Outlet } from 'react-router-dom'; +import { Outlet } from 'react-router'; import { DashboardLayout } from '@toolpad/core/DashboardLayout'; import { PageContainer } from '@toolpad/core/PageContainer'; diff --git a/playground/vite/src/main.tsx b/playground/vite/src/main.tsx index 882c91c0bff..cee7678c361 100644 --- a/playground/vite/src/main.tsx +++ b/playground/vite/src/main.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router'; import App from './App'; import Layout from './layouts/dashboard'; import DashboardPage from './pages'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f193c84faa7..507276099b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -455,8 +455,8 @@ importers: specifier: 18.3.1 version: 18.3.1 react-router: - specifier: 6.26.2 - version: 6.26.2(react@18.3.1) + specifier: 7.1.0 + version: 7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: specifier: 6.26.2 version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -671,9 +671,9 @@ importers: playwright: specifier: ^1.47.2 version: 1.48.2 - react-router-dom: - specifier: 6.26.2 - version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router: + specifier: 7.1.0 + version: 7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) sinon: specifier: ^19.0.2 version: 19.0.2 @@ -918,9 +918,9 @@ importers: react-resizable-panels: specifier: 2.1.7 version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-router-dom: - specifier: 6.26.2 - version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router: + specifier: 7.1.0 + version: 7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) semver: specifier: 7.6.3 version: 7.6.3 @@ -1321,9 +1321,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - react-router-dom: - specifier: 6.26.2 - version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router: + specifier: 7.1.0 + version: 7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) vite: specifier: 5.4.11 version: 5.4.11(@types/node@20.17.12)(terser@5.36.0) @@ -9170,6 +9170,16 @@ packages: peerDependencies: react: '>=16.8' + react-router@7.1.0: + resolution: {integrity: sha512-VcFhWqkNIcojDRYaUO8qV0Jib52s9ULpCp3nkBbmrvtoCVFRp6tmk3tJ2w9BZauVctA1YRnJlFYDn9iJRuCpGA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react-runner@1.0.5: resolution: {integrity: sha512-eCIybRpssp6ffjqXqId024esO9UP2lV838Lvm3fC7VgMQ/dQHhR0jJwOY2IPrYD3AaM/bcvMikmASIRZqNUHsw==} peerDependencies: @@ -10198,6 +10208,9 @@ packages: resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} engines: {node: ^16.14.0 || >=18.0.0} + turbo-stream@2.4.0: + resolution: {integrity: sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -19812,6 +19825,16 @@ snapshots: '@remix-run/router': 1.19.2 react: 18.3.1 + react-router@7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@types/cookie': 0.6.0 + cookie: 1.0.1 + react: 18.3.1 + set-cookie-parser: 2.7.1 + turbo-stream: 2.4.0 + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) + react-runner@1.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 @@ -21012,6 +21035,8 @@ snapshots: transitivePeerDependencies: - supports-color + turbo-stream@2.4.0: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 diff --git a/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts b/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts index 7f1f29ebf29..7348f0141fa 100644 --- a/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts +++ b/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts @@ -3,6 +3,12 @@ import fs from 'fs'; const repositoryRoot = path.resolve(__dirname, '../../../..'); +function findMatchingFileName(directory: string, name: string) { + const files = fs.readdirSync(directory); + const matchingFile = files.find((file) => file.endsWith(name)); + return matchingFile ? matchingFile.replace(/\.[^/.]+$/, '') : null; // Remove the extension +} + export function getComponentImports(name: string, filename: string) { const relativePath = path.relative(repositoryRoot, filename); const directories = path.dirname(relativePath).split(path.sep); @@ -21,18 +27,20 @@ export function getComponentImports(name: string, filename: string) { const componentDirectory = directories[3]; if (componentDirectory === name) { const nextjsRelativePath = path.resolve(relativePath, '../../nextjs'); - const hasNextJsVersion = fs.existsSync(`${nextjsRelativePath}/${name}.tsx`); + const nextjsFileName = findMatchingFileName(nextjsRelativePath, `${name}.tsx`); - const reactRouterDOMRelativePath = path.resolve(relativePath, '../../react-router-dom'); - const hasReactRouterDOMVersion = fs.existsSync(`${reactRouterDOMRelativePath}/${name}.tsx`); + const reactRouterRelativePath = path.resolve(relativePath, '../../react-router'); + const reactRouterFileName = findMatchingFileName(reactRouterRelativePath, `${name}.tsx`); return [ `import { ${name} } from '@toolpad/core/${name}';`, `import { ${name} } from '@toolpad/core';${ - hasNextJsVersion ? `\nimport { ${name} } from '@toolpad/core/nextjs'; // Next.js` : '' + nextjsFileName + ? `\nimport { ${nextjsFileName} } from '@toolpad/core/nextjs'; // Next.js` + : '' }${ - hasReactRouterDOMVersion - ? `\nimport { ${name} } from '@toolpad/core/react-router-dom'; // React Router` + reactRouterFileName + ? `\nimport { ${reactRouterFileName} } from '@toolpad/core/react-router'; // React Router` : '' }`, ]; diff --git a/scripts/docs/buildCoreApiDocs/config/projectSettings.ts b/scripts/docs/buildCoreApiDocs/config/projectSettings.ts index 1702025b097..aa8de4fca9a 100644 --- a/scripts/docs/buildCoreApiDocs/config/projectSettings.ts +++ b/scripts/docs/buildCoreApiDocs/config/projectSettings.ts @@ -26,7 +26,7 @@ export const projectSettings: ProjectSettings = { const relativePath = path.relative(repositoryRoot, filename); const directories = path.dirname(relativePath).split(path.sep); - return directories[3] === 'nextjs' || directories[3] === 'react-router-dom'; + return directories[3] === 'nextjs' || directories[3] === 'react-router'; }, skipSlotsAndClasses: false, translationPagesDirectory: 'docs/translations/api-docs',