From 175996719511d1e990db9b87a9826ea3546124a4 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:14:02 +0000 Subject: [PATCH] fix(app): clamp virtualizer range to scroll bounds Co-authored-by: opencode-agent[bot] --- patches/@tanstack%2Fvirtual-core@3.17.0.patch | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/patches/@tanstack%2Fvirtual-core@3.17.0.patch b/patches/@tanstack%2Fvirtual-core@3.17.0.patch index 388f8855a532..58616e31e6f5 100644 --- a/patches/@tanstack%2Fvirtual-core@3.17.0.patch +++ b/patches/@tanstack%2Fvirtual-core@3.17.0.patch @@ -1,5 +1,5 @@ diff --git a/dist/cjs/index.cjs b/dist/cjs/index.cjs -index df75d0cf0347b62906e04e454d4f4ef062ed5c48..58913f2d30e0beee9d09dffa5ebcaab4601a2c22 100644 +index df75d0cf0347b62906e04e454d4f4ef062ed5c48..e5110715b049c6c8b992bd1375a7432df7c0182e 100644 --- a/dist/cjs/index.cjs +++ b/dist/cjs/index.cjs @@ -526,6 +526,7 @@ class Virtualizer { @@ -10,6 +10,20 @@ index df75d0cf0347b62906e04e454d4f4ef062ed5c48..58913f2d30e0beee9d09dffa5ebcaab4 this.getFurthestMeasurement = (measurements, index) => { const furthestMeasurementsFound = /* @__PURE__ */ new Map(); const furthestMeasurements = /* @__PURE__ */ new Map(); +@@ -715,10 +716,12 @@ class Virtualizer { + this.options.lanes + ], + (measurements, outerSize, scrollOffset, lanes) => { ++ const maxScrollOffset = Math.max(this.getTotalSize() - outerSize, 0); ++ const effectiveScrollOffset = Math.min(Math.max(scrollOffset, 0), maxScrollOffset); + return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({ + measurements, + outerSize, +- scrollOffset, ++ scrollOffset: effectiveScrollOffset, + lanes, + // Pass the typed array so binary search + forward-walk can + // read start/end directly from Float64Array, skipping the diff --git a/dist/cjs/index.d.cts b/dist/cjs/index.d.cts index c61ee17752565253f795c7fc7d57e86237ecbb52..705bb7e3a121b040fb1a3e7890179eaa3e9b219e 100644 --- a/dist/cjs/index.d.cts @@ -35,7 +49,7 @@ index b03abab604eb6578f6f56ff92c489259cfaf8f19..0495f372ea000dffc416c4f56809946f private _iosDeferredAdjustment; private _iosTouching; diff --git a/dist/esm/index.js b/dist/esm/index.js -index e384cf7541978a2782b9dca68146e869b16ac3f2..53b15b7a36247ea4aa5b70b00d08b6d7dec3ea79 100644 +index e384cf7541978a2782b9dca68146e869b16ac3f2..77af22006325377bf9ca0052a3554f881f9e75fe 100644 --- a/dist/esm/index.js +++ b/dist/esm/index.js @@ -524,6 +524,7 @@ class Virtualizer { @@ -46,13 +60,46 @@ index e384cf7541978a2782b9dca68146e869b16ac3f2..53b15b7a36247ea4aa5b70b00d08b6d7 this.getFurthestMeasurement = (measurements, index) => { const furthestMeasurementsFound = /* @__PURE__ */ new Map(); const furthestMeasurements = /* @__PURE__ */ new Map(); +@@ -713,10 +714,12 @@ class Virtualizer { + this.options.lanes + ], + (measurements, outerSize, scrollOffset, lanes) => { ++ const maxScrollOffset = Math.max(this.getTotalSize() - outerSize, 0); ++ const effectiveScrollOffset = Math.min(Math.max(scrollOffset, 0), maxScrollOffset); + return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({ + measurements, + outerSize, +- scrollOffset, ++ scrollOffset: effectiveScrollOffset, + lanes, + // Pass the typed array so binary search + forward-walk can + // read start/end directly from Float64Array, skipping the diff --git a/src/index.ts b/src/index.ts -index d35b3e0695a9c85b261bc1a4fbe23c0a60d5b204..d516a9d00f1233173f9a3e2144666c8159552f91 100644 +index d35b3e0695a9c85b261bc1a4fbe23c0a60d5b204..c504e630a60a3a7791345622bb02754b1308fd86 100644 --- a/src/index.ts +++ b/src/index.ts -@@ -1050,3 +1050,5 @@ export class Virtualizer< +@@ -1047,6 +1047,8 @@ export class Virtualizer< + return this.scrollOffset + } + + getLogicalScrollOffset = () => this.getScrollOffset() + this.scrollAdjustments + private getFurthestMeasurement = ( measurements: Array, index: number, +@@ -1334,12 +1336,14 @@ export class Virtualizer< + this.options.lanes, + ], + (measurements, outerSize, scrollOffset, lanes) => { ++ const maxScrollOffset = Math.max(this.getTotalSize() - outerSize, 0) ++ const effectiveScrollOffset = Math.min(Math.max(scrollOffset, 0), maxScrollOffset) + return (this.range = + measurements.length > 0 && outerSize > 0 + ? calculateRange({ + measurements, + outerSize, +- scrollOffset, ++ scrollOffset: effectiveScrollOffset, + lanes, + // Pass the typed array so binary search + forward-walk can + // read start/end directly from Float64Array, skipping the