Fix Combobox issue when using virtual mode (#3734)

This PR fixes an issue with the `Combobox` component when using the
`virtual` mode.

We recently already fixed this issue
(https://github.com/tailwindlabs/headlessui/pull/3678) by applying a
patch on the `@tanstack/virtual-core` package. But this was only applied
in cjs builds, not in the esm builds.

Instead of trying to fix it in our build process, we decided to just fix
it upstream (https://github.com/TanStack/virtual/pull/1004) and this PR
bumps the version of `@tanstack/virtual-core` to the latest version
(which includes the fix).
This commit is contained in:
Robin Malfait
2025-05-20 16:11:26 +02:00
committed by GitHub
parent 8a24040316
commit d689bbc64f
5 changed files with 22 additions and 319 deletions
+17 -264
View File
@@ -7,7 +7,6 @@
"": { "": {
"name": "headlessui", "name": "headlessui",
"version": "0.0.0", "version": "0.0.0",
"hasInstallScript": true,
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"packages/*", "packages/*",
@@ -26,7 +25,6 @@
"jest": "26", "jest": "26",
"lint-staged": "^12.2.1", "lint-staged": "^12.2.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"patch-package": "^8.0.0",
"prettier": "^3.1.0", "prettier": "^3.1.0",
"prettier-plugin-organize-imports": "^3.2.4", "prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-tailwindcss": "^0.6.11", "prettier-plugin-tailwindcss": "^0.6.11",
@@ -2728,12 +2726,12 @@
} }
}, },
"node_modules/@tanstack/react-virtual": { "node_modules/@tanstack/react-virtual": {
"version": "3.13.6", "version": "3.13.9",
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.6.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.9.tgz",
"integrity": "sha512-WT7nWs8ximoQ0CDx/ngoFP7HbQF9Q2wQe4nh2NB+u2486eX3nZRE40P9g6ccCVq7ZfTSH5gFOuCoVH5DLNS/aA==", "integrity": "sha512-SPWC8kwG/dWBf7Py7cfheAPOxuvIv4fFQ54PdmYbg7CpXfsKxkucak43Q0qKsxVthhUJQ1A7CIMAIplq4BjVwA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tanstack/virtual-core": "3.13.6" "@tanstack/virtual-core": "3.13.9"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
@@ -2744,6 +2742,16 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/@tanstack/react-virtual/node_modules/@tanstack/virtual-core": {
"version": "3.13.9",
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.9.tgz",
"integrity": "sha512-3jztt0jpaoJO5TARe2WIHC1UQC3VMLAFUW5mmMo0yrkwtDB2AQP0+sh10BVUpWrnvHjSLvzFizydtEGLCJKFoQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/virtual-core": { "node_modules/@tanstack/virtual-core": {
"version": "3.13.6", "version": "3.13.6",
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.6.tgz", "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.6.tgz",
@@ -3435,13 +3443,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
"dev": true,
"license": "BSD-2-Clause"
},
"node_modules/abab": { "node_modules/abab": {
"version": "2.0.6", "version": "2.0.6",
"dev": true, "dev": true,
@@ -3687,16 +3688,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/atob": { "node_modules/atob": {
"version": "2.1.2", "version": "2.1.2",
"dev": true, "dev": true,
@@ -4010,23 +4001,6 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"dev": true, "dev": true,
@@ -5584,16 +5558,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/find-yarn-workspace-root": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"micromatch": "^4.0.2"
}
},
"node_modules/flatpickr": { "node_modules/flatpickr": {
"version": "4.6.13", "version": "4.6.13",
"license": "MIT" "license": "MIT"
@@ -5688,32 +5652,6 @@
"tslib": "^2.1.0" "tslib": "^2.1.0"
} }
}, },
"node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/fs-extra/node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"dev": true, "dev": true,
@@ -6415,6 +6353,7 @@
"version": "2.2.1", "version": "2.2.1",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optional": true,
"bin": { "bin": {
"is-docker": "cli.js" "is-docker": "cli.js"
}, },
@@ -6660,6 +6599,7 @@
"version": "2.2.0", "version": "2.2.0",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optional": true,
"dependencies": { "dependencies": {
"is-docker": "^2.0.0" "is-docker": "^2.0.0"
}, },
@@ -7576,26 +7516,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/json-stable-stringify": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.2.1.tgz",
"integrity": "sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
"isarray": "^2.0.5",
"jsonify": "^0.0.1",
"object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/json5": { "node_modules/json5": {
"version": "2.2.3", "version": "2.2.3",
"dev": true, "dev": true,
@@ -7612,39 +7532,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/jsonfile/node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/jsonify": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
"integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
"dev": true,
"license": "Public Domain",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/kind-of": { "node_modules/kind-of": {
"version": "3.2.2", "version": "3.2.2",
"dev": true, "dev": true,
@@ -7656,16 +7543,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/klaw-sync": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.1.11"
}
},
"node_modules/kleur": { "node_modules/kleur": {
"version": "3.0.3", "version": "3.0.3",
"dev": true, "dev": true,
@@ -8990,23 +8867,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/opencollective-postinstall": { "node_modules/opencollective-postinstall": {
"version": "2.0.3", "version": "2.0.3",
"dev": true, "dev": true,
@@ -9015,16 +8875,6 @@
"opencollective-postinstall": "index.js" "opencollective-postinstall": "index.js"
} }
}, },
"node_modules/os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/p-each-series": { "node_modules/p-each-series": {
"version": "2.2.0", "version": "2.2.0",
"dev": true, "dev": true,
@@ -9132,90 +8982,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/patch-package": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz",
"integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@yarnpkg/lockfile": "^1.1.0",
"chalk": "^4.1.2",
"ci-info": "^3.7.0",
"cross-spawn": "^7.0.3",
"find-yarn-workspace-root": "^2.0.0",
"fs-extra": "^9.0.0",
"json-stable-stringify": "^1.0.2",
"klaw-sync": "^6.0.0",
"minimist": "^1.2.6",
"open": "^7.4.2",
"rimraf": "^2.6.3",
"semver": "^7.5.3",
"slash": "^2.0.0",
"tmp": "^0.0.33",
"yaml": "^2.2.2"
},
"bin": {
"patch-package": "index.js"
},
"engines": {
"node": ">=14",
"npm": ">5"
}
},
"node_modules/patch-package/node_modules/ci-info": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/sibiraj-s"
}
],
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/patch-package/node_modules/rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/patch-package/node_modules/slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/patch-package/node_modules/yaml": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
"integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
"dev": true,
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/path-exists": { "node_modules/path-exists": {
"version": "4.0.0", "version": "4.0.0",
"dev": true, "dev": true,
@@ -11696,19 +11462,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"dev": true,
"license": "MIT",
"dependencies": {
"os-tmpdir": "~1.0.2"
},
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/tmpl": { "node_modules/tmpl": {
"version": "1.0.5", "version": "1.0.5",
"dev": true, "dev": true,
@@ -12543,7 +12296,7 @@
"@floating-ui/react": "^0.26.16", "@floating-ui/react": "^0.26.16",
"@react-aria/focus": "^3.20.2", "@react-aria/focus": "^3.20.2",
"@react-aria/interactions": "^3.25.0", "@react-aria/interactions": "^3.25.0",
"@tanstack/react-virtual": "^3.13.6", "@tanstack/react-virtual": "^3.13.9",
"use-sync-external-store": "^1.5.0" "use-sync-external-store": "^1.5.0"
}, },
"devDependencies": { "devDependencies": {
+1 -3
View File
@@ -25,8 +25,7 @@
"lint-types": "CI=true npm run lint-types --workspaces --if-present", "lint-types": "CI=true npm run lint-types --workspaces --if-present",
"release-channel": "node ./scripts/release-channel.js", "release-channel": "node ./scripts/release-channel.js",
"release-notes": "node ./scripts/release-notes.js", "release-notes": "node ./scripts/release-notes.js",
"package-path": "node ./scripts/package-path.js", "package-path": "node ./scripts/package-path.js"
"postinstall": "patch-package"
}, },
"husky": { "husky": {
"hooks": { "hooks": {
@@ -77,7 +76,6 @@
"jest": "26", "jest": "26",
"lint-staged": "^12.2.1", "lint-staged": "^12.2.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"patch-package": "^8.0.0",
"prettier": "^3.1.0", "prettier": "^3.1.0",
"prettier-plugin-organize-imports": "^3.2.4", "prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-tailwindcss": "^0.6.11", "prettier-plugin-tailwindcss": "^0.6.11",
+1 -1
View File
@@ -59,7 +59,7 @@
"@floating-ui/react": "^0.26.16", "@floating-ui/react": "^0.26.16",
"@react-aria/focus": "^3.20.2", "@react-aria/focus": "^3.20.2",
"@react-aria/interactions": "^3.25.0", "@react-aria/interactions": "^3.25.0",
"@tanstack/react-virtual": "^3.13.6", "@tanstack/react-virtual": "^3.13.9",
"use-sync-external-store": "^1.5.0" "use-sync-external-store": "^1.5.0"
} }
} }
@@ -67,6 +67,9 @@ jest.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(() =>
toJSON: () => {}, toJSON: () => {},
})) }))
jest.spyOn(HTMLElement.prototype, 'offsetWidth', 'get').mockReturnValue(100)
jest.spyOn(HTMLElement.prototype, 'offsetHeight', 'get').mockReturnValue(40)
beforeAll(() => { beforeAll(() => {
jest.spyOn(window, 'requestAnimationFrame').mockImplementation(setImmediate as any) jest.spyOn(window, 'requestAnimationFrame').mockImplementation(setImmediate as any)
jest.spyOn(window, 'cancelAnimationFrame').mockImplementation(clearImmediate as any) jest.spyOn(window, 'cancelAnimationFrame').mockImplementation(clearImmediate as any)
@@ -1,51 +0,0 @@
diff --git a/node_modules/@tanstack/virtual-core/dist/cjs/index.cjs b/node_modules/@tanstack/virtual-core/dist/cjs/index.cjs
index dd4e77f..127987e 100644
--- a/node_modules/@tanstack/virtual-core/dist/cjs/index.cjs
+++ b/node_modules/@tanstack/virtual-core/dist/cjs/index.cjs
@@ -665,9 +665,9 @@ class Virtualizer {
this.options.getItemKey(index)
);
if (elementInDOM) {
- const [latestOffset] = utils.notUndefined(
- this.getOffsetForIndex(index, align)
- );
+ const result = this.getOffsetForIndex(index, align)
+ if (!result) return
+ const [latestOffset] = result
if (!utils.approxEqual(latestOffset, this.getScrollOffset())) {
this.scrollToIndex(index, { align, behavior });
}
diff --git a/node_modules/@tanstack/virtual-core/dist/esm/index.js b/node_modules/@tanstack/virtual-core/dist/esm/index.js
index 8da519d..8c78af8 100644
--- a/node_modules/@tanstack/virtual-core/dist/esm/index.js
+++ b/node_modules/@tanstack/virtual-core/dist/esm/index.js
@@ -663,9 +663,9 @@ class Virtualizer {
this.options.getItemKey(index)
);
if (elementInDOM) {
- const [latestOffset] = notUndefined(
- this.getOffsetForIndex(index, align)
- );
+ const result = this.getOffsetForIndex(index, align)
+ if (!result) return
+ const [latestOffset] = result
if (!approxEqual(latestOffset, this.getScrollOffset())) {
this.scrollToIndex(index, { align, behavior });
}
diff --git a/node_modules/@tanstack/virtual-core/src/index.ts b/node_modules/@tanstack/virtual-core/src/index.ts
index 3a0c446..4a9e792 100644
--- a/node_modules/@tanstack/virtual-core/src/index.ts
+++ b/node_modules/@tanstack/virtual-core/src/index.ts
@@ -1003,9 +1003,9 @@ export class Virtualizer<
)
if (elementInDOM) {
- const [latestOffset] = notUndefined(
- this.getOffsetForIndex(index, align),
- )
+ const result = this.getOffsetForIndex(index, align)
+ if (!result) return
+ const [latestOffset] = result
if (!approxEqual(latestOffset, this.getScrollOffset())) {
this.scrollToIndex(index, { align, behavior })