Skip to content

Commit 4fb2d35

Browse files
fix(virtual-core): observe scrollbar viewport changes
1 parent 34eb905 commit 4fb2d35

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

‎packages/virtual-core/src/index.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export const observeElementRect = <T extends Element>(
151151
: run()
152152
})
153153

154-
observer.observe(element, { box: 'border-box' })
154+
observer.observe(element, { box: 'content-box' })
155155

156156
return () => {
157157
observer.unobserve(element)

‎packages/virtual-core/tests/measurement.test.ts‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,3 +1032,47 @@ test.each([false, true])(
10321032
virtualizer._didMount()()
10331033
},
10341034
)
1035+
1036+
test('refreshes horizontal end alignment when a scrollbar toggles', () => {
1037+
const { el } = createOwnWindow()
1038+
let deliverResize: ResizeObserverCallback
1039+
let observedBox: ResizeObserverBoxOptions | undefined
1040+
el.ownerDocument.defaultView!.ResizeObserver = vi.fn(function (cb) {
1041+
deliverResize = cb
1042+
return {
1043+
observe: (_target: Element, options?: ResizeObserverOptions) => {
1044+
observedBox = options?.box
1045+
},
1046+
unobserve: vi.fn(),
1047+
disconnect: vi.fn(),
1048+
}
1049+
}) as unknown as typeof ResizeObserver
1050+
Object.assign(el, { scrollWidth: 5000 })
1051+
const virtualizer = new Virtualizer({
1052+
count: 100,
1053+
horizontal: true,
1054+
estimateSize: () => 50,
1055+
getScrollElement: () => el,
1056+
scrollToFn: vi.fn(),
1057+
observeElementRect,
1058+
observeElementOffset: (_instance, cb) => {
1059+
cb(0, false)
1060+
},
1061+
})
1062+
virtualizer._willUpdate()
1063+
expect(virtualizer.getOffsetForIndex(10, 'end')?.[0]).toBe(150)
1064+
for (const width of [385, 400]) {
1065+
// A classic scrollbar changes the content box, leaving the border box fixed.
1066+
Object.assign(el, { clientWidth: width })
1067+
if (observedBox !== 'border-box') {
1068+
deliverResize!(
1069+
[{ target: el } as ResizeObserverEntry],
1070+
{} as ResizeObserver,
1071+
)
1072+
}
1073+
expect(el.offsetWidth).toBe(400)
1074+
expect(virtualizer.scrollRect?.width).toBe(width)
1075+
expect(virtualizer.getOffsetForIndex(10, 'end')?.[0]).toBe(550 - width)
1076+
}
1077+
virtualizer._didMount()()
1078+
})

0 commit comments

Comments
 (0)