From 08625367bf462f06f6272368c1821456b456fbea Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jul 2026 11:19:29 +0200 Subject: [PATCH 1/6] test: cover packed React compatibility --- .github/workflows/test.yml | 4 + fixtures/react-compat/entry-legacy.jsx | 19 + fixtures/react-compat/entry-react19.jsx | 21 + fixtures/react-compat/rsbuild.config.mjs | 21 + fixtures/react-compat/scenario.jsx | 38 ++ package.json | 4 + pnpm-lock.yaml | 785 ++++++++++++++--------- scripts/compat/packed.mjs | 115 ++++ src/__tests__/useOnInView.test.tsx | 36 ++ 9 files changed, 735 insertions(+), 308 deletions(-) create mode 100644 fixtures/react-compat/entry-legacy.jsx create mode 100644 fixtures/react-compat/entry-react19.jsx create mode 100644 fixtures/react-compat/rsbuild.config.mjs create mode 100644 fixtures/react-compat/scenario.jsx create mode 100644 scripts/compat/packed.mjs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 730756bf..2b13db07 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,6 +60,10 @@ jobs: run: pnpm add -D react@${{ matrix.react }} react-dom@${{ matrix.react }} - name: Validate types run: pnpm tsc + - name: Build package + run: pnpm build + - name: Test packed package + run: pnpm run compat:packed -- $(node -p "require('react/package.json').version.split('.')[0]") - name: Run test run: | pnpm exec playwright install diff --git a/fixtures/react-compat/entry-legacy.jsx b/fixtures/react-compat/entry-legacy.jsx new file mode 100644 index 00000000..1f85a111 --- /dev/null +++ b/fixtures/react-compat/entry-legacy.jsx @@ -0,0 +1,19 @@ +import ReactDOM from "react-dom"; +import { CompatibilityFixture, result, settle } from "./scenario"; + +const container = document.getElementById("root"); + +async function run() { + ReactDOM.render(, container); + await settle(); + ReactDOM.render(, container); + await settle(); + ReactDOM.render(, container); + await settle(); + ReactDOM.unmountComponentAtNode(container); + await settle(); + + window.__COMPAT_RESULT__ = result(); +} + +run(); diff --git a/fixtures/react-compat/entry-react19.jsx b/fixtures/react-compat/entry-react19.jsx new file mode 100644 index 00000000..f93f6a9f --- /dev/null +++ b/fixtures/react-compat/entry-react19.jsx @@ -0,0 +1,21 @@ +import { flushSync } from "react-dom"; +import { createRoot } from "react-dom/client"; +import { CompatibilityFixture, result, settle } from "./scenario"; + +const container = document.getElementById("root"); +const root = createRoot(container); + +async function run() { + flushSync(() => root.render()); + await settle(); + flushSync(() => root.render()); + await settle(); + flushSync(() => root.render()); + await settle(); + flushSync(() => root.unmount()); + await settle(); + + window.__COMPAT_RESULT__ = result(); +} + +run(); diff --git a/fixtures/react-compat/rsbuild.config.mjs b/fixtures/react-compat/rsbuild.config.mjs new file mode 100644 index 00000000..c5138a05 --- /dev/null +++ b/fixtures/react-compat/rsbuild.config.mjs @@ -0,0 +1,21 @@ +import { defineConfig } from "@rsbuild/core"; +import { pluginReact } from "@rsbuild/plugin-react"; + +export default defineConfig({ + plugins: [pluginReact()], + source: { + entry: { + index: + process.env.REACT_MAJOR === "19" + ? "./entry-react19.jsx" + : "./entry-legacy.jsx", + }, + }, + output: { + distPath: { root: "dist" }, + filename: { js: "[name].js" }, + }, + performance: { + chunkSplit: { strategy: "all-in-one" }, + }, +}); diff --git a/fixtures/react-compat/scenario.jsx b/fixtures/react-compat/scenario.jsx new file mode 100644 index 00000000..6c3fe0ac --- /dev/null +++ b/fixtures/react-compat/scenario.jsx @@ -0,0 +1,38 @@ +import { useInView, useOnInView } from "react-intersection-observer"; + +const diagnostics = []; +let observeCount = 0; +let unobserveCount = 0; + +console.error = (...args) => diagnostics.push(args.join(" ")); +console.warn = (...args) => diagnostics.push(args.join(" ")); + +window.IntersectionObserver = class IntersectionObserver { + observe() { + observeCount += 1; + } + + unobserve() { + unobserveCount += 1; + } + + disconnect() {} +}; + +export function CompatibilityFixture({ attached }) { + const callbackRef = useOnInView(() => {}); + const { ref: stateRef } = useInView(); + + return attached ? ( + <> +
+
+ + ) : null; +} + +export const settle = () => new Promise((resolve) => setTimeout(resolve, 0)); + +export function result() { + return { diagnostics, observeCount, unobserveCount }; +} diff --git a/package.json b/package.json index e284a5b4..c7bda298 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "scripts": { "prebuild": "rm -rf dist lib", "build": "tsup && mkdir dist/esm && cp dist/index.mjs dist/esm/index.js", + "compat:packed": "node scripts/compat/packed.mjs", "postbuild": "attw --pack && publint && size-limit", "dev": "run-p dev:*", "dev:package": "tsup src/index.tsx --watch", @@ -122,6 +123,8 @@ "devDependencies": { "@arethetypeswrong/cli": "^0.18.2", "@biomejs/biome": "^2.3.10", + "@rsbuild/core": "1.5.13", + "@rsbuild/plugin-react": "1.4.2", "@size-limit/preset-small-lib": "^12.0.0", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.1", @@ -132,6 +135,7 @@ "@vitest/browser-playwright": "^4.0.16", "@vitest/coverage-istanbul": "^4.0.16", "bumpp": "^10.3.2", + "jsdom": "27.0.1", "lint-staged": "^16.2.7", "microbundle": "^0.15.1", "npm-run-all": "^4.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f277a993..bb903239 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,12 @@ importers: '@biomejs/biome': specifier: ^2.3.10 version: 2.3.10 + '@rsbuild/core': + specifier: 1.5.13 + version: 1.5.13(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@rsbuild/plugin-react': + specifier: 1.4.2 + version: 1.4.2(@rsbuild/core@1.5.13(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)) '@size-limit/preset-small-lib': specifier: ^12.0.0 version: 12.0.0(size-limit@12.0.0(jiti@2.6.1)) @@ -44,6 +50,9 @@ importers: bumpp: specifier: ^10.3.2 version: 10.3.2(magicast@0.5.1) + jsdom: + specifier: 27.0.1 + version: 27.0.1 lint-staged: specifier: ^16.2.7 version: 16.2.7 @@ -79,7 +88,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.16 - version: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + version: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) storybook: dependencies: @@ -170,8 +179,14 @@ packages: resolution: {integrity: sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg==} engines: {node: '>=20'} - '@asamuzakjp/css-color@3.2.0': - resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@asamuzakjp/css-color@4.1.2': + resolution: {integrity: sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==} + + '@asamuzakjp/dom-selector@6.8.1': + resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} @@ -976,33 +991,50 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@csstools/color-helpers@5.1.0': - resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} - engines: {node: '>=18'} + '@csstools/color-helpers@6.1.0': + resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + engines: {node: '>=20.19.0'} - '@csstools/css-calc@2.1.4': - resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} - engines: {node: '>=18'} + '@csstools/css-calc@3.2.1': + resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-color-parser@3.1.0': - resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} - engines: {node: '>=18'} + '@csstools/css-color-parser@4.1.9': + resolution: {integrity: sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-parser-algorithms@3.0.5': - resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} - engines: {node: '>=18'} + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-tokenizer@3.0.4': - resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} - engines: {node: '>=18'} + '@csstools/css-syntax-patches-for-csstree@1.1.6': + resolution: {integrity: sha512-TcJCWFbXLPpJYq6z7bfOyjWYJDiDg2/I4gyUC9pqPNqHFRIey0EB0q0L5cSnQDfWJg8Jd6VadakxdIez/3zkqQ==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} '@esbuild/aix-ppc64@0.27.2': resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} @@ -1269,10 +1301,34 @@ packages: '@types/react': '>=16' react: '>=16' + '@module-federation/error-codes@0.18.0': + resolution: {integrity: sha512-Woonm8ehyVIUPXChmbu80Zj6uJkC0dD9SJUZ/wOPtO8iiz/m+dkrOugAuKgoiR6qH4F+yorWila954tBz4uKsQ==} + + '@module-federation/runtime-core@0.18.0': + resolution: {integrity: sha512-ZyYhrDyVAhUzriOsVfgL6vwd+5ebYm595Y13KeMf6TKDRoUHBMTLGQ8WM4TDj8JNsy7LigncK8C03fn97of0QQ==} + + '@module-federation/runtime-tools@0.18.0': + resolution: {integrity: sha512-fSga9o4t1UfXNV/Kh6qFvRyZpPp3EHSPRISNeyT8ZoTpzDNiYzhtw0BPUSSD8m6C6XQh2s/11rI4g80UY+d+hA==} + + '@module-federation/runtime@0.18.0': + resolution: {integrity: sha512-+C4YtoSztM7nHwNyZl6dQKGUVJdsPrUdaf3HIKReg/GQbrt9uvOlUWo2NXMZ8vDAnf/QRrpSYAwXHmWDn9Obaw==} + + '@module-federation/sdk@0.18.0': + resolution: {integrity: sha512-Lo/Feq73tO2unjmpRfyyoUkTVoejhItXOk/h5C+4cistnHbTV8XHrW/13fD5e1Iu60heVdAhhelJd6F898Ve9A==} + + '@module-federation/webpack-bundler-runtime@0.18.0': + resolution: {integrity: sha512-TEvErbF+YQ+6IFimhUYKK3a5wapD90d90sLsNpcu2kB3QGT7t4nIluE25duXuZDVUKLz86tEPrza/oaaCWTpvQ==} + '@mswjs/interceptors@0.37.6': resolution: {integrity: sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w==} engines: {node: '>=18'} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@open-draft/deferred-promise@2.2.0': resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} @@ -1455,6 +1511,90 @@ packages: cpu: [x64] os: [win32] + '@rsbuild/core@1.5.13': + resolution: {integrity: sha512-P+TCvZCVpBYZ3GDdnzR/tZKicE41khJIqIRlJYnEc9dwUfX1/eqRf8lA8yrsbB5iZbSfj1iOoH1N25cCQ3hhuA==} + engines: {node: '>=18.12.0'} + hasBin: true + + '@rsbuild/plugin-react@1.4.2': + resolution: {integrity: sha512-2rJb5mOuqVof2aDq4SbB1E65+0n1vjhAADipC88jvZRNuTOulg79fh7R4tsCiBMI4VWq46gSpwekiK8G5bq6jg==} + peerDependencies: + '@rsbuild/core': 1.x + + '@rspack/binding-darwin-arm64@1.5.8': + resolution: {integrity: sha512-spJfpOSN3f7V90ic45/ET2NKB2ujAViCNmqb0iGurMNQtFRq+7Kd+jvVKKGXKBHBbsQrFhidSWbbqy2PBPGK8g==} + cpu: [arm64] + os: [darwin] + + '@rspack/binding-darwin-x64@1.5.8': + resolution: {integrity: sha512-YFOzeL1IBknBcri8vjUp43dfUBylCeQnD+9O9p0wZmLAw7DtpN5JEOe2AkGo8kdTqJjYKI+cczJPKIw6lu1LWw==} + cpu: [x64] + os: [darwin] + + '@rspack/binding-linux-arm64-gnu@1.5.8': + resolution: {integrity: sha512-UAWCsOnpkvy8eAVRo0uipbHXDhnoDq5zmqWTMhpga0/a3yzCp2e+fnjZb/qnFNYb5MeL0O1mwMOYgn1M3oHILQ==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-arm64-musl@1.5.8': + resolution: {integrity: sha512-GnSvGT4GjokPSD45cTtE+g7LgghuxSP1MRmvd+Vp/I8pnxTVSTsebRod4TAqyiv+l11nuS8yqNveK9qiOkBLWw==} + cpu: [arm64] + os: [linux] + + '@rspack/binding-linux-x64-gnu@1.5.8': + resolution: {integrity: sha512-XLxh5n/pzUfxsugz/8rVBv+Tx2nqEM+9rharK69kfooDsQNKyz7PANllBQ/v4svJ+W0BRHnDL4qXSGdteZeEjA==} + cpu: [x64] + os: [linux] + + '@rspack/binding-linux-x64-musl@1.5.8': + resolution: {integrity: sha512-gE0+MZmwF+01p9/svpEESkzkLpBkVUG2o03YMpwXYC/maeRRhWvF8BJ7R3i/Ls/jFGSE87dKX5NbRLVzqksq/w==} + cpu: [x64] + os: [linux] + + '@rspack/binding-wasm32-wasi@1.5.8': + resolution: {integrity: sha512-cfg3niNHeJuxuml1Vy9VvaJrI/5TakzoaZvKX2g5S24wfzR50Eyy4JAsZ+L2voWQQp1yMJbmPYPmnTCTxdJQBQ==} + cpu: [wasm32] + + '@rspack/binding-win32-arm64-msvc@1.5.8': + resolution: {integrity: sha512-7i3ZTHFXKfU/9Jm9XhpMkrdkxO7lfeYMNVEGkuU5dyBfRMQj69dRgPL7zJwc2plXiqu9LUOl+TwDNTjap7Q36g==} + cpu: [arm64] + os: [win32] + + '@rspack/binding-win32-ia32-msvc@1.5.8': + resolution: {integrity: sha512-7ZPPWO11J+soea1+mnfaPpQt7GIodBM7A86dx6PbXgVEoZmetcWPrCF2NBfXxQWOKJ9L3RYltC4z+ZyXRgMOrw==} + cpu: [ia32] + os: [win32] + + '@rspack/binding-win32-x64-msvc@1.5.8': + resolution: {integrity: sha512-N/zXQgzIxME3YUzXT8qnyzxjqcnXudWOeDh8CAG9zqTCnCiy16SFfQ/cQgEoLlD9geQntV6jx2GbDDI5kpDGMQ==} + cpu: [x64] + os: [win32] + + '@rspack/binding@1.5.8': + resolution: {integrity: sha512-/91CzhRl9r5BIQCgGsS7jA6MDbw1I2BQpbfcUUdkdKl2P79K3Zo/Mw/TvKzS86catwLaUQEgkGRmYawOfPg7ow==} + + '@rspack/core@1.5.8': + resolution: {integrity: sha512-sUd2LfiDhqYVfvknuoz0+/c+wSpn693xotnG5g1CSWKZArbtwiYzBIVnNlcHGmuoBRsnj/TkSq8dTQ7gwfBroQ==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@rspack/lite-tapable@1.0.1': + resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} + engines: {node: '>=16.0.0'} + + '@rspack/plugin-react-refresh@1.6.2': + resolution: {integrity: sha512-k+/VrfTNgo+KirjI6V+8CWRj6y+DH9jOUWv8JorYY4vKf/9xfnZ8xHzuB4iqCwTtoZl9YnxOaOuoyjJipc2tiQ==} + peerDependencies: + react-refresh: '>=0.10.0 <1.0.0' + webpack-hot-middleware: 2.x + peerDependenciesMeta: + webpack-hot-middleware: + optional: true + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -1564,6 +1704,9 @@ packages: '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + '@tailwindcss/node@4.1.18': resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} @@ -1685,6 +1828,9 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -1903,9 +2049,6 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - asyncro@3.0.0: resolution: {integrity: sha512-nEnWYfrBmA3taTiuiOoZYmgJ/CNrSoQLeLs29SeLcPu60yaw/mHDBHV0iOZ051fTvsTHxpCY+gXibqT9wbQYfg==} @@ -1958,6 +2101,9 @@ packages: resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} hasBin: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2023,10 +2169,6 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -2141,10 +2283,6 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -2196,6 +2334,9 @@ packages: core-js-compat@3.37.0: resolution: {integrity: sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==} + core-js@3.45.1: + resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==} + cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -2221,6 +2362,10 @@ packages: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2255,16 +2400,16 @@ packages: resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} engines: {node: '>=8.0.0'} - cssstyle@4.6.0: - resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} - engines: {node: '>=18'} + cssstyle@5.3.7: + resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} + engines: {node: '>=20'} csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - data-urls@5.0.0: - resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} - engines: {node: '>=18'} + data-urls@6.0.1: + resolution: {integrity: sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==} + engines: {node: '>=20'} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -2317,10 +2462,6 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2359,10 +2500,6 @@ packages: resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - duplexer@0.1.1: resolution: {integrity: sha512-sxNZ+ljy+RA1maXoUReeqBBpBC6RLKmg5ewzV+x+mSETmWNoKdZN6vcQjpFROemza23hGFskJtFNoUWUaQ+R4Q==} @@ -2406,9 +2543,9 @@ packages: entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} @@ -2417,6 +2554,9 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + es-abstract@1.21.1: resolution: {integrity: sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==} engines: {node: '>= 0.4'} @@ -2425,10 +2565,6 @@ packages: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} @@ -2436,18 +2572,10 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - es-set-tostringtag@2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} engines: {node: '>= 0.4'} - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} @@ -2548,10 +2676,6 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} - fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -2615,14 +2739,6 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -2634,11 +2750,12 @@ packages: glob@11.1.0: resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -2657,10 +2774,6 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2931,11 +3044,11 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - jsdom@25.0.1: - resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} - engines: {node: '>=18'} + jsdom@27.0.1: + resolution: {integrity: sha512-SNSQteBL1IlV2zqhwwolaG9CwhIhTvVHWg3kTss/cLE7H/X4644mtPQqYvCfsSrGQWt9hSZcgOXX8bOZaMN+kA==} + engines: {node: '>=20'} peerDependencies: - canvas: ^2.11.2 + canvas: ^3.0.0 peerDependenciesMeta: canvas: optional: true @@ -3103,9 +3216,6 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.2: resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} @@ -3114,6 +3224,10 @@ packages: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3149,10 +3263,6 @@ packages: engines: {node: '>= 16'} hasBin: true - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - maxmin@2.1.0: resolution: {integrity: sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==} engines: {node: '>=0.12'} @@ -3160,6 +3270,9 @@ packages: mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + memorystream@0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} @@ -3175,14 +3288,6 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -3302,9 +3407,6 @@ packages: resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} engines: {node: '>=0.10.0'} - nwsapi@2.2.23: - resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} - nypm@0.6.2: resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==} engines: {node: ^14.16.0 || >=16.10.0} @@ -3403,8 +3505,8 @@ packages: parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -3859,6 +3961,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -3931,9 +4037,6 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rrweb-cssom@0.7.1: - resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} - rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -4089,6 +4192,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -4266,11 +4372,11 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} - tldts-core@6.1.86: - resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + tldts-core@7.4.8: + resolution: {integrity: sha512-c1P7u0EhACHj7lPy4MJm8iTFEU8+nB0LCtddH0fhP7noaVoXAqafMtOOeX+ulpuPBqnrRgRhw494RICT3mbhnw==} - tldts@6.1.86: - resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + tldts@7.4.8: + resolution: {integrity: sha512-htwgN/8KRB3z3vnC0BOETVh2m499g5GmyTK9Wq5JBLX3FNz6tSBveAd+fQhzy9hkjif8vy2jwDMR1sGhLtZl2A==} hasBin: true to-regex-range@5.0.1: @@ -4285,13 +4391,13 @@ packages: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} - tough-cookie@5.1.2: - resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} - tr46@5.1.1: - resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} - engines: {node: '>=18'} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} @@ -4504,9 +4610,9 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} @@ -4520,9 +4626,13 @@ packages: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - whatwg-url@14.2.0: - resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} - engines: {node: '>=18'} + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -4657,14 +4767,23 @@ snapshots: typescript: 5.6.1-rc validate-npm-package-name: 5.0.1 - '@asamuzakjp/css-color@3.2.0': + '@asamuzakjp/css-color@4.1.2': dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 10.4.3 - optional: true + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.5.2 + + '@asamuzakjp/dom-selector@6.8.1': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.2 + + '@asamuzakjp/nwsapi@2.3.9': {} '@babel/code-frame@7.26.2': dependencies: @@ -5653,29 +5772,44 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@csstools/color-helpers@5.1.0': - optional: true + '@csstools/color-helpers@6.1.0': {} - '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - optional: true + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-syntax-patches-for-csstree@1.1.6(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + + '@emnapi/core@1.11.2': dependencies: - '@csstools/color-helpers': 5.1.0 - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 optional: true - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + '@emnapi/runtime@1.11.2': dependencies: - '@csstools/css-tokenizer': 3.0.4 + tslib: 2.8.1 optional: true - '@csstools/css-tokenizer@3.0.4': + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 optional: true '@esbuild/aix-ppc64@0.27.2': @@ -5875,6 +6009,31 @@ snapshots: '@types/react': 19.2.7 react: 19.2.3 + '@module-federation/error-codes@0.18.0': {} + + '@module-federation/runtime-core@0.18.0': + dependencies: + '@module-federation/error-codes': 0.18.0 + '@module-federation/sdk': 0.18.0 + + '@module-federation/runtime-tools@0.18.0': + dependencies: + '@module-federation/runtime': 0.18.0 + '@module-federation/webpack-bundler-runtime': 0.18.0 + + '@module-federation/runtime@0.18.0': + dependencies: + '@module-federation/error-codes': 0.18.0 + '@module-federation/runtime-core': 0.18.0 + '@module-federation/sdk': 0.18.0 + + '@module-federation/sdk@0.18.0': {} + + '@module-federation/webpack-bundler-runtime@0.18.0': + dependencies: + '@module-federation/runtime': 0.18.0 + '@module-federation/sdk': 0.18.0 + '@mswjs/interceptors@0.37.6': dependencies: '@open-draft/deferred-promise': 2.2.0 @@ -5885,6 +6044,13 @@ snapshots: strict-event-emitter: 0.5.1 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@open-draft/deferred-promise@2.2.0': optional: true @@ -6031,6 +6197,94 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.54.0': optional: true + '@rsbuild/core@1.5.13(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@rspack/core': 1.5.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(@swc/helpers@0.5.23) + '@rspack/lite-tapable': 1.0.1 + '@swc/helpers': 0.5.23 + core-js: 3.45.1 + jiti: 2.6.1 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@rsbuild/plugin-react@1.4.2(@rsbuild/core@1.5.13(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2))': + dependencies: + '@rsbuild/core': 1.5.13(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@rspack/plugin-react-refresh': 1.6.2(react-refresh@0.18.0) + react-refresh: 0.18.0 + transitivePeerDependencies: + - webpack-hot-middleware + + '@rspack/binding-darwin-arm64@1.5.8': + optional: true + + '@rspack/binding-darwin-x64@1.5.8': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.5.8': + optional: true + + '@rspack/binding-linux-arm64-musl@1.5.8': + optional: true + + '@rspack/binding-linux-x64-gnu@1.5.8': + optional: true + + '@rspack/binding-linux-x64-musl@1.5.8': + optional: true + + '@rspack/binding-wasm32-wasi@1.5.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@rspack/binding-win32-arm64-msvc@1.5.8': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.5.8': + optional: true + + '@rspack/binding-win32-x64-msvc@1.5.8': + optional: true + + '@rspack/binding@1.5.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.5.8 + '@rspack/binding-darwin-x64': 1.5.8 + '@rspack/binding-linux-arm64-gnu': 1.5.8 + '@rspack/binding-linux-arm64-musl': 1.5.8 + '@rspack/binding-linux-x64-gnu': 1.5.8 + '@rspack/binding-linux-x64-musl': 1.5.8 + '@rspack/binding-wasm32-wasi': 1.5.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@rspack/binding-win32-arm64-msvc': 1.5.8 + '@rspack/binding-win32-ia32-msvc': 1.5.8 + '@rspack/binding-win32-x64-msvc': 1.5.8 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@rspack/core@1.5.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(@swc/helpers@0.5.23)': + dependencies: + '@module-federation/runtime-tools': 0.18.0 + '@rspack/binding': 1.5.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@rspack/lite-tapable': 1.0.1 + optionalDependencies: + '@swc/helpers': 0.5.23 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@rspack/lite-tapable@1.0.1': {} + + '@rspack/plugin-react-refresh@1.6.2(react-refresh@0.18.0)': + dependencies: + error-stack-parser: 2.1.4 + react-refresh: 0.18.0 + '@sindresorhus/is@4.6.0': {} '@size-limit/esbuild@12.0.0(size-limit@12.0.0(jiti@2.6.1))': @@ -6077,7 +6331,7 @@ snapshots: '@vitest/browser': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2))(vitest@4.0.16) '@vitest/browser-playwright': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(playwright@1.57.0)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2))(vitest@4.0.16) '@vitest/runner': 4.0.16 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) transitivePeerDependencies: - react - react-dom @@ -6160,6 +6414,10 @@ snapshots: magic-string: 0.25.9 string.prototype.matchall: 4.0.8 + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + '@tailwindcss/node@4.1.18': dependencies: '@jridgewell/remapping': 2.3.5 @@ -6265,6 +6523,11 @@ snapshots: '@trysound/sax@0.2.0': {} + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -6350,7 +6613,7 @@ snapshots: '@vitest/mocker': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2)) playwright: 1.57.0 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) transitivePeerDependencies: - bufferutil - msw @@ -6366,7 +6629,7 @@ snapshots: pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) ws: 8.18.3 transitivePeerDependencies: - bufferutil @@ -6387,7 +6650,7 @@ snapshots: magicast: 0.5.1 obug: 2.1.1 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -6466,8 +6729,7 @@ snapshots: acorn@8.15.0: {} - agent-base@7.1.4: - optional: true + agent-base@7.1.4: {} ansi-escapes@7.1.1: dependencies: @@ -6517,9 +6779,6 @@ snapshots: async@3.2.5: {} - asynckit@0.4.0: - optional: true - asyncro@3.0.0: {} autoprefixer@10.4.21(postcss@8.5.6): @@ -6579,6 +6838,10 @@ snapshots: baseline-browser-mapping@2.9.11: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -6664,12 +6927,6 @@ snapshots: cac@6.7.14: {} - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - optional: true - call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -6797,11 +7054,6 @@ snapshots: colorette@2.0.20: {} - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - optional: true - commander@10.0.1: {} commander@14.0.2: {} @@ -6837,6 +7089,8 @@ snapshots: dependencies: browserslist: 4.27.0 + core-js@3.45.1: {} + cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.0 @@ -6876,6 +7130,11 @@ snapshots: mdn-data: 2.0.14 source-map: 0.6.1 + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + css-what@6.1.0: {} css.escape@1.5.1: {} @@ -6930,26 +7189,25 @@ snapshots: dependencies: css-tree: 1.1.3 - cssstyle@4.6.0: + cssstyle@5.3.7: dependencies: - '@asamuzakjp/css-color': 3.2.0 - rrweb-cssom: 0.8.0 - optional: true + '@asamuzakjp/css-color': 4.1.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.6(css-tree@3.2.1) + css-tree: 3.2.1 + lru-cache: 11.2.4 csstype@3.2.3: {} - data-urls@5.0.0: + data-urls@6.0.1: dependencies: - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - optional: true + whatwg-mimetype: 5.0.0 + whatwg-url: 15.1.0 debug@4.4.3: dependencies: ms: 2.1.3 - decimal.js@10.6.0: - optional: true + decimal.js@10.6.0: {} deep-eql@5.0.2: {} @@ -6985,9 +7243,6 @@ snapshots: defu@6.1.4: {} - delayed-stream@1.0.0: - optional: true - dequal@2.0.3: {} destr@2.0.5: {} @@ -7022,13 +7277,6 @@ snapshots: dotenv@17.2.3: {} - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - optional: true - duplexer@0.1.1: {} duplexer@0.1.2: {} @@ -7060,8 +7308,7 @@ snapshots: entities@2.2.0: {} - entities@6.0.1: - optional: true + entities@8.0.0: {} environment@1.1.0: {} @@ -7069,6 +7316,10 @@ snapshots: dependencies: is-arrayish: 0.2.1 + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + es-abstract@1.21.1: dependencies: available-typed-arrays: 1.0.7 @@ -7109,32 +7360,16 @@ snapshots: dependencies: get-intrinsic: 1.2.4 - es-define-property@1.0.1: - optional: true - es-errors@1.3.0: {} es-module-lexer@1.7.0: {} - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - optional: true - es-set-tostringtag@2.0.1: dependencies: get-intrinsic: 1.2.4 has: 1.0.3 has-tostringtag: 1.0.2 - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - optional: true - es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 @@ -7245,15 +7480,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - optional: true - fraction.js@4.3.7: {} framer-motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3): @@ -7308,26 +7534,6 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - optional: true - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - optional: true - get-symbol-description@1.0.0: dependencies: call-bind: 1.0.7 @@ -7374,9 +7580,6 @@ snapshots: dependencies: get-intrinsic: 1.2.4 - gopd@1.2.0: - optional: true - graceful-fs@4.2.11: {} graphql@16.12.0: @@ -7432,7 +7635,6 @@ snapshots: html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 - optional: true html-escaper@2.0.2: {} @@ -7442,7 +7644,6 @@ snapshots: debug: 4.4.3 transitivePeerDependencies: - supports-color - optional: true https-proxy-agent@7.0.6: dependencies: @@ -7450,12 +7651,10 @@ snapshots: debug: 4.4.3 transitivePeerDependencies: - supports-color - optional: true iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 - optional: true icss-replace-symbols@1.1.0: {} @@ -7545,8 +7744,7 @@ snapshots: is-number@7.0.0: {} - is-potential-custom-element-name@1.0.1: - optional: true + is-potential-custom-element-name@1.0.1: {} is-reference@1.2.1: dependencies: @@ -7641,34 +7839,32 @@ snapshots: js-tokens@4.0.0: {} - jsdom@25.0.1: + jsdom@27.0.1: dependencies: - cssstyle: 4.6.0 - data-urls: 5.0.0 + '@asamuzakjp/dom-selector': 6.8.1 + cssstyle: 5.3.7 + data-urls: 6.0.1 decimal.js: 10.6.0 - form-data: 4.0.5 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.23 - parse5: 7.3.0 - rrweb-cssom: 0.7.1 + parse5: 8.0.1 + rrweb-cssom: 0.8.0 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 5.1.2 + tough-cookie: 6.0.2 w3c-xmlserializer: 5.0.0 - webidl-conversions: 7.0.0 + webidl-conversions: 8.0.1 whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 + whatwg-url: 15.1.0 ws: 8.18.3 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - optional: true jsesc@0.5.0: {} @@ -7801,13 +7997,12 @@ snapshots: loupe@3.2.1: {} - lru-cache@10.4.3: - optional: true - lru-cache@11.2.2: {} lru-cache@11.2.4: {} + lru-cache@11.5.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -7849,9 +8044,6 @@ snapshots: marked@9.1.6: {} - math-intrinsics@1.1.0: - optional: true - maxmin@2.1.0: dependencies: chalk: 1.1.3 @@ -7861,6 +8053,8 @@ snapshots: mdn-data@2.0.14: {} + mdn-data@2.27.1: {} + memorystream@0.3.1: {} merge-stream@2.0.0: {} @@ -7919,14 +8113,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.52.0: - optional: true - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - optional: true - mimic-function@5.0.1: {} min-indent@1.0.1: {} @@ -8055,9 +8241,6 @@ snapshots: number-is-nan@1.0.1: {} - nwsapi@2.2.23: - optional: true - nypm@0.6.2: dependencies: citty: 0.1.6 @@ -8158,10 +8341,9 @@ snapshots: parse5@6.0.1: {} - parse5@7.3.0: + parse5@8.0.1: dependencies: - entities: 6.0.1 - optional: true + entities: 8.0.0 path-exists@4.0.0: {} @@ -8479,8 +8661,7 @@ snapshots: picocolors: 1.1.1 sade: 1.8.1 - punycode@2.3.1: - optional: true + punycode@2.3.1: {} querystringify@2.2.0: optional: true @@ -8578,6 +8759,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + requires-port@1.0.0: optional: true @@ -8691,11 +8874,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.54.0 fsevents: 2.3.3 - rrweb-cssom@0.7.1: - optional: true - - rrweb-cssom@0.8.0: - optional: true + rrweb-cssom@0.8.0: {} run-applescript@7.1.0: {} @@ -8713,13 +8892,11 @@ snapshots: get-intrinsic: 1.2.4 is-regex: 1.1.4 - safer-buffer@2.1.2: - optional: true + safer-buffer@2.1.2: {} saxes@6.0.0: dependencies: xmlchars: 2.2.0 - optional: true scheduler@0.27.0: {} @@ -8835,6 +9012,8 @@ snapshots: stackback@0.0.2: {} + stackframe@1.3.4: {} + statuses@2.0.2: optional: true @@ -8987,8 +9166,7 @@ snapshots: picocolors: 1.1.1 stable: 0.1.8 - symbol-tree@3.2.4: - optional: true + symbol-tree@3.2.4: {} tailwindcss@4.1.18: {} @@ -9041,13 +9219,11 @@ snapshots: tinyspy@4.0.4: {} - tldts-core@6.1.86: - optional: true + tldts-core@7.4.8: {} - tldts@6.1.86: + tldts@7.4.8: dependencies: - tldts-core: 6.1.86 - optional: true + tldts-core: 7.4.8 to-regex-range@5.0.1: dependencies: @@ -9063,15 +9239,13 @@ snapshots: url-parse: 1.5.10 optional: true - tough-cookie@5.1.2: + tough-cookie@6.0.2: dependencies: - tldts: 6.1.86 - optional: true + tldts: 7.4.8 - tr46@5.1.1: + tr46@6.0.0: dependencies: punycode: 2.3.1 - optional: true tree-kill@1.2.2: {} @@ -9215,7 +9389,7 @@ snapshots: terser: 5.37.0 yaml: 2.8.2 - vitest@4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2): + vitest@4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.16 '@vitest/mocker': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2)) @@ -9240,7 +9414,7 @@ snapshots: optionalDependencies: '@types/node': 25.0.3 '@vitest/browser-playwright': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(playwright@1.57.0)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2))(vitest@4.0.16) - jsdom: 25.0.1 + jsdom: 27.0.1 transitivePeerDependencies: - jiti - less @@ -9257,26 +9431,23 @@ snapshots: w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 - optional: true - webidl-conversions@7.0.0: - optional: true + webidl-conversions@8.0.1: {} webpack-virtual-modules@0.6.2: {} whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 - optional: true - whatwg-mimetype@4.0.0: - optional: true + whatwg-mimetype@4.0.0: {} + + whatwg-mimetype@5.0.0: {} - whatwg-url@14.2.0: + whatwg-url@15.1.0: dependencies: - tr46: 5.1.1 - webidl-conversions: 7.0.0 - optional: true + tr46: 6.0.0 + webidl-conversions: 8.0.1 which-boxed-primitive@1.0.2: dependencies: @@ -9340,11 +9511,9 @@ snapshots: dependencies: is-wsl: 3.1.0 - xml-name-validator@5.0.0: - optional: true + xml-name-validator@5.0.0: {} - xmlchars@2.2.0: - optional: true + xmlchars@2.2.0: {} y18n@5.0.8: {} diff --git a/scripts/compat/packed.mjs b/scripts/compat/packed.mjs new file mode 100644 index 00000000..978f77a5 --- /dev/null +++ b/scripts/compat/packed.mjs @@ -0,0 +1,115 @@ +import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; +import { + cp, + mkdir, + mkdtemp, + readdir, + readFile, + rm, + writeFile, +} from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { basename, dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { promisify } from "node:util"; +import { JSDOM, VirtualConsole } from "jsdom"; + +const exec = promisify(execFile); +const repositoryRoot = resolve( + dirname(fileURLToPath(import.meta.url)), + "../..", +); +const fixtureRoot = join(repositoryRoot, "fixtures/react-compat"); +const versions = { + 17: "17.0.2", + 18: "18.3.1", + 19: "19.2.3", +}; +const major = process.argv.slice(2).find((argument) => argument !== "--"); + +if (!(major in versions)) { + throw new Error("Usage: pnpm run compat:packed -- 17|18|19"); +} + +const temporaryRoot = await mkdtemp(join(tmpdir(), `rio-react-${major}-`)); + +try { + const packageDirectory = join(temporaryRoot, "package"); + const packDirectory = join(temporaryRoot, "pack"); + await cp(fixtureRoot, packageDirectory, { recursive: true }); + await mkdir(packDirectory); + + const { stdout } = await exec( + "corepack", + ["pnpm", "pack", "--pack-destination", packDirectory], + { cwd: repositoryRoot }, + ); + const tarballName = stdout.trim().split("\n").at(-1); + const tarballPath = join(packDirectory, basename(tarballName)); + + await writeFile( + join(packageDirectory, "package.json"), + `${JSON.stringify( + { + private: true, + type: "module", + scripts: { build: "rsbuild build" }, + dependencies: { + "@rsbuild/core": "1.5.13", + "@rsbuild/plugin-react": "1.4.2", + jsdom: "27.0.1", + react: versions[major], + "react-dom": versions[major], + "react-intersection-observer": `file:${tarballPath}`, + }, + }, + null, + 2, + )}\n`, + ); + + await exec("corepack", ["pnpm", "install"], { cwd: packageDirectory }); + await exec("corepack", ["pnpm", "build"], { + cwd: packageDirectory, + env: { ...process.env, REACT_MAJOR: major }, + }); + + const scripts = ( + await readdir(join(packageDirectory, "dist", "static", "js")) + ).filter((file) => file.endsWith(".js")); + assert.equal(scripts.length, 1, "expected one built client bundle"); + const bundle = await readFile( + join(packageDirectory, "dist", "static", "js", scripts[0]), + "utf8", + ); + const jsdomErrors = []; + const virtualConsole = new VirtualConsole(); + virtualConsole.on("jsdomError", (error) => jsdomErrors.push(error)); + const dom = new JSDOM('
', { + runScripts: "dangerously", + url: "http://localhost/", + virtualConsole, + }); + dom.window.eval(bundle); + + for ( + let attempt = 0; + attempt < 100 && !dom.window.__COMPAT_RESULT__; + attempt++ + ) { + await new Promise((resolve) => setTimeout(resolve, 10)); + } + + assert.deepEqual(jsdomErrors, []); + const result = dom.window.__COMPAT_RESULT__; + assert.ok(result, "smoke test did not finish"); + assert.equal(result.diagnostics.length, 0, result.diagnostics.join("\n")); + assert.equal(result.observeCount, 4); + assert.equal(result.unobserveCount, 4); + dom.window.close(); + + console.log(`React ${major} packed compatibility passed`); +} finally { + await rm(temporaryRoot, { recursive: true, force: true }); +} diff --git a/src/__tests__/useOnInView.test.tsx b/src/__tests__/useOnInView.test.tsx index ed9ccab0..7df6fbea 100644 --- a/src/__tests__/useOnInView.test.tsx +++ b/src/__tests__/useOnInView.test.tsx @@ -118,6 +118,12 @@ const ThresholdTriggerComponent = ({ ); }; +const RefLifecycleComponent = ({ attached }: { attached: boolean }) => { + const inViewRef = useOnInView(() => {}); + + return attached ?
: null; +}; + test("should create a hook with useOnInView", () => { const { getByTestId } = render(); const wrapper = getByTestId("wrapper"); @@ -254,6 +260,36 @@ test("should handle ref changes", () => { expect(wrapper.getAttribute("data-inview")).toBe("true"); }); +test("should clean up each ref attachment without React diagnostics", () => { + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); + + try { + const { getByTestId, rerender, unmount } = render( + , + ); + const firstElement = getByTestId("ref-lifecycle"); + const firstObserver = intersectionMockInstance(firstElement); + + rerender(); + expect(firstObserver.unobserve).toHaveBeenCalledTimes(1); + expect(firstObserver.unobserve).toHaveBeenCalledWith(firstElement); + + rerender(); + const secondElement = getByTestId("ref-lifecycle"); + const secondObserver = intersectionMockInstance(secondElement); + + unmount(); + expect(secondObserver.unobserve).toHaveBeenCalledTimes(1); + expect(secondObserver.unobserve).toHaveBeenCalledWith(secondElement); + expect(errorSpy).not.toHaveBeenCalled(); + expect(warnSpy).not.toHaveBeenCalled(); + } finally { + errorSpy.mockRestore(); + warnSpy.mockRestore(); + } +}); + // Test for merging refs const MergeRefsComponent = ({ options, From 7b696f706da9cf2ba0e59b27aeeadf755badea46 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jul 2026 11:19:37 +0200 Subject: [PATCH 2/6] fix: gate callback ref cleanup by React version --- src/useOnInView.tsx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/useOnInView.tsx b/src/useOnInView.tsx index 5e9069c0..a057b94e 100644 --- a/src/useOnInView.tsx +++ b/src/useOnInView.tsx @@ -5,13 +5,17 @@ import type { } from "./index"; import { observe } from "./observe"; -const useSyncEffect = (("useInsertionEffect" in React - ? (React as typeof React & { useInsertionEffect: typeof React.useEffect }) - .useInsertionEffect - : undefined) ?? +const useSyncEffect = ((Reflect.get(React, "useInsertionEffect") as + | typeof React.useEffect + | undefined) ?? React.useLayoutEffect ?? React.useEffect) as typeof React.useEffect; +const supportsRefCleanup = (() => { + const majorVersion = Number.parseInt(React.version.split(".")[0], 10); + return Number.isInteger(majorVersion) && majorVersion >= 19; +})(); + /** * React Hooks make it easy to monitor when elements come into and leave view. Call * the `useOnInView` hook with your callback and (optional) [options](#options). @@ -68,8 +72,8 @@ export const useOnInView = ( // biome-ignore lint/correctness/useExhaustiveDependencies: Threshold arrays are normalized inside the callback return React.useCallback( (element: TElement | undefined | null) => { - // React <19 never calls ref callbacks with `null` during unmount, so we - // eagerly tear down existing observers manually whenever the target changes. + // React 17 and 18 call callback refs with `null` instead of invoking a + // returned cleanup, so eagerly tear down whenever the target changes. const cleanupExisting = () => { if (observerCleanupRef.current) { const cleanup = observerCleanupRef.current; @@ -79,7 +83,7 @@ export const useOnInView = ( }; if (element === observedElementRef.current) { - return observerCleanupRef.current; + return supportsRefCleanup ? observerCleanupRef.current : undefined; } if (!element || skip) { @@ -136,7 +140,7 @@ export const useOnInView = ( observerCleanupRef.current = stopObserving; - return observerCleanupRef.current; + return supportsRefCleanup ? observerCleanupRef.current : undefined; }, [ Array.isArray(threshold) ? threshold.toString() : threshold, From 597f5e5de076605b0693d6673edf2f2d4f761ac2 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jul 2026 12:08:59 +0200 Subject: [PATCH 3/6] fix: parse React ref cleanup support conservatively --- src/__tests__/useOnInView.test.tsx | 17 +++++++++++++++++ src/refCleanupSupport.ts | 3 +++ src/useOnInView.tsx | 10 ++++------ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 src/refCleanupSupport.ts diff --git a/src/__tests__/useOnInView.test.tsx b/src/__tests__/useOnInView.test.tsx index 7df6fbea..74045bd4 100644 --- a/src/__tests__/useOnInView.test.tsx +++ b/src/__tests__/useOnInView.test.tsx @@ -1,6 +1,7 @@ import { render } from "@testing-library/react"; import { useCallback, useEffect, useState } from "react"; import type { IntersectionEffectOptions } from ".."; +import { supportsRefCleanup } from "../refCleanupSupport"; import { intersectionMockInstance, mockAllIsIntersecting } from "../test-utils"; import { useOnInView } from "../useOnInView"; @@ -124,6 +125,22 @@ const RefLifecycleComponent = ({ attached }: { attached: boolean }) => { return attached ?
: null; }; +test.each([ + ["19.0.0", true], + ["19.0.0-rc.1", true], + ["19.0.0-experimental-abcdef", true], + ["20.1.0", false], + ["18.3.1", false], + ["17.0.2", false], + [undefined, false], + ["unknown", false], + ["19unknown", false], + ["19", false], + ["v19.0.0", false], +])("detects ref cleanup support for React version %s", (version, expected) => { + expect(supportsRefCleanup(version)).toBe(expected); +}); + test("should create a hook with useOnInView", () => { const { getByTestId } = render(); const wrapper = getByTestId("wrapper"); diff --git a/src/refCleanupSupport.ts b/src/refCleanupSupport.ts new file mode 100644 index 00000000..6629cc7f --- /dev/null +++ b/src/refCleanupSupport.ts @@ -0,0 +1,3 @@ +export function supportsRefCleanup(version: string | undefined) { + return version?.startsWith("19.") ?? false; +} diff --git a/src/useOnInView.tsx b/src/useOnInView.tsx index a057b94e..758c9f37 100644 --- a/src/useOnInView.tsx +++ b/src/useOnInView.tsx @@ -4,6 +4,7 @@ import type { IntersectionEffectOptions, } from "./index"; import { observe } from "./observe"; +import { supportsRefCleanup } from "./refCleanupSupport"; const useSyncEffect = ((Reflect.get(React, "useInsertionEffect") as | typeof React.useEffect @@ -11,10 +12,7 @@ const useSyncEffect = ((Reflect.get(React, "useInsertionEffect") as React.useLayoutEffect ?? React.useEffect) as typeof React.useEffect; -const supportsRefCleanup = (() => { - const majorVersion = Number.parseInt(React.version.split(".")[0], 10); - return Number.isInteger(majorVersion) && majorVersion >= 19; -})(); +const canUseRefCleanup = supportsRefCleanup(React.version); /** * React Hooks make it easy to monitor when elements come into and leave view. Call @@ -83,7 +81,7 @@ export const useOnInView = ( }; if (element === observedElementRef.current) { - return supportsRefCleanup ? observerCleanupRef.current : undefined; + return canUseRefCleanup ? observerCleanupRef.current : undefined; } if (!element || skip) { @@ -140,7 +138,7 @@ export const useOnInView = ( observerCleanupRef.current = stopObserving; - return supportsRefCleanup ? observerCleanupRef.current : undefined; + return canUseRefCleanup ? observerCleanupRef.current : undefined; }, [ Array.isArray(threshold) ? threshold.toString() : threshold, From 857f0ecb588ba5b8c47080bfac0c8bfa83f92e57 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jul 2026 12:25:36 +0200 Subject: [PATCH 4/6] test: compose callback refs across React versions --- src/__tests__/useOnInView.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/__tests__/useOnInView.test.tsx b/src/__tests__/useOnInView.test.tsx index 74045bd4..5f53c625 100644 --- a/src/__tests__/useOnInView.test.tsx +++ b/src/__tests__/useOnInView.test.tsx @@ -362,6 +362,8 @@ const MultipleCallbacksComponent = ({ const mergedRefs = useCallback( (node: Element | null) => { const cleanup = [ref1(node), ref2(node), ref3(node)]; + if (cleanup.every((fn) => !fn)) return; + return () => cleanup.forEach((fn) => { fn?.(); From a7fc254cebc71012f3eedae2c4ab1504a7b9fc91 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jul 2026 12:28:09 +0200 Subject: [PATCH 5/6] test: simplify packed React compatibility --- .github/workflows/test.yml | 3 +- fixtures/react-compat/entry-legacy.jsx | 19 - fixtures/react-compat/entry-react19.jsx | 21 - fixtures/react-compat/entry.jsx | 15 + fixtures/react-compat/rsbuild.config.mjs | 12 +- fixtures/react-compat/scenario.jsx | 38 -- package.json | 1 - pnpm-lock.yaml | 497 ++++++++++++++--------- scripts/compat/packed.mjs | 63 +-- 9 files changed, 338 insertions(+), 331 deletions(-) delete mode 100644 fixtures/react-compat/entry-legacy.jsx delete mode 100644 fixtures/react-compat/entry-react19.jsx create mode 100644 fixtures/react-compat/entry.jsx delete mode 100644 fixtures/react-compat/scenario.jsx diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2b13db07..9f03af82 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,7 +63,8 @@ jobs: - name: Build package run: pnpm build - name: Test packed package - run: pnpm run compat:packed -- $(node -p "require('react/package.json').version.split('.')[0]") + if: ${{ matrix.react != 'latest' }} + run: pnpm run compat:packed -- ${{ matrix.react }} - name: Run test run: | pnpm exec playwright install diff --git a/fixtures/react-compat/entry-legacy.jsx b/fixtures/react-compat/entry-legacy.jsx deleted file mode 100644 index 1f85a111..00000000 --- a/fixtures/react-compat/entry-legacy.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import ReactDOM from "react-dom"; -import { CompatibilityFixture, result, settle } from "./scenario"; - -const container = document.getElementById("root"); - -async function run() { - ReactDOM.render(, container); - await settle(); - ReactDOM.render(, container); - await settle(); - ReactDOM.render(, container); - await settle(); - ReactDOM.unmountComponentAtNode(container); - await settle(); - - window.__COMPAT_RESULT__ = result(); -} - -run(); diff --git a/fixtures/react-compat/entry-react19.jsx b/fixtures/react-compat/entry-react19.jsx deleted file mode 100644 index f93f6a9f..00000000 --- a/fixtures/react-compat/entry-react19.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import { flushSync } from "react-dom"; -import { createRoot } from "react-dom/client"; -import { CompatibilityFixture, result, settle } from "./scenario"; - -const container = document.getElementById("root"); -const root = createRoot(container); - -async function run() { - flushSync(() => root.render()); - await settle(); - flushSync(() => root.render()); - await settle(); - flushSync(() => root.render()); - await settle(); - flushSync(() => root.unmount()); - await settle(); - - window.__COMPAT_RESULT__ = result(); -} - -run(); diff --git a/fixtures/react-compat/entry.jsx b/fixtures/react-compat/entry.jsx new file mode 100644 index 00000000..7d8de893 --- /dev/null +++ b/fixtures/react-compat/entry.jsx @@ -0,0 +1,15 @@ +import { useInView, useOnInView } from "react-intersection-observer"; + +function CompatibilityFixture() { + const callbackRef = useOnInView(() => {}); + const { ref: stateRef } = useInView(); + + return ( + <> +
+
+ + ); +} + +window.__COMPAT_FIXTURE__ = CompatibilityFixture; diff --git a/fixtures/react-compat/rsbuild.config.mjs b/fixtures/react-compat/rsbuild.config.mjs index c5138a05..11f055d2 100644 --- a/fixtures/react-compat/rsbuild.config.mjs +++ b/fixtures/react-compat/rsbuild.config.mjs @@ -5,17 +5,7 @@ export default defineConfig({ plugins: [pluginReact()], source: { entry: { - index: - process.env.REACT_MAJOR === "19" - ? "./entry-react19.jsx" - : "./entry-legacy.jsx", + index: "./entry.jsx", }, }, - output: { - distPath: { root: "dist" }, - filename: { js: "[name].js" }, - }, - performance: { - chunkSplit: { strategy: "all-in-one" }, - }, }); diff --git a/fixtures/react-compat/scenario.jsx b/fixtures/react-compat/scenario.jsx deleted file mode 100644 index 6c3fe0ac..00000000 --- a/fixtures/react-compat/scenario.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useInView, useOnInView } from "react-intersection-observer"; - -const diagnostics = []; -let observeCount = 0; -let unobserveCount = 0; - -console.error = (...args) => diagnostics.push(args.join(" ")); -console.warn = (...args) => diagnostics.push(args.join(" ")); - -window.IntersectionObserver = class IntersectionObserver { - observe() { - observeCount += 1; - } - - unobserve() { - unobserveCount += 1; - } - - disconnect() {} -}; - -export function CompatibilityFixture({ attached }) { - const callbackRef = useOnInView(() => {}); - const { ref: stateRef } = useInView(); - - return attached ? ( - <> -
-
- - ) : null; -} - -export const settle = () => new Promise((resolve) => setTimeout(resolve, 0)); - -export function result() { - return { diagnostics, observeCount, unobserveCount }; -} diff --git a/package.json b/package.json index c7bda298..5fbd2c1a 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,6 @@ "@vitest/browser-playwright": "^4.0.16", "@vitest/coverage-istanbul": "^4.0.16", "bumpp": "^10.3.2", - "jsdom": "27.0.1", "lint-staged": "^16.2.7", "microbundle": "^0.15.1", "npm-run-all": "^4.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb903239..a6bba85d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,9 +50,6 @@ importers: bumpp: specifier: ^10.3.2 version: 10.3.2(magicast@0.5.1) - jsdom: - specifier: 27.0.1 - version: 27.0.1 lint-staged: specifier: ^16.2.7 version: 16.2.7 @@ -88,7 +85,7 @@ importers: version: 5.9.3 vitest: specifier: ^4.0.16 - version: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + version: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) storybook: dependencies: @@ -179,14 +176,8 @@ packages: resolution: {integrity: sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg==} engines: {node: '>=20'} - '@asamuzakjp/css-color@4.1.2': - resolution: {integrity: sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==} - - '@asamuzakjp/dom-selector@6.8.1': - resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} - - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} @@ -991,41 +982,33 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@csstools/color-helpers@6.1.0': - resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} - engines: {node: '>=20.19.0'} - - '@csstools/css-calc@3.2.1': - resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} - '@csstools/css-color-parser@4.1.9': - resolution: {integrity: sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==} - engines: {node: '>=20.19.0'} + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} peerDependencies: - '@csstools/css-parser-algorithms': ^4.0.0 - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-parser-algorithms@4.0.0': - resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} - engines: {node: '>=20.19.0'} + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} peerDependencies: - '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.1.6': - resolution: {integrity: sha512-TcJCWFbXLPpJYq6z7bfOyjWYJDiDg2/I4gyUC9pqPNqHFRIey0EB0q0L5cSnQDfWJg8Jd6VadakxdIez/3zkqQ==} + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} peerDependencies: - css-tree: ^3.2.1 - peerDependenciesMeta: - css-tree: - optional: true + '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-tokenizer@4.0.0': - resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} - engines: {node: '>=20.19.0'} + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} '@emnapi/core@1.11.2': resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} @@ -2049,6 +2032,9 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + asyncro@3.0.0: resolution: {integrity: sha512-nEnWYfrBmA3taTiuiOoZYmgJ/CNrSoQLeLs29SeLcPu60yaw/mHDBHV0iOZ051fTvsTHxpCY+gXibqT9wbQYfg==} @@ -2101,9 +2087,6 @@ packages: resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} hasBin: true - bidi-js@1.0.3: - resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2169,6 +2152,10 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -2283,6 +2270,10 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -2362,10 +2353,6 @@ packages: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} - css-tree@3.2.1: - resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2400,16 +2387,16 @@ packages: resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} engines: {node: '>=8.0.0'} - cssstyle@5.3.7: - resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} - engines: {node: '>=20'} + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - data-urls@6.0.1: - resolution: {integrity: sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==} - engines: {node: '>=20'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -2462,6 +2449,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2500,6 +2491,10 @@ packages: resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + duplexer@0.1.1: resolution: {integrity: sha512-sxNZ+ljy+RA1maXoUReeqBBpBC6RLKmg5ewzV+x+mSETmWNoKdZN6vcQjpFROemza23hGFskJtFNoUWUaQ+R4Q==} @@ -2543,9 +2538,9 @@ packages: entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - entities@8.0.0: - resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} - engines: {node: '>=20.19.0'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} @@ -2565,6 +2560,10 @@ packages: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} @@ -2572,10 +2571,18 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} @@ -2676,6 +2683,10 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -2739,6 +2750,14 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -2774,6 +2793,10 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -3044,11 +3067,11 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - jsdom@27.0.1: - resolution: {integrity: sha512-SNSQteBL1IlV2zqhwwolaG9CwhIhTvVHWg3kTss/cLE7H/X4644mtPQqYvCfsSrGQWt9hSZcgOXX8bOZaMN+kA==} - engines: {node: '>=20'} + jsdom@25.0.1: + resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} + engines: {node: '>=18'} peerDependencies: - canvas: ^3.0.0 + canvas: ^2.11.2 peerDependenciesMeta: canvas: optional: true @@ -3216,6 +3239,9 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.2: resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} @@ -3224,10 +3250,6 @@ packages: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} - lru-cache@11.5.2: - resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} - engines: {node: 20 || >=22} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3263,6 +3285,10 @@ packages: engines: {node: '>= 16'} hasBin: true + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + maxmin@2.1.0: resolution: {integrity: sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==} engines: {node: '>=0.12'} @@ -3270,9 +3296,6 @@ packages: mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - mdn-data@2.27.1: - resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - memorystream@0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} @@ -3288,6 +3311,14 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -3407,6 +3438,9 @@ packages: resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} engines: {node: '>=0.10.0'} + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + nypm@0.6.2: resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==} engines: {node: ^14.16.0 || >=16.10.0} @@ -3505,8 +3539,8 @@ packages: parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parse5@8.0.1: - resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -3961,10 +3995,6 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -4037,6 +4067,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -4372,11 +4405,11 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} - tldts-core@7.4.8: - resolution: {integrity: sha512-c1P7u0EhACHj7lPy4MJm8iTFEU8+nB0LCtddH0fhP7noaVoXAqafMtOOeX+ulpuPBqnrRgRhw494RICT3mbhnw==} + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts@7.4.8: - resolution: {integrity: sha512-htwgN/8KRB3z3vnC0BOETVh2m499g5GmyTK9Wq5JBLX3FNz6tSBveAd+fQhzy9hkjif8vy2jwDMR1sGhLtZl2A==} + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true to-regex-range@5.0.1: @@ -4391,13 +4424,13 @@ packages: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} - tough-cookie@6.0.2: - resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} - tr46@6.0.0: - resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} - engines: {node: '>=20'} + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} @@ -4610,9 +4643,9 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - webidl-conversions@8.0.1: - resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} - engines: {node: '>=20'} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} @@ -4626,13 +4659,9 @@ packages: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - whatwg-mimetype@5.0.0: - resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} - engines: {node: '>=20'} - - whatwg-url@15.1.0: - resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} - engines: {node: '>=20'} + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -4767,23 +4796,14 @@ snapshots: typescript: 5.6.1-rc validate-npm-package-name: 5.0.1 - '@asamuzakjp/css-color@4.1.2': - dependencies: - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 - lru-cache: 11.5.2 - - '@asamuzakjp/dom-selector@6.8.1': + '@asamuzakjp/css-color@3.2.0': dependencies: - '@asamuzakjp/nwsapi': 2.3.9 - bidi-js: 1.0.3 - css-tree: 3.2.1 - is-potential-custom-element-name: 1.0.1 - lru-cache: 11.5.2 - - '@asamuzakjp/nwsapi@2.3.9': {} + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + optional: true '@babel/code-frame@7.26.2': dependencies: @@ -5772,29 +5792,30 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@csstools/color-helpers@6.1.0': {} + '@csstools/color-helpers@5.1.0': + optional: true - '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + optional: true - '@csstools/css-color-parser@4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - '@csstools/color-helpers': 6.1.0 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) - '@csstools/css-tokenizer': 4.0.0 + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + optional: true - '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': dependencies: - '@csstools/css-tokenizer': 4.0.0 - - '@csstools/css-syntax-patches-for-csstree@1.1.6(css-tree@3.2.1)': - optionalDependencies: - css-tree: 3.2.1 + '@csstools/css-tokenizer': 3.0.4 + optional: true - '@csstools/css-tokenizer@4.0.0': {} + '@csstools/css-tokenizer@3.0.4': + optional: true '@emnapi/core@1.11.2': dependencies: @@ -6331,7 +6352,7 @@ snapshots: '@vitest/browser': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2))(vitest@4.0.16) '@vitest/browser-playwright': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(playwright@1.57.0)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2))(vitest@4.0.16) '@vitest/runner': 4.0.16 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) transitivePeerDependencies: - react - react-dom @@ -6613,7 +6634,7 @@ snapshots: '@vitest/mocker': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2)) playwright: 1.57.0 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) transitivePeerDependencies: - bufferutil - msw @@ -6629,7 +6650,7 @@ snapshots: pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) ws: 8.18.3 transitivePeerDependencies: - bufferutil @@ -6650,7 +6671,7 @@ snapshots: magicast: 0.5.1 obug: 2.1.1 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) + vitest: 4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -6729,7 +6750,8 @@ snapshots: acorn@8.15.0: {} - agent-base@7.1.4: {} + agent-base@7.1.4: + optional: true ansi-escapes@7.1.1: dependencies: @@ -6779,6 +6801,9 @@ snapshots: async@3.2.5: {} + asynckit@0.4.0: + optional: true + asyncro@3.0.0: {} autoprefixer@10.4.21(postcss@8.5.6): @@ -6838,10 +6863,6 @@ snapshots: baseline-browser-mapping@2.9.11: {} - bidi-js@1.0.3: - dependencies: - require-from-string: 2.0.2 - boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -6927,6 +6948,12 @@ snapshots: cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + optional: true + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -7054,6 +7081,11 @@ snapshots: colorette@2.0.20: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + optional: true + commander@10.0.1: {} commander@14.0.2: {} @@ -7130,11 +7162,6 @@ snapshots: mdn-data: 2.0.14 source-map: 0.6.1 - css-tree@3.2.1: - dependencies: - mdn-data: 2.27.1 - source-map-js: 1.2.1 - css-what@6.1.0: {} css.escape@1.5.1: {} @@ -7189,25 +7216,26 @@ snapshots: dependencies: css-tree: 1.1.3 - cssstyle@5.3.7: + cssstyle@4.6.0: dependencies: - '@asamuzakjp/css-color': 4.1.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.6(css-tree@3.2.1) - css-tree: 3.2.1 - lru-cache: 11.2.4 + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + optional: true csstype@3.2.3: {} - data-urls@6.0.1: + data-urls@5.0.0: dependencies: - whatwg-mimetype: 5.0.0 - whatwg-url: 15.1.0 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + optional: true debug@4.4.3: dependencies: ms: 2.1.3 - decimal.js@10.6.0: {} + decimal.js@10.6.0: + optional: true deep-eql@5.0.2: {} @@ -7243,6 +7271,9 @@ snapshots: defu@6.1.4: {} + delayed-stream@1.0.0: + optional: true + dequal@2.0.3: {} destr@2.0.5: {} @@ -7277,6 +7308,13 @@ snapshots: dotenv@17.2.3: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + optional: true + duplexer@0.1.1: {} duplexer@0.1.2: {} @@ -7308,7 +7346,8 @@ snapshots: entities@2.2.0: {} - entities@8.0.0: {} + entities@6.0.1: + optional: true environment@1.1.0: {} @@ -7360,16 +7399,32 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + es-define-property@1.0.1: + optional: true + es-errors@1.3.0: {} es-module-lexer@1.7.0: {} + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + optional: true + es-set-tostringtag@2.0.1: dependencies: get-intrinsic: 1.2.4 has: 1.0.3 has-tostringtag: 1.0.2 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + optional: true + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 @@ -7480,6 +7535,15 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + optional: true + fraction.js@4.3.7: {} framer-motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3): @@ -7534,6 +7598,26 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + optional: true + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + optional: true + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.7 @@ -7580,6 +7664,9 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + gopd@1.2.0: + optional: true + graceful-fs@4.2.11: {} graphql@16.12.0: @@ -7635,6 +7722,7 @@ snapshots: html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 + optional: true html-escaper@2.0.2: {} @@ -7644,6 +7732,7 @@ snapshots: debug: 4.4.3 transitivePeerDependencies: - supports-color + optional: true https-proxy-agent@7.0.6: dependencies: @@ -7651,10 +7740,12 @@ snapshots: debug: 4.4.3 transitivePeerDependencies: - supports-color + optional: true iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + optional: true icss-replace-symbols@1.1.0: {} @@ -7744,7 +7835,8 @@ snapshots: is-number@7.0.0: {} - is-potential-custom-element-name@1.0.1: {} + is-potential-custom-element-name@1.0.1: + optional: true is-reference@1.2.1: dependencies: @@ -7839,32 +7931,34 @@ snapshots: js-tokens@4.0.0: {} - jsdom@27.0.1: + jsdom@25.0.1: dependencies: - '@asamuzakjp/dom-selector': 6.8.1 - cssstyle: 5.3.7 - data-urls: 6.0.1 + cssstyle: 4.6.0 + data-urls: 5.0.0 decimal.js: 10.6.0 + form-data: 4.0.5 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - parse5: 8.0.1 - rrweb-cssom: 0.8.0 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.7.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 6.0.2 + tough-cookie: 5.1.2 w3c-xmlserializer: 5.0.0 - webidl-conversions: 8.0.1 + webidl-conversions: 7.0.0 whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 - whatwg-url: 15.1.0 + whatwg-url: 14.2.0 ws: 8.18.3 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate + optional: true jsesc@0.5.0: {} @@ -7997,12 +8091,13 @@ snapshots: loupe@3.2.1: {} + lru-cache@10.4.3: + optional: true + lru-cache@11.2.2: {} lru-cache@11.2.4: {} - lru-cache@11.5.2: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -8044,6 +8139,9 @@ snapshots: marked@9.1.6: {} + math-intrinsics@1.1.0: + optional: true + maxmin@2.1.0: dependencies: chalk: 1.1.3 @@ -8053,8 +8151,6 @@ snapshots: mdn-data@2.0.14: {} - mdn-data@2.27.1: {} - memorystream@0.3.1: {} merge-stream@2.0.0: {} @@ -8113,6 +8209,14 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: + optional: true + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + optional: true + mimic-function@5.0.1: {} min-indent@1.0.1: {} @@ -8241,6 +8345,9 @@ snapshots: number-is-nan@1.0.1: {} + nwsapi@2.2.23: + optional: true + nypm@0.6.2: dependencies: citty: 0.1.6 @@ -8341,9 +8448,10 @@ snapshots: parse5@6.0.1: {} - parse5@8.0.1: + parse5@7.3.0: dependencies: - entities: 8.0.0 + entities: 6.0.1 + optional: true path-exists@4.0.0: {} @@ -8661,7 +8769,8 @@ snapshots: picocolors: 1.1.1 sade: 1.8.1 - punycode@2.3.1: {} + punycode@2.3.1: + optional: true querystringify@2.2.0: optional: true @@ -8759,8 +8868,6 @@ snapshots: require-directory@2.1.1: {} - require-from-string@2.0.2: {} - requires-port@1.0.0: optional: true @@ -8874,7 +8981,11 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.54.0 fsevents: 2.3.3 - rrweb-cssom@0.8.0: {} + rrweb-cssom@0.7.1: + optional: true + + rrweb-cssom@0.8.0: + optional: true run-applescript@7.1.0: {} @@ -8892,11 +9003,13 @@ snapshots: get-intrinsic: 1.2.4 is-regex: 1.1.4 - safer-buffer@2.1.2: {} + safer-buffer@2.1.2: + optional: true saxes@6.0.0: dependencies: xmlchars: 2.2.0 + optional: true scheduler@0.27.0: {} @@ -9166,7 +9279,8 @@ snapshots: picocolors: 1.1.1 stable: 0.1.8 - symbol-tree@3.2.4: {} + symbol-tree@3.2.4: + optional: true tailwindcss@4.1.18: {} @@ -9219,11 +9333,13 @@ snapshots: tinyspy@4.0.4: {} - tldts-core@7.4.8: {} + tldts-core@6.1.86: + optional: true - tldts@7.4.8: + tldts@6.1.86: dependencies: - tldts-core: 7.4.8 + tldts-core: 6.1.86 + optional: true to-regex-range@5.0.1: dependencies: @@ -9239,13 +9355,15 @@ snapshots: url-parse: 1.5.10 optional: true - tough-cookie@6.0.2: + tough-cookie@5.1.2: dependencies: - tldts: 7.4.8 + tldts: 6.1.86 + optional: true - tr46@6.0.0: + tr46@5.1.1: dependencies: punycode: 2.3.1 + optional: true tree-kill@1.2.2: {} @@ -9389,7 +9507,7 @@ snapshots: terser: 5.37.0 yaml: 2.8.2 - vitest@4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@27.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2): + vitest@4.0.16(@types/node@25.0.3)(@vitest/browser-playwright@4.0.16)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(terser@5.37.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.16 '@vitest/mocker': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2)) @@ -9414,7 +9532,7 @@ snapshots: optionalDependencies: '@types/node': 25.0.3 '@vitest/browser-playwright': 4.0.16(msw@2.7.3(@types/node@25.0.3)(typescript@5.9.3))(playwright@1.57.0)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.37.0)(yaml@2.8.2))(vitest@4.0.16) - jsdom: 27.0.1 + jsdom: 25.0.1 transitivePeerDependencies: - jiti - less @@ -9431,23 +9549,26 @@ snapshots: w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 + optional: true - webidl-conversions@8.0.1: {} + webidl-conversions@7.0.0: + optional: true webpack-virtual-modules@0.6.2: {} whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 + optional: true - whatwg-mimetype@4.0.0: {} - - whatwg-mimetype@5.0.0: {} + whatwg-mimetype@4.0.0: + optional: true - whatwg-url@15.1.0: + whatwg-url@14.2.0: dependencies: - tr46: 6.0.0 - webidl-conversions: 8.0.1 + tr46: 5.1.1 + webidl-conversions: 7.0.0 + optional: true which-boxed-primitive@1.0.2: dependencies: @@ -9511,9 +9632,11 @@ snapshots: dependencies: is-wsl: 3.1.0 - xml-name-validator@5.0.0: {} + xml-name-validator@5.0.0: + optional: true - xmlchars@2.2.0: {} + xmlchars@2.2.0: + optional: true y18n@5.0.8: {} diff --git a/scripts/compat/packed.mjs b/scripts/compat/packed.mjs index 978f77a5..5c236063 100644 --- a/scripts/compat/packed.mjs +++ b/scripts/compat/packed.mjs @@ -1,19 +1,9 @@ -import assert from "node:assert/strict"; import { execFile } from "node:child_process"; -import { - cp, - mkdir, - mkdtemp, - readdir, - readFile, - rm, - writeFile, -} from "node:fs/promises"; +import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { basename, dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; -import { JSDOM, VirtualConsole } from "jsdom"; const exec = promisify(execFile); const repositoryRoot = resolve( @@ -21,6 +11,9 @@ const repositoryRoot = resolve( "../..", ); const fixtureRoot = join(repositoryRoot, "fixtures/react-compat"); +const repositoryPackage = JSON.parse( + await readFile(join(repositoryRoot, "package.json"), "utf8"), +); const versions = { 17: "17.0.2", 18: "18.3.1", @@ -54,11 +47,12 @@ try { { private: true, type: "module", + packageManager: repositoryPackage.packageManager, scripts: { build: "rsbuild build" }, dependencies: { - "@rsbuild/core": "1.5.13", - "@rsbuild/plugin-react": "1.4.2", - jsdom: "27.0.1", + "@rsbuild/core": repositoryPackage.devDependencies["@rsbuild/core"], + "@rsbuild/plugin-react": + repositoryPackage.devDependencies["@rsbuild/plugin-react"], react: versions[major], "react-dom": versions[major], "react-intersection-observer": `file:${tarballPath}`, @@ -70,46 +64,9 @@ try { ); await exec("corepack", ["pnpm", "install"], { cwd: packageDirectory }); - await exec("corepack", ["pnpm", "build"], { - cwd: packageDirectory, - env: { ...process.env, REACT_MAJOR: major }, - }); - - const scripts = ( - await readdir(join(packageDirectory, "dist", "static", "js")) - ).filter((file) => file.endsWith(".js")); - assert.equal(scripts.length, 1, "expected one built client bundle"); - const bundle = await readFile( - join(packageDirectory, "dist", "static", "js", scripts[0]), - "utf8", - ); - const jsdomErrors = []; - const virtualConsole = new VirtualConsole(); - virtualConsole.on("jsdomError", (error) => jsdomErrors.push(error)); - const dom = new JSDOM('
', { - runScripts: "dangerously", - url: "http://localhost/", - virtualConsole, - }); - dom.window.eval(bundle); - - for ( - let attempt = 0; - attempt < 100 && !dom.window.__COMPAT_RESULT__; - attempt++ - ) { - await new Promise((resolve) => setTimeout(resolve, 10)); - } - - assert.deepEqual(jsdomErrors, []); - const result = dom.window.__COMPAT_RESULT__; - assert.ok(result, "smoke test did not finish"); - assert.equal(result.diagnostics.length, 0, result.diagnostics.join("\n")); - assert.equal(result.observeCount, 4); - assert.equal(result.unobserveCount, 4); - dom.window.close(); + await exec("corepack", ["pnpm", "build"], { cwd: packageDirectory }); - console.log(`React ${major} packed compatibility passed`); + console.log(`React ${major} packed build passed`); } finally { await rm(temporaryRoot, { recursive: true, force: true }); } From 0d633131b7343a19385f13c2c950f5c07263cab8 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 14 Jul 2026 12:35:06 +0200 Subject: [PATCH 6/6] test: run packed harness as native TypeScript --- package.json | 2 +- scripts/compat/{packed.mjs => packed.mts} | 37 +++++++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) rename scripts/compat/{packed.mjs => packed.mts} (75%) diff --git a/package.json b/package.json index 5fbd2c1a..53ead3b6 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "scripts": { "prebuild": "rm -rf dist lib", "build": "tsup && mkdir dist/esm && cp dist/index.mjs dist/esm/index.js", - "compat:packed": "node scripts/compat/packed.mjs", + "compat:packed": "node scripts/compat/packed.mts", "postbuild": "attw --pack && publint && size-limit", "dev": "run-p dev:*", "dev:package": "tsup src/index.tsx --watch", diff --git a/scripts/compat/packed.mjs b/scripts/compat/packed.mts similarity index 75% rename from scripts/compat/packed.mjs rename to scripts/compat/packed.mts index 5c236063..c02e6c31 100644 --- a/scripts/compat/packed.mjs +++ b/scripts/compat/packed.mts @@ -5,6 +5,11 @@ import { basename, dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; +type RepositoryPackage = { + packageManager: string; + devDependencies: Record; +}; + const exec = promisify(execFile); const repositoryRoot = resolve( dirname(fileURLToPath(import.meta.url)), @@ -13,15 +18,22 @@ const repositoryRoot = resolve( const fixtureRoot = join(repositoryRoot, "fixtures/react-compat"); const repositoryPackage = JSON.parse( await readFile(join(repositoryRoot, "package.json"), "utf8"), -); +) as RepositoryPackage; const versions = { - 17: "17.0.2", - 18: "18.3.1", - 19: "19.2.3", -}; + "17": "17.0.2", + "18": "18.3.1", + "19": "19.2.3", +} as const; + +type ReactMajor = keyof typeof versions; + +function isReactMajor(value: string | undefined): value is ReactMajor { + return value !== undefined && value in versions; +} + const major = process.argv.slice(2).find((argument) => argument !== "--"); -if (!(major in versions)) { +if (!isReactMajor(major)) { throw new Error("Usage: pnpm run compat:packed -- 17|18|19"); } @@ -34,11 +46,16 @@ try { await mkdir(packDirectory); const { stdout } = await exec( - "corepack", - ["pnpm", "pack", "--pack-destination", packDirectory], + "pnpm", + ["pack", "--pack-destination", packDirectory], { cwd: repositoryRoot }, ); const tarballName = stdout.trim().split("\n").at(-1); + + if (!tarballName) { + throw new Error("pnpm pack did not return a tarball path"); + } + const tarballPath = join(packDirectory, basename(tarballName)); await writeFile( @@ -63,8 +80,8 @@ try { )}\n`, ); - await exec("corepack", ["pnpm", "install"], { cwd: packageDirectory }); - await exec("corepack", ["pnpm", "build"], { cwd: packageDirectory }); + await exec("pnpm", ["install"], { cwd: packageDirectory }); + await exec("pnpm", ["build"], { cwd: packageDirectory }); console.log(`React ${major} packed build passed`); } finally {