From 2963a22c8294111fd7a46c2cba84527aa79097eb 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 | 209 ++++++++++------------ pnpm-workspace.yaml | 4 +- 7 files changed, 136 insertions(+), 130 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 c00883aa..43b75c66 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 64125741..057a6af0 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 @@ -45,6 +45,9 @@ catalogs: typescript: specifier: ^5 version: 5.9.3 + vite: + specifier: ^7.3.2 + version: 7.3.5 vitest: specifier: ^4.1.6 version: 4.1.7 @@ -125,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 @@ -143,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 @@ -198,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 @@ -232,7 +235,7 @@ importers: dependencies: '@base-ui/react': specifier: ^1.5.0 - version: 1.5.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.5.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 @@ -259,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) @@ -267,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 @@ -281,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) @@ -311,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 @@ -2973,12 +2976,6 @@ packages: os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.60.2': - resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==} - cpu: [x64] - os: [linux] - libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.62.3': resolution: {integrity: sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==} cpu: [x64] @@ -3885,9 +3882,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==} @@ -5242,10 +5238,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==} @@ -5269,12 +5265,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 @@ -5287,8 +5283,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: @@ -5481,9 +5477,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} @@ -6252,27 +6245,27 @@ snapshots: '@badgateway/oauth2-client@3.3.1': {} - '@base-ui/react@1.5.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.5.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.2 - '@base-ui/utils': 0.2.9(@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.2.9(@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.2.9(@types/react@19.2.13)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@base-ui/utils@0.2.9(@types/react@19.2.13)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@babel/runtime': 7.29.2 '@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 @@ -6666,18 +6659,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 @@ -8037,7 +8030,7 @@ snapshots: dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 - picomatch: 4.0.4 + picomatch: 4.0.5 optionalDependencies: rollup: 4.62.3 @@ -8092,9 +8085,6 @@ snapshots: '@rollup/rollup-linux-s390x-gnu@4.62.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.60.2': - optional: true - '@rollup/rollup-linux-x64-gnu@4.62.3': optional: true @@ -8449,12 +8439,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) @@ -8494,7 +8484,7 @@ snapshots: dependencies: minimatch: 10.2.5 path-browserify: 1.0.1 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 '@turbo/darwin-64@2.9.14': optional: true @@ -8618,7 +8608,7 @@ snapshots: debug: 4.4.3(supports-color@8.1.1) minimatch: 10.2.5 semver: 7.8.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -8743,7 +8733,7 @@ snapshots: '@vue/shared': 3.5.33 estree-walker: 2.0.2 magic-string: 0.30.21 - postcss: 8.5.18 + postcss: 8.5.23 source-map-js: 1.2.1 '@vue/compiler-ssr@3.5.33': @@ -9072,7 +9062,7 @@ snapshots: convert-to-spaces@2.0.1: {} - cookie@1.1.1: {} + cookie-es@3.1.1: {} cross-spawn@7.0.6: dependencies: @@ -9148,11 +9138,11 @@ snapshots: dependencies: node-source-walk: 7.0.2 - detective-postcss@7.0.1(postcss@8.5.18): + detective-postcss@7.0.1(postcss@8.5.23): dependencies: is-url: 1.2.4 - postcss: 8.5.18 - postcss-values-parser: 6.0.2(postcss@8.5.18) + postcss: 8.5.23 + postcss-values-parser: 6.0.2(postcss@8.5.23) detective-sass@6.0.2: dependencies: @@ -9320,7 +9310,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -9372,10 +9362,6 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.4): - optionalDependencies: - picomatch: 4.0.4 - fdir@6.5.0(picomatch@4.0.5): optionalDependencies: picomatch: 4.0.5 @@ -9871,9 +9857,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: {} @@ -9999,18 +9985,18 @@ snapshots: neverthrow@8.2.0: optionalDependencies: - '@rollup/rollup-linux-x64-gnu': 4.60.2 + '@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 @@ -10303,11 +10289,11 @@ snapshots: optionalDependencies: '@inquirer/prompts': 8.5.2(@types/node@25.9.1) - postcss-values-parser@6.0.2(postcss@8.5.18): + postcss-values-parser@6.0.2(postcss@8.5.23): dependencies: color-name: 1.1.4 is-url-superb: 4.0.0 - postcss: 8.5.18 + postcss: 8.5.23 quote-unquote: 1.0.0 postcss@8.4.31: @@ -10337,7 +10323,7 @@ snapshots: detective-amd: 6.1.0 detective-cjs: 6.1.1 detective-es6: 5.0.2 - detective-postcss: 7.0.1(postcss@8.5.18) + detective-postcss: 7.0.1(postcss@8.5.23) detective-sass: 6.0.2 detective-scss: 5.0.2 detective-stylus: 5.0.1 @@ -10345,7 +10331,7 @@ snapshots: detective-vue2: 2.3.0(supports-color@8.1.1)(typescript@5.9.3) module-definition: 6.0.2 node-source-walk: 7.0.2 - postcss: 8.5.18 + postcss: 8.5.23 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -10414,14 +10400,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: {} @@ -10434,19 +10420,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: @@ -10709,8 +10694,6 @@ snapshots: transitivePeerDependencies: - supports-color - set-cookie-parser@2.7.2: {} - sharp@0.34.5: dependencies: '@img/colour': 1.1.0 @@ -10775,10 +10758,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: {} @@ -10860,10 +10843,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) @@ -10907,8 +10890,8 @@ snapshots: tinyglobby@0.2.16: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 tinyglobby@0.2.17: dependencies: @@ -11060,9 +11043,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: {} @@ -11135,11 +11118,11 @@ snapshots: magic-string: 0.30.21 obug: 2.1.1 pathe: 2.0.3 - picomatch: 4.0.4 + picomatch: 4.0.5 std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.2 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 tinyrainbow: 3.1.0 vite: 7.3.5(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.22.4)(yaml@2.9.0) why-is-node-running: 2.3.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 34fb6f0b..66a09603 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 2838b927f2269c646c20c40f1f4192a4a9fdf9ba 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 463ffdab7f98edbfe58b21494e0a266f35095608 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 afb0fa8aa0286f593c693633b1eb0c4319f1a577 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`.