From a69cd7e8dde42fe4410e195ee88b0f981f1ff356 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Jan 2026 14:18:49 +0100 Subject: [PATCH 1/6] upgrade React monorepo types to v19 --- package.json | 2 +- .../Navbar/MobileSidebar/Layout/index.tsx | 3 ++- .../src/hooks/useCodeWordWrap.ts | 4 ++-- .../src/utils/reactUtils.tsx | 2 +- .../src/utils/skipToContentUtils.tsx | 2 +- .../docusaurus/src/client/exports/Link.tsx | 2 +- yarn.lock | 24 +++++++------------ 7 files changed, 17 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 92d57c5705d0..3b8bf1346e27 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "@types/lodash": "^4.14.197", "@types/node": "^18.16.19", "@types/prompts": "^2.4.4", - "@types/react": "^18.2.15", + "@types/react": "^19.2.10", "@types/react-test-renderer": "^18.0.0", "@types/semver": "^7.5.0", "@types/shelljs": "^0.8.12", diff --git a/packages/docusaurus-theme-classic/src/theme/Navbar/MobileSidebar/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/Navbar/MobileSidebar/Layout/index.tsx index 7afe2f823c6f..29e705b220e1 100644 --- a/packages/docusaurus-theme-classic/src/theme/Navbar/MobileSidebar/Layout/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Navbar/MobileSidebar/Layout/index.tsx @@ -17,7 +17,8 @@ import type {Props} from '@theme/Navbar/MobileSidebar/Layout'; function inertProps(inert: boolean) { const isBeforeReact19 = parseInt(version!.split('.')[0]!, 10) < 19; if (isBeforeReact19) { - return {inert: inert ? '' : undefined}; + // TODO Docusaurus v4: remove temporary inert workaround + return {inert: inert ? '' : undefined} as unknown as {inert: boolean}; } return {inert}; } diff --git a/packages/docusaurus-theme-common/src/hooks/useCodeWordWrap.ts b/packages/docusaurus-theme-common/src/hooks/useCodeWordWrap.ts index 11cd15896590..df17460c46f6 100644 --- a/packages/docusaurus-theme-common/src/hooks/useCodeWordWrap.ts +++ b/packages/docusaurus-theme-common/src/hooks/useCodeWordWrap.ts @@ -11,7 +11,7 @@ import {useMutationObserver} from './useMutationObserver'; // Callback fires when the "hidden" attribute of a tabpanel changes // See https://github.com/facebook/docusaurus/pull/7485 function useTabBecameVisibleCallback( - codeBlockRef: RefObject, + codeBlockRef: RefObject, callback: () => void, ) { const [hiddenTabElement, setHiddenTabElement] = useState< @@ -53,7 +53,7 @@ function useTabBecameVisibleCallback( } export type WordWrap = { - readonly codeBlockRef: RefObject; + readonly codeBlockRef: RefObject; readonly isEnabled: boolean; readonly isCodeScrollable: boolean; readonly toggle: () => void; diff --git a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx index d0d212fd7d7d..80e349e3ba8f 100644 --- a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx @@ -44,7 +44,7 @@ export function useEvent unknown>( * Gets `value` from the last render. */ export function usePrevious(value: T): T | undefined { - const ref = useRef(); + const ref = useRef(undefined); useIsomorphicLayoutEffect(() => { ref.current = value; diff --git a/packages/docusaurus-theme-common/src/utils/skipToContentUtils.tsx b/packages/docusaurus-theme-common/src/utils/skipToContentUtils.tsx index 3c5e16fd1cf1..fcc4228a6830 100644 --- a/packages/docusaurus-theme-common/src/utils/skipToContentUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/skipToContentUtils.tsx @@ -52,7 +52,7 @@ function useSkipToContent(): { * so that keyboard navigators can instantly interact with the link and jump * to content. */ - containerRef: React.RefObject; + containerRef: React.RefObject; /** * Callback fired when the skip to content link has been clicked. * It will programmatically focus the main content. diff --git a/packages/docusaurus/src/client/exports/Link.tsx b/packages/docusaurus/src/client/exports/Link.tsx index 76c9f4f5ea69..e294ecff7b70 100644 --- a/packages/docusaurus/src/client/exports/Link.tsx +++ b/packages/docusaurus/src/client/exports/Link.tsx @@ -100,7 +100,7 @@ function Link( const IOSupported = ExecutionEnvironment.canUseIntersectionObserver; - const ioRef = useRef(); + const ioRef = useRef(undefined); const handleRef = (el: HTMLAnchorElement | null) => { innerRef.current = el; diff --git a/yarn.lock b/yarn.lock index 19cd653d21ab..7ef3380fafb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4562,11 +4562,6 @@ "@types/node" "*" kleur "^3.0.3" -"@types/prop-types@*": - version "15.7.13" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" - integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA== - "@types/qs@*": version "6.9.16" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.16.tgz#52bba125a07c0482d26747d5d4947a64daf8f794" @@ -4617,13 +4612,12 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^18.2.15": - version "18.3.12" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.12.tgz#99419f182ccd69151813b7ee24b792fe08774f60" - integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw== +"@types/react@*", "@types/react@^19.2.10": + version "19.2.10" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.10.tgz#f3ea799e6b4cebad6dfd231c238fc9de7652e2d2" + integrity sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw== dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" + csstype "^3.2.2" "@types/resolve@1.20.2": version "1.20.2" @@ -7267,10 +7261,10 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== +csstype@^3.2.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" + integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== cytoscape-cose-bilkent@^4.1.0: version "4.1.0" From e80cf89051fb6037864ae938da8d2cb1cedfe741 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Jan 2026 15:41:57 +0100 Subject: [PATCH 2/6] add shitty JSX namespace fix for our website --- website/types.d.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 website/types.d.ts diff --git a/website/types.d.ts b/website/types.d.ts new file mode 100644 index 000000000000..eefda515b8f4 --- /dev/null +++ b/website/types.d.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// This is a bad workaround to make our site typecheck under React 19 +// We run our site with "skipLibCheck=false", unfortunately some libraries +// are still using the global JSX namespace, that has been removed in v19 +// See https://react.dev/blog/2024/04/25/react-19-upgrade-guide#the-jsx-namespace-in-typescript +declare namespace JSX { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface Element {} + interface IntrinsicElements { + [elemName: string]: unknown; + } + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface ElementClass {} +} From 093639b5c72dac0b0bcfd7886f8835d16327cd7c Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Jan 2026 15:42:09 +0100 Subject: [PATCH 3/6] React 19 type fixes --- website/src/components/APITable/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/website/src/components/APITable/index.tsx b/website/src/components/APITable/index.tsx index 96d4e43278c2..29ad3e57881f 100644 --- a/website/src/components/APITable/index.tsx +++ b/website/src/components/APITable/index.tsx @@ -26,7 +26,9 @@ interface Props { function getRowName(node: ReactElement): string { let curNode: ReactNode = node; while (isValidElement(curNode)) { - [curNode] = React.Children.toArray(curNode.props.children); + [curNode] = React.Children.toArray( + (curNode.props as {children: ReactNode}).children, + ); } if (typeof curNode !== 'string') { throw new Error( @@ -99,6 +101,7 @@ export default function APITable({children, name}: Props): ReactNode { highlightedRow.current?.focus(); }, [highlightedRow]); const rows = React.Children.map( + // @ts-expect-error: TODO fix typing tbody.props.children, (row: ReactElement>) => ( From 426d98f3ef72ba5fe80b2f543fc1762db5e4ebd1 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Jan 2026 15:55:21 +0100 Subject: [PATCH 4/6] TS fix --- packages/docusaurus-theme-classic/src/theme-classic.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 961d68fcc044..03a00f833a76 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -1745,11 +1745,11 @@ declare module '@theme/Icon/LightMode' { } declare module '@theme/Icon/SystemColorMode' { - import type {ComponentProps} from 'react'; + import type {ComponentProps, ReactNode} from 'react'; export interface Props extends ComponentProps<'svg'> {} - export default function IconSystemColorMode(props: Props): JSX.Element; + export default function IconSystemColorMode(props: Props): ReactNode; } declare module '@theme/Icon/Menu' { From 54aae7acc321ef12ae5bcff7abe553eb9f8f0264 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Jan 2026 16:47:59 +0100 Subject: [PATCH 5/6] attempt to make it work --- .../src/theme-classic.d.ts | 8 +++++--- website/types.d.ts | 15 ++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 03a00f833a76..675b066ae2ea 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -1119,9 +1119,11 @@ declare module '@theme/MDXComponents' { import type Mermaid from '@theme/Mermaid'; import type Head from '@docusaurus/Head'; - import type {MDXProvider} from '@mdx-js/react'; - - type MDXComponentsBase = ComponentProps['components']; + // Doesn't work anymore under React 19 because MDX uses JSX and not React.JSX + // import type {MDXProvider} from '@mdx-js/react'; + // type MDXComponentsBase = ComponentProps['components']; + // See also https://github.com/mdx-js/mdx/issues/2487 + type MDXComponentsBase = any; export type MDXComponentsObject = MDXComponentsBase & { readonly Head: typeof Head; diff --git a/website/types.d.ts b/website/types.d.ts index eefda515b8f4..b04ea05654ab 100644 --- a/website/types.d.ts +++ b/website/types.d.ts @@ -9,12 +9,13 @@ // We run our site with "skipLibCheck=false", unfortunately some libraries // are still using the global JSX namespace, that has been removed in v19 // See https://react.dev/blog/2024/04/25/react-19-upgrade-guide#the-jsx-namespace-in-typescript -declare namespace JSX { - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface Element {} - interface IntrinsicElements { - [elemName: string]: unknown; +// See https://github.com/mdx-js/mdx/issues/2487 +import type {JSX as Jsx} from 'react/jsx-runtime'; + +declare global { + namespace JSX { + type ElementClass = Jsx.ElementClass; + type Element = Jsx.Element; + type IntrinsicElements = Jsx.IntrinsicElements; } - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface ElementClass {} } From 34ada2357bfa018127b29f2c1fa6d5a9942f3df0 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Jan 2026 17:16:42 +0100 Subject: [PATCH 6/6] better mdx components fix --- packages/docusaurus-theme-classic/src/theme-classic.d.ts | 8 +++----- website/types.d.ts | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 675b066ae2ea..03a00f833a76 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -1119,11 +1119,9 @@ declare module '@theme/MDXComponents' { import type Mermaid from '@theme/Mermaid'; import type Head from '@docusaurus/Head'; - // Doesn't work anymore under React 19 because MDX uses JSX and not React.JSX - // import type {MDXProvider} from '@mdx-js/react'; - // type MDXComponentsBase = ComponentProps['components']; - // See also https://github.com/mdx-js/mdx/issues/2487 - type MDXComponentsBase = any; + import type {MDXProvider} from '@mdx-js/react'; + + type MDXComponentsBase = ComponentProps['components']; export type MDXComponentsObject = MDXComponentsBase & { readonly Head: typeof Head; diff --git a/website/types.d.ts b/website/types.d.ts index b04ea05654ab..7f7393587fc7 100644 --- a/website/types.d.ts +++ b/website/types.d.ts @@ -16,6 +16,7 @@ declare global { namespace JSX { type ElementClass = Jsx.ElementClass; type Element = Jsx.Element; + type ElementType = Jsx.ElementType; type IntrinsicElements = Jsx.IntrinsicElements; } }