CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tanstack--react-virtual

Headless UI for virtualizing scrollable elements in React

Pending
Overview
Eval results
Files

types-utilities.mddocs/

Types and Utilities

Core type definitions, interfaces, and utility functions used throughout the TanStack React Virtual virtualization system.

Capabilities

Core Interfaces

Essential interfaces that define the structure of virtual items and configuration objects.

/**
 * Represents a virtualized item with position and size information
 */
export interface VirtualItem {
  /** Unique key for the item (from getItemKey function) */
  key: Key;
  /** Zero-based index of the item in the data array */
  index: number;
  /** Start position of the item in pixels from the beginning of the scroll area */
  start: number;
  /** End position of the item in pixels from the beginning of the scroll area */
  end: number;
  /** Height (vertical) or width (horizontal) of the item in pixels */
  size: number;
  /** Lane number for grid layouts (0-based) */
  lane: number;
}

/**
 * Represents the dimensions of a rectangular area
 */
export interface Rect {
  /** Width in pixels */
  width: number;
  /** Height in pixels */
  height: number;
}

/**
 * Defines a range of items with overscan information
 */
export interface Range {
  /** Index of the first item in the range */
  startIndex: number;
  /** Index of the last item in the range */
  endIndex: number;
  /** Number of items to render outside the visible area */
  overscan: number;
  /** Total number of items in the dataset */
  count: number;
}

/**
 * Options for scrolling operations
 */
export interface ScrollToOptions {
  /** How to align the target within the viewport */
  align?: ScrollAlignment;
  /** Scroll behavior (smooth or instant) */
  behavior?: ScrollBehavior;
}

Type Aliases

Common type aliases used throughout the virtualization system.

/**
 * Valid key types for identifying virtual items
 */
export type Key = number | string | bigint;

/**
 * Direction of scroll movement
 */
export type ScrollDirection = 'forward' | 'backward';

/**
 * How to align items when scrolling
 */
export type ScrollAlignment = 'start' | 'center' | 'end' | 'auto';

/**
 * Browser scroll behavior
 */
export type ScrollBehavior = 'auto' | 'smooth';

/**
 * Options for scrollToOffset method
 */
export type ScrollToOffsetOptions = ScrollToOptions;

/**
 * Options for scrollToIndex method  
 */
export type ScrollToIndexOptions = ScrollToOptions;

Observer Functions

Functions for observing element and window changes, used internally by the virtualization engine.

/**
 * Observe changes to an element's dimensions using ResizeObserver
 * @param instance - Virtualizer instance
 * @param cb - Callback function to receive dimension updates
 * @returns Cleanup function to stop observing
 */
export function observeElementRect<T extends Element>(
  instance: Virtualizer<T, any>,
  cb: (rect: Rect) => void
): void | (() => void);

/**
 * Observe changes to window dimensions
 * @param instance - Virtualizer instance for window
 * @param cb - Callback function to receive dimension updates
 * @returns Cleanup function to stop observing
 */
export function observeWindowRect(
  instance: Virtualizer<Window, any>,
  cb: (rect: Rect) => void
): void | (() => void);

/**
 * Observe scroll offset changes for an element
 * @param instance - Virtualizer instance
 * @param cb - Callback function to receive offset and scrolling state
 * @returns Cleanup function to stop observing
 */
export function observeElementOffset<T extends Element>(
  instance: Virtualizer<T, any>,
  cb: (offset: number, isScrolling: boolean) => void
): void | (() => void);

/**
 * Observe scroll offset changes for the window
 * @param instance - Virtualizer instance for window
 * @param cb - Callback function to receive offset and scrolling state
 * @returns Cleanup function to stop observing
 */
export function observeWindowOffset(
  instance: Virtualizer<Window, any>,
  cb: (offset: number, isScrolling: boolean) => void
): void | (() => void);

Scroll Functions

Functions that handle scrolling for different element types.

/**
 * Scroll function for DOM elements
 * @param offset - Target scroll position in pixels
 * @param options - Scroll options with adjustments and behavior
 * @param instance - Virtualizer instance
 */
export function elementScroll<T extends Element>(
  offset: number,
  options: { adjustments?: number; behavior?: ScrollBehavior },
  instance: Virtualizer<T, any>
): void;

/**
 * Scroll function for the window
 * @param offset - Target scroll position in pixels
 * @param options - Scroll options with adjustments and behavior
 * @param instance - Virtualizer instance
 */
export function windowScroll<T extends Window>(
  offset: number,
  options: { adjustments?: number; behavior?: ScrollBehavior },
  instance: Virtualizer<T, any>
): void;

Measurement Functions

Functions for measuring and calculating item sizes.

/**
 * Measure the size of a DOM element
 * @param element - Element to measure
 * @param entry - ResizeObserver entry (optional)
 * @param instance - Virtualizer instance
 * @returns Size in pixels (height for vertical, width for horizontal)
 */
export function measureElement<TItemElement extends Element>(
  element: TItemElement,
  entry: ResizeObserverEntry | undefined,
  instance: Virtualizer<any, TItemElement>
): number;

Default Functions

Default implementation functions that can be customized.

/**
 * Default key extraction function
 * @param index - Item index
 * @returns The index as the key
 */
export function defaultKeyExtractor(index: number): number;

/**
 * Default range extraction function that includes overscan
 * @param range - Range specification with overscan
 * @returns Array of indexes to render
 */
export function defaultRangeExtractor(range: Range): Array<number>;

Usage Examples:

import { defaultRangeExtractor, Range } from '@tanstack/react-virtual';

// Custom range extractor that limits overscan
function limitedRangeExtractor(range: Range): Array<number> {
  const maxOverscan = 5;
  const actualOverscan = Math.min(range.overscan, maxOverscan);
  
  return defaultRangeExtractor({
    ...range,
    overscan: actualOverscan
  });
}

// Custom key extractor for complex data
function dataKeyExtractor(index: number): string {
  return `item-${data[index]?.id ?? index}`;
}

Utility Functions

General utility functions used throughout the library.

/**
 * Assert that a value is not undefined
 * @param value - Value to check
 * @param msg - Optional error message
 * @returns The value if not undefined
 * @throws Error if value is undefined
 */
export function notUndefined<T>(value: T | undefined, msg?: string): T;

/**
 * Check if two numbers are approximately equal (within 1.01 pixels)
 * @param a - First number
 * @param b - Second number
 * @returns True if approximately equal
 */
export function approxEqual(a: number, b: number): boolean;

/**
 * Create a debounced version of a function
 * @param targetWindow - Window object for setTimeout/clearTimeout
 * @param fn - Function to debounce
 * @param ms - Debounce delay in milliseconds
 * @returns Debounced function
 */
export function debounce(
  targetWindow: Window & typeof globalThis,
  fn: Function,
  ms: number
): Function;

/**
 * Memoization utility with dependency tracking
 * @param getDeps - Function that returns current dependencies
 * @param fn - Function to memoize
 * @param opts - Memoization options
 * @returns Memoized function with updateDeps method
 */
export function memo<TDeps extends ReadonlyArray<any>, TResult>(
  getDeps: () => [...TDeps],
  fn: (...args: NoInfer<[...TDeps]>) => TResult,
  opts: {
    key: false | string;
    debug?: () => boolean;
    onChange?: (result: TResult) => void;
    initialDeps?: TDeps;
  }
): (() => TResult) & { updateDeps: (newDeps: [...TDeps]) => void };

Utility Types

Advanced TypeScript utility types for better type safety.

/**
 * Type that prevents TypeScript from inferring generic types
 */
export type NoInfer<A extends any> = [A][A extends any ? 0 : never];

/**
 * Make specific keys of an interface optional while keeping others required
 */
export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

Usage Examples:

import { PartialKeys, VirtualizerOptions } from '@tanstack/react-virtual';

// Example of PartialKeys usage - make some required options optional
type SimplifiedOptions<TScrollElement extends Element, TItemElement extends Element> = 
  PartialKeys<
    VirtualizerOptions<TScrollElement, TItemElement>, 
    'observeElementRect' | 'observeElementOffset' | 'scrollToFn'
  >;

// This allows creating options objects without providing the complex observer functions
const options: SimplifiedOptions<HTMLDivElement, HTMLDivElement> = {
  count: 1000,
  getScrollElement: () => document.getElementById('container') as HTMLDivElement,
  estimateSize: () => 50,
  // observeElementRect, observeElementOffset, and scrollToFn are now optional
};

Common Usage Patterns

Custom Key Extraction

import { useVirtualizer } from '@tanstack/react-virtual';

interface DataItem {
  id: string;
  name: string;
}

function CustomKeyList({ items }: { items: DataItem[] }) {
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
    getItemKey: (index) => items[index]?.id ?? index,
  });

  return (
    // Virtual list implementation
  );
}

Custom Range Extraction

import { useVirtualizer, defaultRangeExtractor, Range } from '@tanstack/react-virtual';

// Custom range extractor that adds extra items at the end
function extraEndRangeExtractor(range: Range): Array<number> {
  const defaultIndexes = defaultRangeExtractor(range);
  
  // Add 5 extra items at the end if we're near the bottom
  if (range.endIndex >= range.count - 10) {
    const extraItems = Math.min(5, range.count - 1 - range.endIndex);
    for (let i = 1; i <= extraItems; i++) {
      if (range.endIndex + i < range.count) {
        defaultIndexes.push(range.endIndex + i);
      }
    }
  }
  
  return defaultIndexes;
}

function CustomRangeList({ items }: { items: any[] }) {
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
    rangeExtractor: extraEndRangeExtractor,
  });

  return (
    // Virtual list implementation
  );
}

Debug Mode Usage

import { useVirtualizer } from '@tanstack/react-virtual';

function DebugVirtualList({ items }: { items: any[] }) {
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
    debug: process.env.NODE_ENV === 'development',
  });

  // Debug mode will log performance metrics to console
  
  return (
    // Virtual list implementation
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-tanstack--react-virtual

docs

index.md

react-hooks.md

types-utilities.md

virtualizer-engine.md

tile.json