diff --git a/benchmarks/CHANGELOG.md b/benchmarks/CHANGELOG.md index 2c773352..74c55e3d 100644 --- a/benchmarks/CHANGELOG.md +++ b/benchmarks/CHANGELOG.md @@ -1,5 +1,19 @@ # @tanstack/virtual-benchmarks +## 0.0.4 + +### Patch Changes + +- Updated dependencies []: + - @tanstack/react-virtual@3.14.1 + +## 0.0.3 + +### Patch Changes + +- Updated dependencies [[`73e115d`](https://github.com/TanStack/virtual/commit/73e115d53faf01f073bc4a7bd71ee0139307f4a8)]: + - @tanstack/react-virtual@3.14.0 + ## 0.0.2 ### Patch Changes diff --git a/benchmarks/package.json b/benchmarks/package.json index c900a764..1895185b 100644 --- a/benchmarks/package.json +++ b/benchmarks/package.json @@ -1,7 +1,7 @@ { "name": "@tanstack/virtual-benchmarks", "private": true, - "version": "0.0.2", + "version": "0.0.4", "type": "module", "scripts": { "dev": "vite", diff --git a/examples/angular/dynamic/package.json b/examples/angular/dynamic/package.json index 41e86f09..caf7ec62 100644 --- a/examples/angular/dynamic/package.json +++ b/examples/angular/dynamic/package.json @@ -18,7 +18,7 @@ "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "@faker-js/faker": "^8.4.1", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/fixed/package.json b/examples/angular/fixed/package.json index fc87e7b9..5791444f 100644 --- a/examples/angular/fixed/package.json +++ b/examples/angular/fixed/package.json @@ -17,7 +17,7 @@ "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/infinite-scroll/package.json b/examples/angular/infinite-scroll/package.json index ee094cae..35f1adcf 100644 --- a/examples/angular/infinite-scroll/package.json +++ b/examples/angular/infinite-scroll/package.json @@ -18,7 +18,7 @@ "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "@tanstack/angular-query-experimental": "5.80.7", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/padding/package.json b/examples/angular/padding/package.json index 53839b2f..189dde6f 100644 --- a/examples/angular/padding/package.json +++ b/examples/angular/padding/package.json @@ -17,7 +17,7 @@ "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/smooth-scroll/package.json b/examples/angular/smooth-scroll/package.json index 1539938d..b82d0077 100644 --- a/examples/angular/smooth-scroll/package.json +++ b/examples/angular/smooth-scroll/package.json @@ -17,7 +17,7 @@ "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/sticky/package.json b/examples/angular/sticky/package.json index 0bea4142..0683db65 100644 --- a/examples/angular/sticky/package.json +++ b/examples/angular/sticky/package.json @@ -18,7 +18,7 @@ "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "@faker-js/faker": "^8.4.1", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/table/package.json b/examples/angular/table/package.json index 89956c47..d035bcf1 100644 --- a/examples/angular/table/package.json +++ b/examples/angular/table/package.json @@ -19,7 +19,7 @@ "@angular/router": "^19.0.0", "@faker-js/faker": "^8.4.1", "@tanstack/angular-table": "8.21.3", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/variable/package.json b/examples/angular/variable/package.json index cadb1fdd..2959961d 100644 --- a/examples/angular/variable/package.json +++ b/examples/angular/variable/package.json @@ -17,7 +17,7 @@ "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/angular/window/package.json b/examples/angular/window/package.json index de71f556..8d3b461d 100644 --- a/examples/angular/window/package.json +++ b/examples/angular/window/package.json @@ -17,7 +17,7 @@ "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", - "@tanstack/angular-virtual": "^5.0.2", + "@tanstack/angular-virtual": "^5.0.3", "rxjs": "^7.8.2", "tslib": "^2.8.1", "zone.js": "0.15.1" diff --git a/examples/lit/dynamic/package.json b/examples/lit/dynamic/package.json index a9621671..1607f9f5 100644 --- a/examples/lit/dynamic/package.json +++ b/examples/lit/dynamic/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/lit-virtual": "^3.13.27", - "@tanstack/virtual-core": "^3.16.0", + "@tanstack/lit-virtual": "^3.13.28", + "@tanstack/virtual-core": "^3.16.1", "lit": "^3.3.0" }, "devDependencies": { diff --git a/examples/lit/fixed/package.json b/examples/lit/fixed/package.json index 40f02887..9b811565 100644 --- a/examples/lit/fixed/package.json +++ b/examples/lit/fixed/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/lit-virtual": "^3.13.27", - "@tanstack/virtual-core": "^3.16.0", + "@tanstack/lit-virtual": "^3.13.28", + "@tanstack/virtual-core": "^3.16.1", "lit": "^3.3.0" }, "devDependencies": { diff --git a/examples/react/chat/package.json b/examples/react/chat/package.json index b265f878..038026fe 100644 --- a/examples/react/chat/package.json +++ b/examples/react/chat/package.json @@ -8,7 +8,7 @@ "serve": "vite preview" }, "dependencies": { - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/chat/src/main.tsx b/examples/react/chat/src/main.tsx index 2f4d9a17..7329f8f2 100644 --- a/examples/react/chat/src/main.tsx +++ b/examples/react/chat/src/main.tsx @@ -43,11 +43,15 @@ function App() { count: messages.length, getScrollElement: () => parentRef.current, estimateSize: () => 74, - getItemKey: (index) => messages[index]!.id, + getItemKey: React.useCallback( + (index: number) => messages[index]!.id, + [messages], + ), anchorTo: 'end', followOnAppend: true, scrollEndThreshold: 80, overscan: 6, + directDomUpdates: true, }) const virtualItems = virtualizer.getVirtualItems() @@ -180,8 +184,8 @@ function App() { }} >
diff --git a/examples/react/dynamic/package.json b/examples/react/dynamic/package.json index 395d4b11..777846ab 100644 --- a/examples/react/dynamic/package.json +++ b/examples/react/dynamic/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/dynamic/src/main.tsx b/examples/react/dynamic/src/main.tsx index 1a0fe0ae..5e4b2b7e 100644 --- a/examples/react/dynamic/src/main.tsx +++ b/examples/react/dynamic/src/main.tsx @@ -24,14 +24,13 @@ function RowVirtualizerDynamic() { getScrollElement: () => parentRef.current, estimateSize: () => 45, enabled, + directDomUpdates: true, }) React.useEffect(() => { virtualizer.scrollToIndex(count - 1, { align: 'end' }) }, []) - const items = virtualizer.getVirtualItems() - return (
diff --git a/examples/react/fixed/package.json b/examples/react/fixed/package.json index 599d9409..5df29ada 100644 --- a/examples/react/fixed/package.json +++ b/examples/react/fixed/package.json @@ -8,7 +8,7 @@ "serve": "vite preview" }, "dependencies": { - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/infinite-scroll/package.json b/examples/react/infinite-scroll/package.json index c1c4bfd8..2fa5c762 100644 --- a/examples/react/infinite-scroll/package.json +++ b/examples/react/infinite-scroll/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@tanstack/react-query": "^5.80.7", - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/padding/package.json b/examples/react/padding/package.json index 2fd58799..e2afa43e 100644 --- a/examples/react/padding/package.json +++ b/examples/react/padding/package.json @@ -9,7 +9,7 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/pretext/package.json b/examples/react/pretext/package.json index 9e1dd5f5..e05b1db2 100644 --- a/examples/react/pretext/package.json +++ b/examples/react/pretext/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@chenglou/pretext": "^0.0.7", - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/scroll-padding/package.json b/examples/react/scroll-padding/package.json index e09bf120..809ef56d 100644 --- a/examples/react/scroll-padding/package.json +++ b/examples/react/scroll-padding/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@react-hookz/web": "^25.1.1", - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/smooth-scroll/package.json b/examples/react/smooth-scroll/package.json index acf85b83..37ade224 100644 --- a/examples/react/smooth-scroll/package.json +++ b/examples/react/smooth-scroll/package.json @@ -9,7 +9,7 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/sticky/package.json b/examples/react/sticky/package.json index ab1e4734..1581be9f 100644 --- a/examples/react/sticky/package.json +++ b/examples/react/sticky/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "lodash": "^4.17.21", "react": "^18.3.1", "react-dom": "^18.3.1" diff --git a/examples/react/table/package.json b/examples/react/table/package.json index 72e8dce5..d1f647a8 100644 --- a/examples/react/table/package.json +++ b/examples/react/table/package.json @@ -11,7 +11,7 @@ "dependencies": { "@faker-js/faker": "^8.4.1", "@tanstack/react-table": "^8.21.3", - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/variable/package.json b/examples/react/variable/package.json index d7027222..361bc8a6 100644 --- a/examples/react/variable/package.json +++ b/examples/react/variable/package.json @@ -9,7 +9,7 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/react/window/package.json b/examples/react/window/package.json index 27a602e5..7d36a7ff 100644 --- a/examples/react/window/package.json +++ b/examples/react/window/package.json @@ -8,7 +8,7 @@ "serve": "vite preview" }, "dependencies": { - "@tanstack/react-virtual": "^3.13.26", + "@tanstack/react-virtual": "^3.14.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/examples/svelte/dynamic/package.json b/examples/svelte/dynamic/package.json index a5a10cd2..ee8d4735 100644 --- a/examples/svelte/dynamic/package.json +++ b/examples/svelte/dynamic/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/svelte-virtual": "^3.13.26" + "@tanstack/svelte-virtual": "^3.13.27" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.2", diff --git a/examples/svelte/fixed/package.json b/examples/svelte/fixed/package.json index 27fe362d..71494152 100644 --- a/examples/svelte/fixed/package.json +++ b/examples/svelte/fixed/package.json @@ -9,7 +9,7 @@ "check": "svelte-check --tsconfig ./tsconfig.json" }, "dependencies": { - "@tanstack/svelte-virtual": "^3.13.26" + "@tanstack/svelte-virtual": "^3.13.27" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.2", diff --git a/examples/svelte/infinite-scroll/package.json b/examples/svelte/infinite-scroll/package.json index ecf02098..dd3bb309 100644 --- a/examples/svelte/infinite-scroll/package.json +++ b/examples/svelte/infinite-scroll/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@tanstack/svelte-query": "^5.80.7", - "@tanstack/svelte-virtual": "^3.13.26" + "@tanstack/svelte-virtual": "^3.13.27" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.2", diff --git a/examples/svelte/smooth-scroll/package.json b/examples/svelte/smooth-scroll/package.json index 64487f0a..8771bf56 100644 --- a/examples/svelte/smooth-scroll/package.json +++ b/examples/svelte/smooth-scroll/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/svelte-virtual": "^3.13.26" + "@tanstack/svelte-virtual": "^3.13.27" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.2", diff --git a/examples/svelte/sticky/package.json b/examples/svelte/sticky/package.json index 31e1682c..8f3c878c 100644 --- a/examples/svelte/sticky/package.json +++ b/examples/svelte/sticky/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/svelte-virtual": "^3.13.26", + "@tanstack/svelte-virtual": "^3.13.27", "lodash": "^4.17.21" }, "devDependencies": { diff --git a/examples/svelte/table/package.json b/examples/svelte/table/package.json index b84efcf1..063acfec 100644 --- a/examples/svelte/table/package.json +++ b/examples/svelte/table/package.json @@ -11,7 +11,7 @@ "dependencies": { "@faker-js/faker": "^8.4.1", "@tanstack/svelte-table": "^8.21.3", - "@tanstack/svelte-virtual": "^3.13.26" + "@tanstack/svelte-virtual": "^3.13.27" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.2", diff --git a/examples/vue/dynamic/package.json b/examples/vue/dynamic/package.json index bc9cf174..71c1282c 100644 --- a/examples/vue/dynamic/package.json +++ b/examples/vue/dynamic/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/examples/vue/fixed/package.json b/examples/vue/fixed/package.json index e15cafd2..781e646a 100644 --- a/examples/vue/fixed/package.json +++ b/examples/vue/fixed/package.json @@ -8,7 +8,7 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/examples/vue/infinite-scroll/package.json b/examples/vue/infinite-scroll/package.json index 7bdf6347..a7d6addc 100644 --- a/examples/vue/infinite-scroll/package.json +++ b/examples/vue/infinite-scroll/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@tanstack/vue-query": "^5.80.7", - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/examples/vue/padding/package.json b/examples/vue/padding/package.json index 9fb10414..97a5c987 100644 --- a/examples/vue/padding/package.json +++ b/examples/vue/padding/package.json @@ -8,7 +8,7 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/examples/vue/scroll-padding/package.json b/examples/vue/scroll-padding/package.json index 2389fb6c..375a97b0 100644 --- a/examples/vue/scroll-padding/package.json +++ b/examples/vue/scroll-padding/package.json @@ -8,7 +8,7 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "@vueuse/core": "^12.8.2", "vue": "^3.5.16" }, diff --git a/examples/vue/smooth-scroll/package.json b/examples/vue/smooth-scroll/package.json index ff740cf5..f533d980 100644 --- a/examples/vue/smooth-scroll/package.json +++ b/examples/vue/smooth-scroll/package.json @@ -8,7 +8,7 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/examples/vue/sticky/package.json b/examples/vue/sticky/package.json index 418a074c..ec478aba 100644 --- a/examples/vue/sticky/package.json +++ b/examples/vue/sticky/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "lodash": "^4.17.21", "vue": "^3.5.16" }, diff --git a/examples/vue/table/package.json b/examples/vue/table/package.json index c6d541b1..a7734453 100644 --- a/examples/vue/table/package.json +++ b/examples/vue/table/package.json @@ -10,7 +10,7 @@ "dependencies": { "@faker-js/faker": "^8.4.1", "@tanstack/vue-table": "^8.21.3", - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/examples/vue/variable/package.json b/examples/vue/variable/package.json index 384a4b49..13d81e6e 100644 --- a/examples/vue/variable/package.json +++ b/examples/vue/variable/package.json @@ -8,7 +8,7 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/vue-virtual": "^3.13.26", + "@tanstack/vue-virtual": "^3.13.27", "vue": "^3.5.16" }, "devDependencies": { diff --git a/packages/angular-virtual/CHANGELOG.md b/packages/angular-virtual/CHANGELOG.md index 4e96548e..e2f4f088 100644 --- a/packages/angular-virtual/CHANGELOG.md +++ b/packages/angular-virtual/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/angular-virtual +## 5.0.3 + +### Patch Changes + +- Updated dependencies [[`c746841`](https://github.com/TanStack/virtual/commit/c7468416354c203cd7cc952da5997073394224fb)]: + - @tanstack/virtual-core@3.16.1 + ## 5.0.2 ### Patch Changes diff --git a/packages/angular-virtual/package.json b/packages/angular-virtual/package.json index eac8041a..b6449b4e 100644 --- a/packages/angular-virtual/package.json +++ b/packages/angular-virtual/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/angular-virtual", - "version": "5.0.2", + "version": "5.0.3", "description": "Headless UI for virtualizing scrollable elements in Angular", "author": "Garrett Darnell", "license": "MIT", diff --git a/packages/lit-virtual/CHANGELOG.md b/packages/lit-virtual/CHANGELOG.md index af1dd376..0ad1acce 100644 --- a/packages/lit-virtual/CHANGELOG.md +++ b/packages/lit-virtual/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/lit-virtual +## 3.13.28 + +### Patch Changes + +- Updated dependencies [[`c746841`](https://github.com/TanStack/virtual/commit/c7468416354c203cd7cc952da5997073394224fb)]: + - @tanstack/virtual-core@3.16.1 + ## 3.13.27 ### Patch Changes diff --git a/packages/lit-virtual/package.json b/packages/lit-virtual/package.json index 9ef1d117..f5f399f3 100644 --- a/packages/lit-virtual/package.json +++ b/packages/lit-virtual/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/lit-virtual", - "version": "3.13.27", + "version": "3.13.28", "description": "Headless UI for virtualizing scrollable elements in Lit", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-virtual/CHANGELOG.md b/packages/react-virtual/CHANGELOG.md index 6371e7b6..c557b022 100644 --- a/packages/react-virtual/CHANGELOG.md +++ b/packages/react-virtual/CHANGELOG.md @@ -1,5 +1,18 @@ # @tanstack/react-virtual +## 3.14.1 + +### Patch Changes + +- Updated dependencies [[`c746841`](https://github.com/TanStack/virtual/commit/c7468416354c203cd7cc952da5997073394224fb)]: + - @tanstack/virtual-core@3.16.1 + +## 3.14.0 + +### Minor Changes + +- Add opt-in direct DOM updates for scroll positioning with `directDomUpdates`, `directDomUpdatesMode`, and `containerRef`. ([#1180](https://github.com/TanStack/virtual/pull/1180)) + ## 3.13.26 ### Patch Changes diff --git a/packages/react-virtual/e2e/app/direct-dom-updates/index.html b/packages/react-virtual/e2e/app/direct-dom-updates/index.html new file mode 100644 index 00000000..56f418f6 --- /dev/null +++ b/packages/react-virtual/e2e/app/direct-dom-updates/index.html @@ -0,0 +1,10 @@ + + + + + + +
+ + + diff --git a/packages/react-virtual/e2e/app/direct-dom-updates/main.tsx b/packages/react-virtual/e2e/app/direct-dom-updates/main.tsx new file mode 100644 index 00000000..e40673d1 --- /dev/null +++ b/packages/react-virtual/e2e/app/direct-dom-updates/main.tsx @@ -0,0 +1,70 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import { useVirtualizer } from '@tanstack/react-virtual' + +const ITEM_SIZE = 40 +const COUNT = 1000 + +const App = () => { + const parentRef = React.useRef(null) + + const params = new URLSearchParams(window.location.search) + const mode = (params.get('mode') ?? 'transform') as 'position' | 'transform' + + const renderCount = React.useRef(0) + renderCount.current += 1 + + const rowVirtualizer = useVirtualizer({ + count: COUNT, + getScrollElement: () => parentRef.current, + estimateSize: () => ITEM_SIZE, + overscan: 2, + directDomUpdates: true, + directDomUpdatesMode: mode, + }) + + return ( +
+
{renderCount.current}
+
{mode}
+ + +
+
+ {rowVirtualizer.getVirtualItems().map((v) => ( +
+ Row {v.index} +
+ ))} +
+
+
+ ) +} + +ReactDOM.createRoot(document.getElementById('root')!).render() diff --git a/packages/react-virtual/e2e/app/test/direct-dom-updates.spec.ts b/packages/react-virtual/e2e/app/test/direct-dom-updates.spec.ts new file mode 100644 index 00000000..c20c7050 --- /dev/null +++ b/packages/react-virtual/e2e/app/test/direct-dom-updates.spec.ts @@ -0,0 +1,93 @@ +import { expect, test } from '@playwright/test' + +const ITEM_SIZE = 40 +const COUNT = 1000 + +for (const mode of ['position', 'transform'] as const) { + test.describe(`directDomUpdates mode=${mode}`, () => { + test('sets container size and positions items via direct DOM updates', async ({ + page, + }) => { + await page.goto(`/direct-dom-updates/?mode=${mode}`) + + await expect(page.locator('[data-testid="mode"]')).toHaveText(mode) + + // Container height is written directly by containerRef, NOT from JSX style. + const inner = page.locator('#inner') + await expect(inner).toHaveAttribute( + 'style', + new RegExp(`height:\\s*${COUNT * ITEM_SIZE}px`), + ) + + // First item is at top 0 (position) or translate3d(0, 0, 0) (transform). + const first = page.locator('[data-testid="item-0"]') + await expect(first).toBeVisible() + if (mode === 'position') { + await expect(first).toHaveAttribute('style', /top:\s*0px/) + } else { + await expect(first).toHaveAttribute( + 'style', + /translate3d\(0px,\s*0px,\s*0px\)/, + ) + } + }) + + test('scrolling moves items via direct DOM without per-pixel React re-renders', async ({ + page, + }) => { + await page.goto(`/direct-dom-updates/?mode=${mode}`) + + const initialRenders = Number( + await page.locator('[data-testid="render-count"]').textContent(), + ) + + // Scroll by exactly one item — does NOT change the visible range + // (overscan absorbs it), so React should not re-render. + await page.locator('#scroll-container').evaluate((el, by) => { + el.scrollTop = by + }, ITEM_SIZE) + + const item1 = page.locator('[data-testid="item-1"]') + await expect(item1).toHaveAttribute( + 'style', + mode === 'position' + ? /top:\s*40px/ + : /translate3d\(0px,\s*40px,\s*0px\)/, + ) + + const renderAfterSmallScroll = Number( + await page.locator('[data-testid="render-count"]').textContent(), + ) + // Allow at most 1 extra render (isScrolling flip), zero for the offset itself. + expect(renderAfterSmallScroll - initialRenders).toBeLessThanOrEqual(2) + }) + + test('large scroll triggers a re-render and items still position correctly', async ({ + page, + }) => { + await page.goto(`/direct-dom-updates/?mode=${mode}`) + + const before = Number( + await page.locator('[data-testid="render-count"]').textContent(), + ) + + await page.click('#scroll-to-500') + + // Wait for the new range to render. + await expect(page.locator('[data-testid="item-500"]')).toBeVisible() + + const after = Number( + await page.locator('[data-testid="render-count"]').textContent(), + ) + expect(after).toBeGreaterThan(before) + + const item500 = page.locator('[data-testid="item-500"]') + const style = (await item500.getAttribute('style')) ?? '' + if (mode === 'position') { + expect(style).toMatch(/top:\s*20000px/) + } else { + expect(style).toMatch(/translate3d\(0px,\s*20000px,\s*0px\)/) + } + }) + }) +} diff --git a/packages/react-virtual/e2e/app/vite.config.ts b/packages/react-virtual/e2e/app/vite.config.ts index 964267f3..70a1602f 100644 --- a/packages/react-virtual/e2e/app/vite.config.ts +++ b/packages/react-virtual/e2e/app/vite.config.ts @@ -16,6 +16,10 @@ export default defineConfig({ ), 'smooth-scroll': path.resolve(__dirname, 'smooth-scroll/index.html'), 'stale-index': path.resolve(__dirname, 'stale-index/index.html'), + 'direct-dom-updates': path.resolve( + __dirname, + 'direct-dom-updates/index.html', + ), }, }, }, diff --git a/packages/react-virtual/package.json b/packages/react-virtual/package.json index 21411bbb..e358a2e8 100644 --- a/packages/react-virtual/package.json +++ b/packages/react-virtual/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-virtual", - "version": "3.13.26", + "version": "3.14.1", "description": "Headless UI for virtualizing scrollable elements in React", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-virtual/src/index.tsx b/packages/react-virtual/src/index.tsx index 89678ad6..ab39cb15 100644 --- a/packages/react-virtual/src/index.tsx +++ b/packages/react-virtual/src/index.tsx @@ -16,11 +16,57 @@ export * from '@tanstack/virtual-core' const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect +export type ReactVirtualizer< + TScrollElement extends Element | Window, + TItemElement extends Element, +> = Virtualizer & { + /** + * Ref callback for the inner sized container element. Only meaningful when + * `directDomUpdates: true` — the virtualizer writes the container's + * main-axis size (`height` or `width`) directly to skip React re-renders. + */ + containerRef: (node: HTMLElement | null) => void +} + export type ReactVirtualizerOptions< TScrollElement extends Element | Window, TItemElement extends Element, > = VirtualizerOptions & { useFlushSync?: boolean + /** + * Skip React re-renders for scroll-only updates. The virtualizer writes + * item positions (`top`/`left`) and the container size (`height`/`width`) + * directly to the DOM, and only re-renders when the visible index range + * or `isScrolling` changes. + * + * Requirements when enabled: + * - Item elements must be `position: absolute`; in `'transform'` mode they + * must also be anchored with `top: 0` / `left: 0`. + * - Item elements must NOT set the main-axis position in their style — the + * virtualizer owns `top` / `left` in `'position'` mode and `transform` in + * `'transform'` mode. + * - The inner sized container must receive `virtualizer.containerRef` and + * must NOT set `height` / `width` in its style. + * - For multi-lane layouts (grids / masonry), the cross-axis position + * (e.g. `left: ${(item.lane * 100) / lanes}%`) is stable per item and + * must still be set in your JSX — only the main axis is automated. + * + * This flag is intended to be set once at mount. Toggling it (or + * `directDomUpdatesMode`) at runtime can leave stale inline styles on + * items and the container. + */ + directDomUpdates?: boolean + /** + * How `directDomUpdates` positions item elements. + * - `'transform'` (default): writes `transform: translate3d(...)`. + * Promotes items to their own compositor layer — usually smoother on long + * lists, but creates a stacking context and can interfere with + * `position: fixed` descendants. Item elements must still be anchored with + * `position: absolute`, `top: 0`, and `left: 0`. + * - `'position'`: writes `top` / `left`. Item elements must be + * `position: absolute`. + */ + directDomUpdatesMode?: 'position' | 'transform' } function useVirtualizerBase< @@ -28,28 +74,129 @@ function useVirtualizerBase< TItemElement extends Element, >({ useFlushSync = true, + directDomUpdates = false, + directDomUpdatesMode = 'transform', ...options -}: ReactVirtualizerOptions): Virtualizer< +}: ReactVirtualizerOptions): ReactVirtualizer< TScrollElement, TItemElement > { const rerender = React.useReducer((x: number) => x + 1, 0)[1] + // Mutable across renders so the onChange closure captured by setOptions + // always reads the latest values without us having to re-create it. + const directRef = React.useRef({ + enabled: directDomUpdates, + mode: directDomUpdatesMode, + container: null as HTMLElement | null, + lastSize: null as number | null, + // Keyed by the element itself so a remounted node (same key, new DOM + // node — e.g. when `enabled` is toggled off then on) is treated as fresh + // and gets its style written. + lastPositions: new WeakMap(), + prevRange: null as { + startIndex: number + endIndex: number + isScrolling: boolean + } | null, + }) + directRef.current.enabled = directDomUpdates + directRef.current.mode = directDomUpdatesMode + + // Writes container size + item positions to the DOM. Idempotent — guarded + // by lastSize / lastPositions. Called from onChange (covers scroll-driven + // updates) and from a layout effect (covers post-render commits when refs + // have just registered new items in elementsCache). + const applyDirectStyles = ( + instance: Virtualizer, + ) => { + const state = directRef.current + if (!state.enabled) return + + const totalSize = instance.getTotalSize() + if (state.container && totalSize !== state.lastSize) { + state.lastSize = totalSize + const sizeAxis = instance.options.horizontal ? 'width' : 'height' + state.container.style[sizeAxis] = `${totalSize}px` + } + + const horizontal = !!instance.options.horizontal + const useTransform = state.mode === 'transform' + const posAxis = horizontal ? 'left' : 'top' + const scrollMargin = instance.options.scrollMargin + const items = instance.getVirtualItems() + for (const item of items) { + const next = item.start - scrollMargin + const el = instance.elementsCache.get(item.key) as HTMLElement | undefined + if (!el) continue + if (state.lastPositions.get(el) === next) continue + state.lastPositions.set(el, next) + if (useTransform) { + el.style.transform = horizontal + ? `translate3d(${next}px, 0, 0)` + : `translate3d(0, ${next}px, 0)` + } else { + el.style[posAxis] = `${next}px` + } + } + } + const resolvedOptions: VirtualizerOptions = { ...options, onChange: (instance, sync) => { - if (useFlushSync && sync) { - flushSync(rerender) - } else { - rerender() + const state = directRef.current + let shouldRerender = true + + if (state.enabled) { + applyDirectStyles(instance) + + // Only re-render on range / isScrolling changes + const range = instance.range + const prev = state.prevRange + shouldRerender = + !prev || + prev.isScrolling !== instance.isScrolling || + prev.startIndex !== range?.startIndex || + prev.endIndex !== range?.endIndex + if (shouldRerender) { + state.prevRange = range + ? { + startIndex: range.startIndex, + endIndex: range.endIndex, + isScrolling: instance.isScrolling, + } + : null + } + } + + if (shouldRerender) { + if (useFlushSync && sync) { + flushSync(rerender) + } else { + rerender() + } } + options.onChange?.(instance, sync) }, } - const [instance] = React.useState( - () => new Virtualizer(resolvedOptions), - ) + const [instance] = React.useState(() => { + const v = new Virtualizer(resolvedOptions) + return Object.assign(v, { + containerRef: (node: HTMLElement | null) => { + const state = directRef.current + state.container = node + state.lastSize = null + if (node && state.enabled) { + const total = v.getTotalSize() + state.lastSize = total + const axis = v.options.horizontal ? 'width' : 'height' + node.style[axis] = `${total}px` + } + }, + }) + }) instance.setOptions(resolvedOptions) @@ -61,6 +208,13 @@ function useVirtualizerBase< return instance._willUpdate() }) + // After every render commit, newly mounted item refs have registered in + // elementsCache; write their positions to the DOM so the user doesn't see + // them at (0, 0) until the next onChange. + useIsomorphicLayoutEffect(() => { + applyDirectStyles(instance) + }) + return instance } @@ -72,7 +226,7 @@ export function useVirtualizer< ReactVirtualizerOptions, 'observeElementRect' | 'observeElementOffset' | 'scrollToFn' >, -): Virtualizer { +): ReactVirtualizer { return useVirtualizerBase({ observeElementRect: observeElementRect, observeElementOffset: observeElementOffset, @@ -89,7 +243,7 @@ export function useWindowVirtualizer( | 'observeElementOffset' | 'scrollToFn' >, -): Virtualizer { +): ReactVirtualizer { return useVirtualizerBase({ getScrollElement: () => (typeof document !== 'undefined' ? window : null), observeElementRect: observeWindowRect, diff --git a/packages/solid-virtual/CHANGELOG.md b/packages/solid-virtual/CHANGELOG.md index 709e9dee..90f09761 100644 --- a/packages/solid-virtual/CHANGELOG.md +++ b/packages/solid-virtual/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/solid-virtual +## 3.13.27 + +### Patch Changes + +- Updated dependencies [[`c746841`](https://github.com/TanStack/virtual/commit/c7468416354c203cd7cc952da5997073394224fb)]: + - @tanstack/virtual-core@3.16.1 + ## 3.13.26 ### Patch Changes diff --git a/packages/solid-virtual/package.json b/packages/solid-virtual/package.json index 14082986..3fc2318f 100644 --- a/packages/solid-virtual/package.json +++ b/packages/solid-virtual/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-virtual", - "version": "3.13.26", + "version": "3.13.27", "description": "Headless UI for virtualizing scrollable elements in Solid", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/svelte-virtual/CHANGELOG.md b/packages/svelte-virtual/CHANGELOG.md index f52bee0c..5bc82c7d 100644 --- a/packages/svelte-virtual/CHANGELOG.md +++ b/packages/svelte-virtual/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/svelte-virtual +## 3.13.27 + +### Patch Changes + +- Updated dependencies [[`c746841`](https://github.com/TanStack/virtual/commit/c7468416354c203cd7cc952da5997073394224fb)]: + - @tanstack/virtual-core@3.16.1 + ## 3.13.26 ### Patch Changes diff --git a/packages/svelte-virtual/package.json b/packages/svelte-virtual/package.json index 3d74900a..031a4878 100644 --- a/packages/svelte-virtual/package.json +++ b/packages/svelte-virtual/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/svelte-virtual", - "version": "3.13.26", + "version": "3.13.27", "description": "Headless UI for virtualizing scrollable elements in Svelte", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/virtual-core/CHANGELOG.md b/packages/virtual-core/CHANGELOG.md index 569a0733..ef19da1f 100644 --- a/packages/virtual-core/CHANGELOG.md +++ b/packages/virtual-core/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/virtual-core +## 3.16.1 + +### Patch Changes + +- Eagerly adjust scrollOffset on prepend to prevent one-frame jump with anchorTo: 'end' ([#1176](https://github.com/TanStack/virtual/pull/1176)) + + When items are prepended with `anchorTo: 'end'` and dynamic sizes, the virtualizer would compute the wrong visible range for one frame (using stale estimate-based positions) and then correct in the next frame via `_willUpdate`, producing a visible jump. This fix eagerly adjusts `scrollOffset` in `setOptions` during the render pass so `calculateRange`/`getVirtualItems` return the correct items immediately. + ## 3.16.0 ### Minor Changes diff --git a/packages/virtual-core/package.json b/packages/virtual-core/package.json index fc9f4342..0529ac37 100644 --- a/packages/virtual-core/package.json +++ b/packages/virtual-core/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/virtual-core", - "version": "3.16.0", + "version": "3.16.1", "description": "Headless UI for virtualizing scrollable elements in TS/JS + Frameworks", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/virtual-core/src/index.ts b/packages/virtual-core/src/index.ts index 7890df33..29b36f99 100644 --- a/packages/virtual-core/src/index.ts +++ b/packages/virtual-core/src/index.ts @@ -365,6 +365,7 @@ type PendingScrollAnchor = [ key: Key | null, offset: number, followOnAppend: ScrollBehavior | null, + anchorDelta: number, ] export class Virtualizer< @@ -535,6 +536,7 @@ export class Virtualizer< | undefined let anchor: [Key, number] | null = null let followOnAppend: ScrollBehavior | null = null + let edgeKeysChanged = false if ( prevOptions !== undefined && @@ -564,6 +566,7 @@ export class Virtualizer< merged.getItemKey(nextCount - 1) !== prevLastKey)) if (didEdgeKeysChange) { + edgeKeysChanged = true const item = prevCount > 0 ? (this.getVirtualItemForOffset(this.getScrollOffset()) ?? @@ -592,11 +595,51 @@ export class Virtualizer< this.options = merged - if (anchor || followOnAppend) { + // When edge keys changed (prepend, trim, reorder, etc.) the key→index + // mapping has shifted. Force a full measurement rebuild so the anchor + // resolution below reads positions from the new layout, not the stale + // memoised cache. Without this, a stable `getItemKey` reference + + // unchanged `count` would let getMeasurements() return the old layout. + if (edgeKeysChanged) { + this.pendingMin = 0 + this.itemSizeCacheVersion++ + } + + // Eagerly adjust scrollOffset so the virtualizer computes the correct + // visible range during the current render pass — before _willUpdate + // syncs the DOM scroll position in a layout effect. Without this, + // the virtualizer would render the wrong items for one frame (the + // estimate-based positions are stale) and then correct in the next + // frame, producing a visible "jump" on prepend with dynamic sizes. + let anchorResolved = false + let anchorDelta = 0 + if (anchor && this.scrollOffset !== null) { + const [anchorKey, anchorOffset] = anchor + const newMeasurements = this.getMeasurements() + const { count, getItemKey } = this.options + let idx = 0 + while (idx < count && getItemKey(idx) !== anchorKey) { + idx++ + } + if (idx < count) { + const anchorItem = newMeasurements[idx] + if (anchorItem) { + const newOffset = anchorItem.start + anchorOffset + if (newOffset !== this.scrollOffset) { + anchorDelta = newOffset - this.scrollOffset + this.scrollOffset = newOffset + anchorResolved = true + } + } + } + } + + if (anchorResolved || followOnAppend) { this.pendingScrollAnchor = [ - anchor?.[0] ?? null, - anchor?.[1] ?? 0, + anchorResolved ? anchor![0] : null, + anchorResolved ? anchor![1] : 0, followOnAppend, + anchorDelta, ] } } @@ -798,22 +841,30 @@ export class Virtualizer< this.pendingScrollAnchor = null if (anchor && this.scrollElement && this.options.enabled) { - const [key, offset, followOnAppend] = anchor - - if (key !== null) { - const { count, getItemKey } = this.options - let index = 0 - while (index < count && getItemKey(index) !== key) { - index++ - } - - const item = index < count ? this.getMeasurements()[index] : undefined - if (item) { - const delta = item.start + offset - this.getScrollOffset() - - if (!approxEqual(delta, 0)) { - this.applyScrollAdjustment(delta) + const [key, _offset, followOnAppend, anchorDelta] = anchor + + if (key !== null && !followOnAppend) { + // scrollOffset was eagerly adjusted in setOptions so the + // virtualizer already computed the correct range during render. + // Now sync the browser's actual scroll position to match. + // Skip when followOnAppend is set — scrollToEnd will handle it. + // + // On iOS WebKit, writing scrollTop during touch/momentum cancels + // the in-flight scroll. Defer the DOM sync the same way + // applyScrollAdjustment does — accumulate the delta and let + // _flushIosDeferredIfReady handle it once the scroll settles. + if ( + isIOSWebKit() && + (this.isScrolling || this._iosTouching || this._iosJustTouchEnded) + ) { + if (anchorDelta !== 0) { + this._iosDeferredAdjustment += anchorDelta } + } else { + this._scrollToOffset(this.getScrollOffset(), { + adjustments: undefined, + behavior: undefined, + }) } } diff --git a/packages/virtual-core/tests/index.test.ts b/packages/virtual-core/tests/index.test.ts index e57119a1..0dc72977 100644 --- a/packages/virtual-core/tests/index.test.ts +++ b/packages/virtual-core/tests/index.test.ts @@ -2275,8 +2275,8 @@ test('anchorTo:end keeps visible content stable when older items are prepended', expect(scrollToFn).toHaveBeenCalledTimes(1) const [offset, options] = scrollToFn.mock.calls[0]! - expect(offset).toBe(100) - expect(options.adjustments).toBe(100) + expect(offset).toBe(200) + expect(options.adjustments).toBeUndefined() }) test('anchorTo:end does not yank a scrolled-up user when items append', () => { diff --git a/packages/vue-virtual/CHANGELOG.md b/packages/vue-virtual/CHANGELOG.md index 45229076..4cbe050b 100644 --- a/packages/vue-virtual/CHANGELOG.md +++ b/packages/vue-virtual/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/vue-virtual +## 3.13.27 + +### Patch Changes + +- Updated dependencies [[`c746841`](https://github.com/TanStack/virtual/commit/c7468416354c203cd7cc952da5997073394224fb)]: + - @tanstack/virtual-core@3.16.1 + ## 3.13.26 ### Patch Changes diff --git a/packages/vue-virtual/package.json b/packages/vue-virtual/package.json index d16e3d51..250545b9 100644 --- a/packages/vue-virtual/package.json +++ b/packages/vue-virtual/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/vue-virtual", - "version": "3.13.26", + "version": "3.13.27", "description": "Headless UI for virtualizing scrollable elements in Vue", "author": "Tanner Linsley", "license": "MIT", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 28e50fe8..d43e2cfc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -142,7 +142,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -194,7 +194,7 @@ importers: specifier: ^19.0.0 version: 19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.20(@angular/animations@19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -249,7 +249,7 @@ importers: specifier: 5.80.7 version: 5.80.7(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -301,7 +301,7 @@ importers: specifier: ^19.0.0 version: 19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.20(@angular/animations@19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -353,7 +353,7 @@ importers: specifier: ^19.0.0 version: 19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.20(@angular/animations@19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -408,7 +408,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -466,7 +466,7 @@ importers: specifier: 8.21.3 version: 8.21.3(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -518,7 +518,7 @@ importers: specifier: ^19.0.0 version: 19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.20(@angular/animations@19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -570,7 +570,7 @@ importers: specifier: ^19.0.0 version: 19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@19.2.20(@angular/animations@19.2.20(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@19.2.20(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@19.2.20(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@tanstack/angular-virtual': - specifier: ^5.0.2 + specifier: ^5.0.3 version: link:../../../packages/angular-virtual rxjs: specifier: ^7.8.2 @@ -601,10 +601,10 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/lit-virtual': - specifier: ^3.13.27 + specifier: ^3.13.28 version: link:../../../packages/lit-virtual '@tanstack/virtual-core': - specifier: ^3.16.0 + specifier: ^3.16.1 version: link:../../../packages/virtual-core lit: specifier: ^3.3.0 @@ -626,10 +626,10 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/lit-virtual': - specifier: ^3.13.27 + specifier: ^3.13.28 version: link:../../../packages/lit-virtual '@tanstack/virtual-core': - specifier: ^3.16.0 + specifier: ^3.16.1 version: link:../../../packages/virtual-core lit: specifier: ^3.3.0 @@ -648,7 +648,7 @@ importers: examples/react/chat: dependencies: '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -679,7 +679,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -710,7 +710,7 @@ importers: examples/react/fixed: dependencies: '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -744,7 +744,7 @@ importers: specifier: ^5.80.7 version: 5.90.5(react@18.3.1) '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -769,7 +769,7 @@ importers: examples/react/padding: dependencies: '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -797,7 +797,7 @@ importers: specifier: ^0.0.7 version: 0.0.7 '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -831,7 +831,7 @@ importers: specifier: ^25.1.1 version: 25.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -856,7 +856,7 @@ importers: examples/react/smooth-scroll: dependencies: '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -884,7 +884,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual lodash: specifier: ^4.17.21 @@ -921,7 +921,7 @@ importers: specifier: ^8.21.3 version: 8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -946,7 +946,7 @@ importers: examples/react/variable: dependencies: '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -971,7 +971,7 @@ importers: examples/react/window: dependencies: '@tanstack/react-virtual': - specifier: ^3.13.26 + specifier: ^3.14.1 version: link:../../../packages/react-virtual react: specifier: ^18.3.1 @@ -1005,7 +1005,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/svelte-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/svelte-virtual devDependencies: '@sveltejs/vite-plugin-svelte': @@ -1033,7 +1033,7 @@ importers: examples/svelte/fixed: dependencies: '@tanstack/svelte-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/svelte-virtual devDependencies: '@sveltejs/vite-plugin-svelte': @@ -1064,7 +1064,7 @@ importers: specifier: ^5.80.7 version: 5.90.2(svelte@4.2.20) '@tanstack/svelte-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/svelte-virtual devDependencies: '@sveltejs/vite-plugin-svelte': @@ -1095,7 +1095,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/svelte-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/svelte-virtual devDependencies: '@sveltejs/vite-plugin-svelte': @@ -1126,7 +1126,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/svelte-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/svelte-virtual lodash: specifier: ^4.17.21 @@ -1163,7 +1163,7 @@ importers: specifier: ^8.21.3 version: 8.21.3(svelte@4.2.20) '@tanstack/svelte-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/svelte-virtual devDependencies: '@sveltejs/vite-plugin-svelte': @@ -1194,7 +1194,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16 @@ -1219,7 +1219,7 @@ importers: examples/vue/fixed: dependencies: '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16 @@ -1247,7 +1247,7 @@ importers: specifier: ^5.80.7 version: 5.90.5(vue@3.5.22(typescript@5.6.3)) '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16 @@ -1272,7 +1272,7 @@ importers: examples/vue/padding: dependencies: '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16 @@ -1297,7 +1297,7 @@ importers: examples/vue/scroll-padding: dependencies: '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual '@vueuse/core': specifier: ^12.8.2 @@ -1325,7 +1325,7 @@ importers: examples/vue/smooth-scroll: dependencies: '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16 @@ -1353,7 +1353,7 @@ importers: specifier: ^8.4.1 version: 8.4.1 '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual lodash: specifier: ^4.17.21 @@ -1390,7 +1390,7 @@ importers: specifier: ^8.21.3 version: 8.21.3(vue@3.5.22(typescript@5.6.3)) '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16 @@ -1415,7 +1415,7 @@ importers: examples/vue/variable: dependencies: '@tanstack/vue-virtual': - specifier: ^3.13.26 + specifier: ^3.13.27 version: link:../../../packages/vue-virtual vue: specifier: ^3.5.16