From f17770bf80cdb46b97fa20e6c1cf1d788db70afa Mon Sep 17 00:00:00 2001 From: IzumiSy Date: Fri, 31 Jul 2026 12:21:23 +0900 Subject: [PATCH 1/4] feat(routing)!: upgrade react-router to v8 --- .changeset/mean-oranges-rest.md | 19 +++ docs/concepts/routing-navigation.md | 4 +- packages/core/package.json | 6 +- packages/core/src/routing/router.test.tsx | 10 +- packages/core/src/routing/router.tsx | 14 +- pnpm-lock.yaml | 159 +++++++++++----------- pnpm-workspace.yaml | 4 +- 7 files changed, 116 insertions(+), 100 deletions(-) create mode 100644 .changeset/mean-oranges-rest.md diff --git a/.changeset/mean-oranges-rest.md b/.changeset/mean-oranges-rest.md new file mode 100644 index 00000000..1d026d38 --- /dev/null +++ b/.changeset/mean-oranges-rest.md @@ -0,0 +1,19 @@ +--- +"@tailor-platform/app-shell": major +--- + +Upgrade AppShell to React Router v8 and raise the minimum supported `react` / `react-dom` version to `19.2.7`. + +If your app uses router primitives alongside AppShell, import them from `@tailor-platform/app-shell` so they share the same router context. + +Before: + +```tsx +import { Link, useNavigate } from "react-router"; +``` + +After: + +```tsx +import { Link, useNavigate } from "@tailor-platform/app-shell"; +``` diff --git a/docs/concepts/routing-navigation.md b/docs/concepts/routing-navigation.md index 9c846d8f..3bb1e191 100644 --- a/docs/concepts/routing-navigation.md +++ b/docs/concepts/routing-navigation.md @@ -5,9 +5,9 @@ description: Learn how to navigate between pages using React Router hooks and co # Routing and Navigation -Because AppShell manages routing internally, it has its own instance of the RouterProvider from `react-router`. +Because AppShell manages routing internally, it owns the application's `RouterProvider` instance. -To use client-side navigation from AppShell pages, instead of installing `react-router` to package.json and importing components and hooks from your application's dependencies, we must use the exports from `@tailor-platform/app-shell`, such as `Link` component, or `useParams`, `useNavigate` hooks. These components and hooks internally use the correct context for the AppShell `RouterProvider` to properly recognize the intent. +To use client-side navigation from AppShell pages, use the exports from `@tailor-platform/app-shell`, such as the `Link` component or `useParams` / `useNavigate` hooks, instead of importing those primitives from your app's `react-router` dependency. This keeps every hook and component on the same router context; mixing AppShell with a separate `react-router` import can fail at runtime, especially across mismatched major versions. ## Exported React Router Hooks diff --git a/packages/core/package.json b/packages/core/package.json index df503f86..20b611a5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -62,7 +62,7 @@ "lucide-react": "^1.8.0", "openai": "6.45.0", "papaparse": "^5.5.3", - "react-router": "^7.18.2", + "react-router": "^8.3.0", "sonner": "^2.0.7", "tailwind-merge": "^3.6.0" }, @@ -90,7 +90,7 @@ "vitest": "catalog:" }, "peerDependencies": { - "react": ">= 19", - "react-dom": ">= 19" + "react": ">=19.2.7", + "react-dom": ">=19.2.7" } } diff --git a/packages/core/src/routing/router.test.tsx b/packages/core/src/routing/router.test.tsx index 5373c55c..59ab711c 100644 --- a/packages/core/src/routing/router.test.tsx +++ b/packages/core/src/routing/router.test.tsx @@ -1,8 +1,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { act, cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react"; -import { RouterContainer } from "./router"; +import { RouterContainer, routerFactories } from "./router"; import { AppShellConfigContext, AppShellDataContext } from "@/contexts/appshell-context"; -import * as ReactRouter from "react-router"; import { Link, Outlet, useNavigate } from "react-router"; import { defineModule, @@ -518,7 +517,7 @@ describe("RouterContainer with AuthProvider", () => { isReady: false, }; const listeners: Array<(event: { type: string }) => void> = []; - const createMemoryRouterSpy = vi.spyOn(ReactRouter, "createMemoryRouter"); + const createMemoryRouterSpy = vi.spyOn(routerFactories, "createMemoryRouter"); const authClient = createMockAuthClient(snapshot, { getState: vi.fn(() => snapshot), @@ -541,8 +540,6 @@ describe("RouterContainer with AuthProvider", () => { }); expect(await screen.findByText("Loading...")).toBeDefined(); - // With guardComponent now applied in AuthProvider (not the router), - // RouterContainer is not mounted until auth is ready. expect(createMemoryRouterSpy).toHaveBeenCalledTimes(0); act(() => { @@ -557,7 +554,6 @@ describe("RouterContainer with AuthProvider", () => { }); expect(await screen.findByText("Home")).toBeDefined(); - // Router is created once when children first render after auth is ready. expect(createMemoryRouterSpy).toHaveBeenCalledTimes(1); } finally { createMemoryRouterSpy.mockRestore(); @@ -565,7 +561,7 @@ describe("RouterContainer with AuthProvider", () => { }); it("recreates the router when route-defining config changes", async () => { - const createMemoryRouterSpy = vi.spyOn(ReactRouter, "createMemoryRouter"); + const createMemoryRouterSpy = vi.spyOn(routerFactories, "createMemoryRouter"); const module = defineModule({ path: "dashboard", component: () =>
Dashboard
, diff --git a/packages/core/src/routing/router.tsx b/packages/core/src/routing/router.tsx index e67ca986..ef039df9 100644 --- a/packages/core/src/routing/router.tsx +++ b/packages/core/src/routing/router.tsx @@ -1,5 +1,6 @@ import { type PropsWithChildren, type ReactNode, useMemo } from "react"; -import { Outlet, createMemoryRouter, createBrowserRouter, RouterProvider } from "react-router"; +import { Outlet, createMemoryRouter, createBrowserRouter } from "react-router"; +import { RouterProvider } from "react-router/dom"; import type { RouteObject } from "react-router"; import { createContentRoutes, wrapErrorBoundary } from "./routes"; import { useAppShellConfig, type RootConfiguration } from "@/contexts/appshell-context"; @@ -68,6 +69,13 @@ export type RouterContainerProps = initialEntries: Array; }; +// Small indirection so tests can observe router creation under react-router v8's +// ESM-only exports, which Vitest cannot spy on directly. +export const routerFactories = { + createBrowserRouter, + createMemoryRouter, +}; + export const RouterContainer = (props: PropsWithChildren) => { const { children } = props; const { configurations } = useAppShellConfig(); @@ -101,11 +109,11 @@ export const RouterContainer = (props: PropsWithChildren) const router = useMemo( () => props.memory - ? createMemoryRouter(routes, { + ? routerFactories.createMemoryRouter(routes, { basename, ...(initialEntries ? { initialEntries } : {}), }) - : createBrowserRouter(routes, { + : routerFactories.createBrowserRouter(routes, { basename, }), [basename, initialEntries, props.memory, routes], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index feb2d264..e26351cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,11 +31,11 @@ catalogs: specifier: ^1.64.0 version: 1.64.0 react: - specifier: ^19.2.6 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.8 react-dom: - specifier: ^19.2.6 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.8 tailwindcss: specifier: ^4.2.4 version: 4.3.0 @@ -128,10 +128,10 @@ importers: version: 16.6.1 react: specifier: 'catalog:' - version: 19.2.6 + version: 19.2.8 react-dom: specifier: 'catalog:' - version: 19.2.6(react@19.2.6) + version: 19.2.8(react@19.2.8) tailwindcss: specifier: 'catalog:' version: 4.3.0 @@ -146,25 +146,25 @@ importers: dependencies: '@hookform/resolvers': specifier: ^5.2.2 - version: 5.4.0(react-hook-form@7.71.2(react@19.2.6)) + version: 5.4.0(react-hook-form@7.71.2(react@19.2.8)) '@tailor-platform/app-shell': specifier: workspace:* version: link:../../packages/core lucide-react: specifier: 'catalog:' - version: 1.8.0(react@19.2.6) + version: 1.8.0(react@19.2.8) next: specifier: 16.2.6 - version: 16.2.6(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.1)(@playwright/test@1.51.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 16.2.6(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.1)(@playwright/test@1.51.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) react: specifier: 'catalog:' - version: 19.2.6 + version: 19.2.8 react-dom: specifier: 'catalog:' - version: 19.2.6(react@19.2.6) + version: 19.2.8(react@19.2.8) react-hook-form: specifier: ^7.71.2 - version: 7.71.2(react@19.2.6) + version: 7.71.2(react@19.2.8) zod: specifier: ^3.24.0 version: 3.25.76 @@ -201,13 +201,13 @@ importers: version: link:../../packages/core lucide-react: specifier: 'catalog:' - version: 1.8.0(react@19.2.6) + version: 1.8.0(react@19.2.8) react: specifier: 'catalog:' - version: 19.2.6 + version: 19.2.8 react-dom: specifier: 'catalog:' - version: 19.2.6(react@19.2.6) + version: 19.2.8(react@19.2.8) tailwindcss: specifier: 'catalog:' version: 4.3.0 @@ -235,7 +235,7 @@ importers: dependencies: '@base-ui/react': specifier: ^1.6.0 - version: 1.6.0(@types/react@19.2.13)(date-fns@4.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 1.6.0(@types/react@19.2.13)(date-fns@4.4.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@internationalized/date': specifier: 3.12.2 version: 3.12.2 @@ -262,7 +262,7 @@ importers: version: 2.2.0 lucide-react: specifier: ^1.8.0 - version: 1.8.0(react@19.2.6) + version: 1.8.0(react@19.2.8) openai: specifier: 6.45.0 version: 6.45.0(ws@8.21.0)(zod@4.4.3) @@ -270,11 +270,11 @@ importers: specifier: ^5.5.3 version: 5.5.3 react-router: - specifier: ^7.18.2 - version: 7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + specifier: ^8.3.0 + version: 8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8) sonner: specifier: ^2.0.7 - version: 2.0.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8) tailwind-merge: specifier: ^3.6.0 version: 3.6.0 @@ -284,7 +284,7 @@ importers: version: 4.3.0 '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@testing-library/user-event': specifier: ^14.6.1 version: 14.6.1(@testing-library/dom@10.4.1) @@ -314,10 +314,10 @@ importers: version: 8.5.18 react: specifier: 'catalog:' - version: 19.2.6 + version: 19.2.8 react-dom: specifier: 'catalog:' - version: 19.2.6(react@19.2.6) + version: 19.2.8(react@19.2.8) tailwindcss: specifier: 'catalog:' version: 4.3.0 @@ -3869,9 +3869,8 @@ packages: resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - cookie@1.1.1: - resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} - engines: {node: '>=18'} + cookie-es@3.1.1: + resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} @@ -5223,10 +5222,10 @@ packages: peerDependencies: react: ^19.2.5 - react-dom@19.2.6: - resolution: {integrity: sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==} + react-dom@19.2.8: + resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} peerDependencies: - react: ^19.2.6 + react: ^19.2.8 react-hook-form@7.71.2: resolution: {integrity: sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==} @@ -5250,12 +5249,12 @@ packages: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} - react-router@7.18.2: - resolution: {integrity: sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==} - engines: {node: '>=20.0.0'} + react-router@8.3.0: + resolution: {integrity: sha512-qyPMvW83jGIct3yiieisxdk9M745anqhpIMKN5m1t6yBMfgVPpt77aHOqs5fUlEJRMCGffg9BaQLH9oPVOL7xQ==} + engines: {node: '>=22.22.0'} peerDependencies: - react: '>=18' - react-dom: '>=18' + react: '>=19.2.7' + react-dom: '>=19.2.7' peerDependenciesMeta: react-dom: optional: true @@ -5268,8 +5267,8 @@ packages: resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} engines: {node: '>=0.10.0'} - react@19.2.6: - resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==} + react@19.2.8: + resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} engines: {node: '>=0.10.0'} read-yaml-file@1.1.0: @@ -5462,9 +5461,6 @@ packages: engines: {node: '>= 14'} hasBin: true - set-cookie-parser@2.7.2: - resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} - sharp@0.34.5: resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -6231,27 +6227,27 @@ snapshots: '@badgateway/oauth2-client@3.3.1': {} - '@base-ui/react@1.6.0(@types/react@19.2.13)(date-fns@4.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@base-ui/react@1.6.0(@types/react@19.2.13)(date-fns@4.4.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 - '@base-ui/utils': 0.3.1(@types/react@19.2.13)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@floating-ui/react-dom': 2.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@base-ui/utils': 0.3.1(@types/react@19.2.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@floating-ui/utils': 0.2.11 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) - use-sync-external-store: 1.6.0(react@19.2.6) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + use-sync-external-store: 1.6.0(react@19.2.8) optionalDependencies: '@types/react': 19.2.13 date-fns: 4.4.0 - '@base-ui/utils@0.3.1(@types/react@19.2.13)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@base-ui/utils@0.3.1(@types/react@19.2.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 '@floating-ui/utils': 0.2.11 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) reselect: 5.2.0 - use-sync-external-store: 1.6.0(react@19.2.6) + use-sync-external-store: 1.6.0(react@19.2.8) optionalDependencies: '@types/react': 19.2.13 @@ -6645,18 +6641,18 @@ snapshots: '@floating-ui/core': 1.7.5 '@floating-ui/utils': 0.2.11 - '@floating-ui/react-dom@2.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@floating-ui/react-dom@2.1.8(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@floating-ui/dom': 1.7.6 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) '@floating-ui/utils@0.2.11': {} - '@hookform/resolvers@5.4.0(react-hook-form@7.71.2(react@19.2.6))': + '@hookform/resolvers@5.4.0(react-hook-form@7.71.2(react@19.2.8))': dependencies: '@standard-schema/utils': 0.3.0 - react-hook-form: 7.71.2(react@19.2.6) + react-hook-form: 7.71.2(react@19.2.8) '@img/colour@1.1.0': optional: true @@ -8418,12 +8414,12 @@ snapshots: picocolors: 1.1.1 pretty-format: 27.5.1 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@babel/runtime': 7.28.6 '@testing-library/dom': 10.4.1 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) optionalDependencies: '@types/react': 19.2.13 '@types/react-dom': 19.2.3(@types/react@19.2.13) @@ -9041,7 +9037,7 @@ snapshots: convert-to-spaces@2.0.1: {} - cookie@1.1.1: {} + cookie-es@3.1.1: {} cross-spawn@7.0.6: dependencies: @@ -9830,9 +9826,9 @@ snapshots: dependencies: yallist: 4.0.0 - lucide-react@1.8.0(react@19.2.6): + lucide-react@1.8.0(react@19.2.8): dependencies: - react: 19.2.6 + react: 19.2.8 lz-string@1.5.0: {} @@ -9960,16 +9956,16 @@ snapshots: optionalDependencies: '@rollup/rollup-linux-x64-gnu': 4.62.3 - next@16.2.6(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.1)(@playwright/test@1.51.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + next@16.2.6(@babel/core@7.29.0(supports-color@8.1.1))(@opentelemetry/api@1.9.1)(@playwright/test@1.51.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: '@next/env': 16.2.6 '@swc/helpers': 0.5.15 baseline-browser-mapping: 2.10.30 caniuse-lite: 1.0.30001793 postcss: 8.4.31 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) - styled-jsx: 5.1.6(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.6) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + styled-jsx: 5.1.6(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.8) optionalDependencies: '@next/swc-darwin-arm64': 16.2.6 '@next/swc-darwin-x64': 16.2.6 @@ -10373,14 +10369,14 @@ snapshots: react: 19.2.5 scheduler: 0.27.0 - react-dom@19.2.6(react@19.2.6): + react-dom@19.2.8(react@19.2.8): dependencies: - react: 19.2.6 + react: 19.2.8 scheduler: 0.27.0 - react-hook-form@7.71.2(react@19.2.6): + react-hook-form@7.71.2(react@19.2.8): dependencies: - react: 19.2.6 + react: 19.2.8 react-is@16.13.1: {} @@ -10393,19 +10389,18 @@ snapshots: react-refresh@0.18.0: {} - react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: - cookie: 1.1.1 - react: 19.2.6 - set-cookie-parser: 2.7.2 + cookie-es: 3.1.1 + react: 19.2.8 optionalDependencies: - react-dom: 19.2.6(react@19.2.6) + react-dom: 19.2.8(react@19.2.8) react@19.1.1: {} react@19.2.5: {} - react@19.2.6: {} + react@19.2.8: {} read-yaml-file@1.1.0: dependencies: @@ -10668,8 +10663,6 @@ snapshots: transitivePeerDependencies: - supports-color - set-cookie-parser@2.7.2: {} - sharp@0.34.5: dependencies: '@img/colour': 1.1.0 @@ -10734,10 +10727,10 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - sonner@2.0.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + sonner@2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8): dependencies: - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) source-map-js@1.2.1: {} @@ -10819,10 +10812,10 @@ snapshots: strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.6): + styled-jsx@5.1.6(@babel/core@7.29.0(supports-color@8.1.1))(react@19.2.8): dependencies: client-only: 0.0.1 - react: 19.2.6 + react: 19.2.8 optionalDependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -11019,9 +11012,9 @@ snapshots: dependencies: punycode: 2.3.1 - use-sync-external-store@1.6.0(react@19.2.6): + use-sync-external-store@1.6.0(react@19.2.8): dependencies: - react: 19.2.6 + react: 19.2.8 util-deprecate@1.0.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 01bd9107..b7373019 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -13,8 +13,8 @@ catalog: lucide-react: ^1.8.0 oxfmt: ^0.47.0 oxlint: ^1.64.0 - react: ^19.2.6 - react-dom: ^19.2.6 + react: ^19.2.7 + react-dom: ^19.2.7 tailwindcss: ^4.2.4 tsdown: ^0.22.0 typescript: ^5 From d8867dea3e620edb274ea60b92fabcfd8c02928d Mon Sep 17 00:00:00 2001 From: IzumiSy Date: Fri, 31 Jul 2026 12:23:39 +0900 Subject: [PATCH 2/4] docs(changeset): trim react-router v8 migration example --- .changeset/mean-oranges-rest.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.changeset/mean-oranges-rest.md b/.changeset/mean-oranges-rest.md index 1d026d38..36f317b8 100644 --- a/.changeset/mean-oranges-rest.md +++ b/.changeset/mean-oranges-rest.md @@ -4,16 +4,4 @@ Upgrade AppShell to React Router v8 and raise the minimum supported `react` / `react-dom` version to `19.2.7`. -If your app uses router primitives alongside AppShell, import them from `@tailor-platform/app-shell` so they share the same router context. - -Before: - -```tsx -import { Link, useNavigate } from "react-router"; -``` - -After: - -```tsx -import { Link, useNavigate } from "@tailor-platform/app-shell"; -``` +This keeps AppShell aligned with the React Router version it owns internally while preserving the existing AppShell routing API for consumers. From 78a1ea4043422ec4fe116a2b1051bd1b0534ea82 Mon Sep 17 00:00:00 2001 From: IzumiSy Date: Fri, 31 Jul 2026 12:24:33 +0900 Subject: [PATCH 3/4] docs(changeset): simplify react-router v8 summary --- .changeset/mean-oranges-rest.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/.changeset/mean-oranges-rest.md b/.changeset/mean-oranges-rest.md index 36f317b8..21add33d 100644 --- a/.changeset/mean-oranges-rest.md +++ b/.changeset/mean-oranges-rest.md @@ -3,5 +3,3 @@ --- Upgrade AppShell to React Router v8 and raise the minimum supported `react` / `react-dom` version to `19.2.7`. - -This keeps AppShell aligned with the React Router version it owns internally while preserving the existing AppShell routing API for consumers. From 810931c156fdd22cfd506923b497fab8929ba343 Mon Sep 17 00:00:00 2001 From: IzumiSy Date: Fri, 31 Jul 2026 12:31:59 +0900 Subject: [PATCH 4/4] docs(changeset): mark react-router v8 upgrade as patch --- .changeset/mean-oranges-rest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/mean-oranges-rest.md b/.changeset/mean-oranges-rest.md index 21add33d..18d45af5 100644 --- a/.changeset/mean-oranges-rest.md +++ b/.changeset/mean-oranges-rest.md @@ -1,5 +1,5 @@ --- -"@tailor-platform/app-shell": major +"@tailor-platform/app-shell": patch --- Upgrade AppShell to React Router v8 and raise the minimum supported `react` / `react-dom` version to `19.2.7`.