diff --git a/.gitignore b/.gitignore index 07168936c32..53b4196ca9a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ lerna-debug.log .vscode # For vim *.swp -.yarn +.yarn/* +!.yarn/patches diff --git a/.yarn/patches/@patternfly-documentation-framework-npm-6.49.2-02e7a8d840.patch b/.yarn/patches/@patternfly-documentation-framework-npm-6.49.2-02e7a8d840.patch new file mode 100644 index 00000000000..8702eb371e2 --- /dev/null +++ b/.yarn/patches/@patternfly-documentation-framework-npm-6.49.2-02e7a8d840.patch @@ -0,0 +1,65 @@ +diff --git a/scripts/webpack/prerender.js b/scripts/webpack/prerender.js +index 37306139a11cabc0c89e2eee637ea8af88693cd9..03f0c1d909a9bc516c5006cb4f8805c250e060bf 100644 +--- a/scripts/webpack/prerender.js ++++ b/scripts/webpack/prerender.js +@@ -1,10 +1,44 @@ + const React = require('react'); + const ReactDOMServer = require('react-dom/server'); + const { ServerLocation } = require('@reach/router'); +-const ssrPrepass = require('react-ssr-prepass'); + // react, react-dom, and @reach/router are all EXCLUDED from the ssr-bundle.js + // The versions imported above are used instead, which allows us to use +-// const ssrPrepass = require('react-ssr-prepass'); ++ ++// Let pending dynamic imports (AsyncComponent.preload) settle before re-rendering ++const flushAsync = () => new Promise((resolve) => setImmediate(() => setImmediate(resolve))); ++ ++// The loading state rendered by asyncComponentFactory while a page chunk loads ++const LOADING_MARKER = 'style="height:100vh">Loading...'; ++ ++// react-ssr-prepass walked the element tree to await AsyncComponent.preload(), but it ++// relies on React internals that no longer exist in React 19. AsyncComponent already ++// kicks off preload() from its loading-state render, so rendering to a fixpoint with ++// plain renderToString preloads the same chunks using only public React APIs. ++let prerenderCount = 0; ++ ++async function renderToStringWithPreload(element) { ++ const maxPasses = 4; ++ const start = Date.now(); ++ let passes = 1; ++ let html = ReactDOMServer.renderToString(element); ++ if (++prerenderCount % 25 === 0) { ++ console.log(` [prerender #${prerenderCount}] heap=${Math.round(process.memoryUsage().heapUsed / 1048576)}MB`); ++ } ++ ++ for (; passes < maxPasses && html.includes(LOADING_MARKER); passes++) { ++ // The first render has kicked off preload(); give the dynamic imports a chance ++ // to settle, then render again until no loading placeholder is left. ++ await (passes === 1 ? flushAsync() : new Promise((resolve) => setTimeout(resolve, 50))); ++ html = ReactDOMServer.renderToString(element); ++ } ++ ++ const elapsed = Date.now() - start; ++ if (elapsed > 5000 || html.includes(LOADING_MARKER)) { ++ console.log(` rendered in ${passes} passes, ${elapsed}ms${html.includes(LOADING_MARKER) ? ' (loading placeholder left!)' : ''}`); ++ } ++ ++ return html; ++} + + // This function is effectively synchronous because it mutates global.setTimeout + // Only allow one copy at a time to run +@@ -44,12 +78,7 @@ async function prerender(url) { + const WrappedApp = React.createElement(ServerLocation, { url }, + React.createElement(App) + ); +- await ssrPrepass(WrappedApp, element => { +- if (element.type.name === 'AsyncComponent') { +- return element.type.preload(); +- } +- }); +- const string = ReactDOMServer.renderToString(WrappedApp); ++ const string = await renderToStringWithPreload(WrappedApp); + + return string; + } diff --git a/package.json b/package.json index 41662fc6405..92f5157babe 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "@testing-library/user-event": "^14.6.1", "@types/jest": "29.5.14", "@types/node": "^22.16.5", - "@types/react": "^18.3.28", - "@types/react-dom": "^18.3.7", + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.5", "babel-jest": "^29.7.0", "concurrently": "^9.2.1", "eslint": "^9.32.0", @@ -68,8 +68,8 @@ "plop": "^4.0.5", "prettier": "^3.8.1", "publint": "^0.3.18", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "react": "^19.2.8", + "react-dom": "^19.2.8", "rimraf": "^6.1.3", "rollup": "^4.57.1", "rollup-plugin-scss": "^4.0.1", @@ -124,6 +124,7 @@ ] }, "resolutions": { - "dompurify": "3.4.13" + "dompurify": "3.4.13", + "@patternfly/documentation-framework": "patch:@patternfly/documentation-framework@npm%3A6.49.2#~/.yarn/patches/@patternfly-documentation-framework-npm-6.49.2-02e7a8d840.patch" } } diff --git a/packages/react-charts/package.json b/packages/react-charts/package.json index 06a373825e5..d17c1634e89 100644 --- a/packages/react-charts/package.json +++ b/packages/react-charts/package.json @@ -52,8 +52,8 @@ }, "peerDependencies": { "echarts": "^5.6.0 || ^6.0.0", - "react": "^17 || ^18 || ^19", - "react-dom": "^17 || ^18 || ^19", + "react": "^18 || ^19", + "react-dom": "^18 || ^19", "victory-area": "^37.3.6", "victory-axis": "^37.3.6", "victory-bar": "^37.3.6", diff --git a/packages/react-code-editor/package.json b/packages/react-code-editor/package.json index 65a678c0dbf..7a4f5b7953c 100644 --- a/packages/react-code-editor/package.json +++ b/packages/react-code-editor/package.json @@ -38,8 +38,8 @@ "tslib": "^2.8.1" }, "peerDependencies": { - "react": "^17 || ^18 || ^19", - "react-dom": "^17 || ^18 || ^19" + "react": "^18 || ^19", + "react-dom": "^18 || ^19" }, "devDependencies": { "monaco-editor": "^0.56.0" diff --git a/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditor.test.tsx.snap b/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditor.test.tsx.snap index 88173df32e3..c6275d8a4b5 100644 --- a/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditor.test.tsx.snap +++ b/packages/react-code-editor/src/components/CodeEditor/__test__/__snapshots__/CodeEditor.test.tsx.snap @@ -25,7 +25,7 @@ exports[`Matches snapshot with control buttons enabled 1`] = `