diff --git a/bun.lock b/bun.lock index c78211b4604..b51a75a3baf 100644 --- a/bun.lock +++ b/bun.lock @@ -917,6 +917,7 @@ "@tanstack/solid-virtual@3.13.28": "patches/@tanstack%2Fsolid-virtual@3.13.28.patch", "@ai-sdk/xai@3.0.82": "patches/@ai-sdk%2Fxai@3.0.82.patch", "pacote@21.5.0": "patches/pacote@21.5.0.patch", + "@tanstack/virtual-core@3.17.0": "patches/@tanstack%2Fvirtual-core@3.17.0.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", diff --git a/package.json b/package.json index e59dff3211c..b1301309542 100644 --- a/package.json +++ b/package.json @@ -151,6 +151,7 @@ "pacote@21.5.0": "patches/pacote@21.5.0.patch", "@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch", "@tanstack/solid-virtual@3.13.28": "patches/@tanstack%2Fsolid-virtual@3.13.28.patch", - "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch" + "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", + "@tanstack/virtual-core@3.17.0": "patches/@tanstack%2Fvirtual-core@3.17.0.patch" } } diff --git a/packages/app/src/pages/session/timeline/message-timeline.tsx b/packages/app/src/pages/session/timeline/message-timeline.tsx index f684c43e7c4..acf22ef226d 100644 --- a/packages/app/src/pages/session/timeline/message-timeline.tsx +++ b/packages/app/src/pages/session/timeline/message-timeline.tsx @@ -473,7 +473,7 @@ export function MessageTimeline(props: { resizeItem(index, size) } virtualizer.shouldAdjustScrollPositionOnItemSizeChange = (item, _delta, instance) => - item.end <= (instance.scrollOffset ?? 0) + item.end <= instance.getLogicalScrollOffset() const virtualItemByKey = createMemo( () => new Map(virtualizer.getVirtualItems().map((item) => [item.key, item] as const)), ) diff --git a/packages/app/test-browser/solid-virtual.test.ts b/packages/app/test-browser/solid-virtual.test.ts index 01e2e6f7495..445fc799cbc 100644 --- a/packages/app/test-browser/solid-virtual.test.ts +++ b/packages/app/test-browser/solid-virtual.test.ts @@ -25,3 +25,22 @@ test("reactive count updates preserve measured row sizes", () => { dispose() }) }) + +test("logical scroll offset includes pending measurement adjustments", () => { + createRoot((dispose) => { + const virtualizer = createVirtualizer({ + count: 2, + getScrollElement: () => null, + estimateSize: () => 60, + initialOffset: 100, + initialRect: { width: 800, height: 60 }, + }) + + virtualizer.getTotalSize() + virtualizer.resizeItem(0, 100) + + expect(virtualizer.scrollOffset).toBe(100) + expect(virtualizer.getLogicalScrollOffset()).toBe(140) + dispose() + }) +}) diff --git a/patches/@tanstack%2Fvirtual-core@3.17.0.patch b/patches/@tanstack%2Fvirtual-core@3.17.0.patch new file mode 100644 index 00000000000..3034007c1da --- /dev/null +++ b/patches/@tanstack%2Fvirtual-core@3.17.0.patch @@ -0,0 +1,61 @@ +diff --git a/dist/cjs/index.cjs b/dist/cjs/index.cjs +index df75d0cf0347b62906e04e454d4f4ef062ed5c48..58913f2d30e0beee9d09dffa5ebcaab4601a2c22 100644 +--- a/dist/cjs/index.cjs ++++ b/dist/cjs/index.cjs +@@ -526,6 +526,7 @@ class Virtualizer { + this.scrollOffset = this.scrollOffset ?? (typeof this.options.initialOffset === "function" ? this.options.initialOffset() : this.options.initialOffset); + return this.scrollOffset; + }; ++ this.getLogicalScrollOffset = () => this.getScrollOffset() + this.scrollAdjustments; + this.getFurthestMeasurement = (measurements, index) => { + const furthestMeasurementsFound = /* @__PURE__ */ new Map(); + const furthestMeasurements = /* @__PURE__ */ new Map(); +diff --git a/dist/cjs/index.d.cts b/dist/cjs/index.d.cts +index c61ee17752565253f795c7fc7d57e86237ecbb52..705bb7e3a121b040fb1a3e7890179eaa3e9b219e 100644 +--- a/dist/cjs/index.d.cts ++++ b/dist/cjs/index.d.cts +@@ -108,6 +108,7 @@ export declare class Virtualizer number; + private scrollAdjustments; + private _iosDeferredAdjustment; + private _iosTouching; +diff --git a/dist/esm/index.d.ts b/dist/esm/index.d.ts +index b03abab604eb6578f6f56ff92c489259cfaf8f19..0495f372ea000dffc416c4f56809946f7ba73099 100644 +--- a/dist/esm/index.d.ts ++++ b/dist/esm/index.d.ts +@@ -108,6 +108,7 @@ export declare class Virtualizer number; + private scrollAdjustments; + private _iosDeferredAdjustment; + private _iosTouching; +diff --git a/dist/esm/index.js b/dist/esm/index.js +index e384cf7541978a2782b9dca68146e869b16ac3f2..53b15b7a36247ea4aa5b70b00d08b6d7dec3ea79 100644 +--- a/dist/esm/index.js ++++ b/dist/esm/index.js +@@ -524,6 +524,7 @@ class Virtualizer { + this.scrollOffset = this.scrollOffset ?? (typeof this.options.initialOffset === "function" ? this.options.initialOffset() : this.options.initialOffset); + return this.scrollOffset; + }; ++ this.getLogicalScrollOffset = () => this.getScrollOffset() + this.scrollAdjustments; + this.getFurthestMeasurement = (measurements, index) => { + const furthestMeasurementsFound = /* @__PURE__ */ new Map(); + const furthestMeasurements = /* @__PURE__ */ new Map(); +diff --git a/src/index.ts b/src/index.ts +index d35b3e0695a9c85b261bc1a4fbe23c0a60d5b204..d516a9d00f1233173f9a3e2144666c8159552f91 100644 +--- a/src/index.ts ++++ b/src/index.ts +@@ -1047,6 +1047,8 @@ export class Virtualizer< + return this.scrollOffset + } + ++ getLogicalScrollOffset = () => this.getScrollOffset() + this.scrollAdjustments ++ + private getFurthestMeasurement = ( + measurements: Array, + index: number,