Upgrade frontend toolchain to latest majors

Bump React 19.2, Relay 21, React Router 8, Vite 8 with
@vitejs/plugin-react 6, ESLint 10, GraphQL 17, TypeScript 6,
@types/node 24, and Tailwind 4.3 across the workspaces.

vite-plugin-react 6 (Vite 8) no longer runs Babel, so the Relay
tagged-template transform now runs through @rolldown/plugin-babel
in the console and trust Vite configs.

Relay 21 ships first-party types and enables the ambiguous-alias
check by default; disable that flag to preserve existing queries
and add explicit usePreloadedQuery type arguments where the new
types no longer infer the operation. TypeScript 6 deprecations and
stricter inference are addressed in tsconfigs and call sites.

Keep n8n-node on ESLint 9 and eslint-plugin-react on 7.37.5, the
newest releases compatible with their toolchains.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-18 19:10:00 +02:00
parent f1fc2dc0e0
commit f98b73f073
130 changed files with 2228 additions and 1763 deletions

View File

@@ -42,7 +42,7 @@
"remark-gfm": "^4.0.1",
"tailwind-merge": "^3.4.0",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^4.1.7",
"tailwindcss": "^4.3.1",
"tw-animate-css": "^1.3.0",
"zustand": "^5.0.4"
},
@@ -54,27 +54,27 @@
"@storybook/react": "^10.2.8",
"@storybook/react-vite": "^10.2.8",
"@tailwindcss/typography": "^0.5.16",
"@tailwindcss/vite": "^4.1.17",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^5.1.4",
"@tailwindcss/vite": "^4.3.1",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.2",
"@vitest/browser": "4.1.8",
"@vitest/coverage-v8": "4.1.8",
"eslint": "^9.39.2",
"eslint": "^10.5.0",
"playwright": "^1.55.1",
"react": "^19.1.0",
"react": "^19.2.7",
"react-docgen": "^7.1.1",
"react-dom": "^19.1.0",
"react-router": "^7.17.0",
"react-dom": "^19.2.7",
"react-router": "^8.0.0",
"storybook": "^10.2.10",
"typescript": "~5.8.3",
"vite": "^7.3.2",
"typescript": "~6.0.3",
"vite": "^8.0.16",
"vitest": "^4.1.8"
},
"peerDependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router": "^7.17.0"
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-router": "^8.0.0"
},
"volta": {
"node": "24.4.0"

View File

@@ -81,7 +81,7 @@ export function Th({
);
}
const TrContext = createContext({} as { to?: string });
const TrContext = createContext<{ to?: string }>({});
export function Tr({
to,

View File

@@ -14,6 +14,7 @@
import { objectKeys } from "@probo/helpers";
import type { Meta, StoryObj } from "@storybook/react";
import type { ComponentType } from "react";
import * as icons from "./Atoms/Icons";
@@ -183,7 +184,7 @@ export const Icons: Story = {
<div className="flex flex-wrap gap-4">
{objectKeys(icons).map((k) => {
/* eslint import-x/namespace: ['error', { allowComputed: true }] */
const IconComponent = icons[k];
const IconComponent = icons[k] as ComponentType;
return (
<button
title={k}

View File

@@ -36,8 +36,8 @@ type Props = PropsWithChildren<{
sidebar?: ReactNode;
}>;
const LayoutContext = createContext({
setDrawer: (() => {}) as (v: boolean) => void,
const LayoutContext = createContext<{ setDrawer: (v: boolean) => void }>({
setDrawer: () => {},
});
export function Layout({

View File

@@ -38,12 +38,14 @@ type State = {
onConfirm: () => void | Promise<unknown>;
};
const initialConfirmState: State = {
message: null,
onConfirm: () => Promise.resolve(),
};
const useConfirmStore = create(
combine(
{
message: null,
onConfirm: () => Promise.resolve(),
} as State,
initialConfirmState,
set => ({
open: (props: State) => {
set(props);

View File

@@ -25,22 +25,20 @@ export default {
type Story = StoryObj<typeof MeasureImplementation>;
type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED" | "UNKNOWN" | "NOT_IMPLEMENTED";
export const Default: Story = {
args: {
measures: [
...times(15, () => ({
state: "IMPLEMENTED" as MeasureState,
state: "IMPLEMENTED" as const,
})),
...times(10, () => ({
state: "IN_PROGRESS" as MeasureState,
state: "IN_PROGRESS" as const,
})),
...times(5, () => ({
state: "NOT_APPLICABLE" as MeasureState,
state: "NOT_APPLICABLE" as const,
})),
...times(5, () => ({
state: "NOT_STARTED" as MeasureState,
state: "NOT_STARTED" as const,
})),
],
},

View File

@@ -131,7 +131,7 @@ export const SlashCommandExtension = Extension.create<object, SlashCommandStorag
"data-empty": isEmpty
? "true"
: "false",
} as Record<string, string>),
}),
]);
} catch {
deactivateSlashCommand(storage);

View File

@@ -14,5 +14,5 @@ export function cellDomElement(
while (el && !(el instanceof HTMLTableCellElement)) {
el = (el as HTMLElement).parentElement;
}
return el as HTMLElement | null;
return el;
}