import type { DataTableScrollAlign } from "../types"; interface DataTableVisibleWindowOptions { appViewportHeight: number; items: T[]; measuredViewportHeight: number | undefined; overscan: number; scrollTop: number; virtualize: boolean; } export interface DataTableVisibleWindow { endIndex: number; startIndex: number; viewportHeight: number; visibleItems: T[]; } export function resolveDataTableScrollTop( targetIndex: number, currentTop: number, visibleHeight: number, itemCount: number, align: DataTableScrollAlign, ): number { const maxTop = Math.max(0, itemCount - visibleHeight); let nextTop = currentTop; if (align === "center") { nextTop = targetIndex - Math.floor(visibleHeight / 2); } else if (targetIndex < currentTop) { nextTop = targetIndex; } else if (targetIndex >= currentTop + visibleHeight) { nextTop = targetIndex - visibleHeight + 1; } return Math.max(0, Math.min(maxTop, nextTop)); } export function resolveDataTableVisibleWindow({ appViewportHeight, items, measuredViewportHeight, overscan, scrollTop, virtualize, }: DataTableVisibleWindowOptions): DataTableVisibleWindow { const viewportHeight = virtualize ? Math.max( 1, Math.min( measuredViewportHeight ?? Math.min(items.length, 16), Math.max(1, Math.ceil(appViewportHeight)), ), ) : items.length; const startIndex = virtualize ? Math.max(scrollTop - overscan, 0) : 0; const endIndex = virtualize ? Math.min(startIndex + viewportHeight + overscan * 2, items.length) : items.length; return { endIndex, startIndex, viewportHeight, visibleItems: items.slice(startIndex, endIndex), }; }