Skip to content

Commit 35c88c3

Browse files
authored
fix(app): preserve timeline bottom anchoring (anomalyco#36160)
1 parent b5e0902 commit 35c88c3

6 files changed

Lines changed: 167 additions & 184 deletions

File tree

bun.lock

Lines changed: 13 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"@opentui/core": "0.4.3",
4444
"@opentui/keymap": "0.4.3",
4545
"@opentui/solid": "0.4.3",
46-
"@tanstack/solid-virtual": "3.13.28",
46+
"@tanstack/solid-virtual": "3.13.32",
4747
"@shikijs/stream": "4.2.0",
4848
"ulid": "3.0.1",
4949
"@kobalte/core": "0.13.11",
@@ -152,10 +152,9 @@
152152
"gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch",
153153
"pacote@21.5.0": "patches/pacote@21.5.0.patch",
154154
"@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch",
155-
"@tanstack/solid-virtual@3.13.28": "patches/@tanstack%2Fsolid-virtual@3.13.28.patch",
156155
"@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch",
157156
"@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch",
158-
"@tanstack/virtual-core@3.17.0": "patches/@tanstack%2Fvirtual-core@3.17.0.patch",
159-
"effect@4.0.0-beta.83": "patches/effect@4.0.0-beta.83.patch"
157+
"effect@4.0.0-beta.83": "patches/effect@4.0.0-beta.83.patch",
158+
"@tanstack/virtual-core@3.17.3": "patches/@tanstack%2Fvirtual-core@3.17.3.patch"
160159
}
161160
}

packages/app/test-browser/solid-virtual.test.ts

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
import { expect, test } from "bun:test"
2-
import { createVirtualizer, defaultRangeExtractor } from "@tanstack/solid-virtual"
2+
import { createVirtualizer, defaultRangeExtractor, Virtualizer } from "@tanstack/solid-virtual"
33
import { createRoot, createSignal } from "solid-js"
44
import { filterVirtualIndexes } from "@/pages/session/timeline/virtual-items"
55

6+
test("end anchoring survives consecutive resizes when the first scroll write is clamped", () => {
7+
const writes: { offset: number; adjustments?: number }[] = []
8+
const virtualizer = new Virtualizer<HTMLDivElement, HTMLDivElement>({
9+
count: 5,
10+
estimateSize: () => 50,
11+
initialOffset: 50,
12+
initialRect: { width: 400, height: 200 },
13+
anchorTo: "end",
14+
scrollEndThreshold: 1,
15+
getScrollElement: () => null,
16+
scrollToFn: (offset, options) => writes.push({ offset, adjustments: options.adjustments }),
17+
observeElementRect: () => {},
18+
observeElementOffset: () => {},
19+
})
20+
21+
virtualizer.getTotalSize()
22+
virtualizer.resizeItem(4, 120)
23+
expect(writes).toEqual([{ offset: 50, adjustments: 70 }])
24+
writes.length = 0
25+
26+
virtualizer.resizeItem(4, 200)
27+
expect(writes).toEqual([{ offset: 120, adjustments: 80 }])
28+
})
29+
630
test("reactive count updates preserve measured row sizes", () => {
731
createRoot((dispose) => {
832
const [count, setCount] = createSignal(2)
@@ -42,23 +66,26 @@ test("initial rect projects rows before a scroll element connects", () => {
4266
})
4367
})
4468

45-
test("logical scroll offset includes pending measurement adjustments", () => {
46-
createRoot((dispose) => {
47-
const virtualizer = createVirtualizer<HTMLDivElement, HTMLDivElement>({
48-
count: 2,
49-
getScrollElement: () => null,
50-
estimateSize: () => 60,
51-
initialOffset: 100,
52-
initialRect: { width: 800, height: 60 },
53-
})
69+
test("clamps oversized offsets with scroll margin and padding changes", () => {
70+
const options = (paddingEnd: number) => ({
71+
count: 20,
72+
estimateSize: () => 60,
73+
initialOffset: Number.MAX_SAFE_INTEGER,
74+
initialRect: { width: 800, height: 600 },
75+
scrollMargin: 64,
76+
paddingEnd,
77+
overscan: 1,
78+
getScrollElement: () => null,
79+
scrollToFn: () => {},
80+
observeElementRect: () => {},
81+
observeElementOffset: () => {},
82+
})
83+
const virtualizer = new Virtualizer<HTMLDivElement, HTMLDivElement>(options(64))
5484

55-
virtualizer.getTotalSize()
56-
virtualizer.resizeItem(0, 100)
85+
expect(virtualizer.getVirtualItems().map((item) => item.index)).toEqual([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
5786

58-
expect(virtualizer.scrollOffset).toBe(100)
59-
expect(virtualizer.getLogicalScrollOffset()).toBe(140)
60-
dispose()
61-
})
87+
virtualizer.setOptions(options(600))
88+
expect(virtualizer.getVirtualItems().map((item) => item.index)).toEqual([18, 19])
6289
})
6390

6491
test("stale pinned indexes do not produce missing virtual items after count shrinks", () => {

patches/@tanstack%2Fsolid-virtual@3.13.28.patch

Lines changed: 0 additions & 45 deletions
This file was deleted.

patches/@tanstack%2Fvirtual-core@3.17.0.patch

Lines changed: 0 additions & 105 deletions
This file was deleted.

0 commit comments

Comments
 (0)