All files / src/utils scrollUtils.ts

100% Statements 21/21
100% Branches 6/6
100% Functions 2/2
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50            1x                       1x 8x 8x 8x 8x 8x 8x 8x   3x 3x   5x 5x 5x                   1x 3x 3x 3x 3x 3x 3x  
/**
 * Pure scroll-math utilities for the smart-scroll feature.
 * No DOM or React dependencies — easy to unit test.
 */
 
/** Pixel threshold for "near anchor" detection. */
export const SCROLL_ANCHOR_THRESHOLD_PX: number = 50;
 
/**
 * Whether the scroll position is within threshold of the anchor point.
 *
 * @param scrollTop - Current scrollTop of the container
 * @param scrollHeight - Total scrollable height of the container
 * @param clientHeight - Visible height of the container
 * @param isReversed - If true, anchor is at the top; otherwise at bottom
 * @param threshold - Override the default 50px threshold
 * @returns True if the scroll position is near the anchor
 */
export function isNearAnchor(
  scrollTop: number,
  scrollHeight: number,
  clientHeight: number,
  isReversed: boolean,
  threshold: number = SCROLL_ANCHOR_THRESHOLD_PX,
): boolean {
  if (isReversed) {
    // Anchor is at the top — near anchor when scrollTop is small
    return scrollTop < threshold;
  }
  // Anchor is at the bottom — near anchor when close to max scroll
  const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
  return distanceFromBottom < threshold;
}
 
/**
 * Compute the scrollTop delta needed to compensate for prepended content.
 * Used in reverse mode to prevent viewport shift when new items appear at top.
 *
 * @param previousScrollHeight - scrollHeight before the render
 * @param currentScrollHeight - scrollHeight after the render
 * @returns Positive delta to add to scrollTop, or 0 if no compensation needed
 */
export function computeScrollCompensation(
  previousScrollHeight: number,
  currentScrollHeight: number,
): number {
  const delta = currentScrollHeight - previousScrollHeight;
  return delta > 0 ? delta : 0;
}