From 6fece64ace0a3867c749d314cd0a8ca2280e985b Mon Sep 17 00:00:00 2001 From: ms-austin-beaulieu Date: Tue, 24 Sep 2024 09:51:17 -0700 Subject: [PATCH] Add prop to gate element dimension rounding Due to default element dimension rounding, programatic scrolling while at the bottom of very large lists can be unstable when element dimensions contain sub-pixel values. Adding an option to the virtualizer fixes this when this level of precision is needed --- packages/virtual-core/src/index.ts | 33 ++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/packages/virtual-core/src/index.ts b/packages/virtual-core/src/index.ts index 2b3d4ff1..1d95a644 100644 --- a/packages/virtual-core/src/index.ts +++ b/packages/virtual-core/src/index.ts @@ -73,8 +73,14 @@ export const observeElementRect = ( } const handler = (rect: Rect) => { - const { width, height } = rect - cb({ width: Math.round(width), height: Math.round(height) }) + let { width, height } = rect + + if (instance.options.roundElementDimensions) { + width = Math.round(width) + height = Math.round(height) + } + + cb({ width, height }) } handler(element.getBoundingClientRect()) @@ -225,17 +231,26 @@ export const measureElement = ( if (entry?.borderBoxSize) { const box = entry.borderBoxSize[0] if (box) { - const size = Math.round( - box[instance.options.horizontal ? 'inlineSize' : 'blockSize'], - ) + let size = box[instance.options.horizontal ? 'inlineSize' : 'blockSize'] + + if (instance.options.roundElementDimensions) { + size = Math.round(size) + } + return size } } - return Math.round( + + let size = element.getBoundingClientRect()[ instance.options.horizontal ? 'width' : 'height' - ], - ) + ] + + if (instance.options.roundElementDimensions) { + size = Math.round(size) + } + + return size } export const windowScroll = ( @@ -323,6 +338,7 @@ export interface VirtualizerOptions< isScrollingResetDelay?: number enabled?: boolean isRtl?: boolean + roundElementDimensions?: boolean } export class Virtualizer< @@ -412,6 +428,7 @@ export class Virtualizer< isScrollingResetDelay: 150, enabled: true, isRtl: false, + roundElementDimensions: true, ...opts, } }