/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import type * as React from 'react'; import type { StyleProp, ViewStyle, ScrollViewProps, LayoutChangeEvent, View, ScrollResponderMixin, ScrollView, } from 'react-native'; export interface ViewToken { item: any; key: string; index: number | null; isViewable: boolean; section?: any | undefined; } export interface ViewabilityConfig { /** * Minimum amount of time (in milliseconds) that an item must be physically viewable before the * viewability callback will be fired. A high number means that scrolling through content without * stopping will not mark the content as viewable. */ minimumViewTime?: number | undefined; /** * Percent of viewport that must be covered for a partially occluded item to count as * "viewable", 0-100. Fully visible items are always considered viewable. A value of 0 means * that a single pixel in the viewport makes the item viewable, and a value of 100 means that * an item must be either entirely visible or cover the entire viewport to count as viewable. */ viewAreaCoveragePercentThreshold?: number | undefined; /** * Similar to `viewAreaCoveragePercentThreshold`, but considers the percent of the item that is visible, * rather than the fraction of the viewable area it covers. */ itemVisiblePercentThreshold?: number | undefined; /** * Nothing is considered viewable until the user scrolls or `recordInteraction` is called after * render. */ waitForInteraction?: boolean | undefined; } export interface ViewabilityConfigCallbackPair { viewabilityConfig: ViewabilityConfig; onViewableItemsChanged: | ((info: { viewableItems: Array; changed: Array; }) => void) | null; } export type ViewabilityConfigCallbackPairs = ViewabilityConfigCallbackPair[]; /** * @see https://reactnative.dev/docs/flatlist#props */ export interface ListRenderItemInfo { item: ItemT; index: number; separators: { highlight: () => void; unhighlight: () => void; updateProps: (select: 'leading' | 'trailing', newProps: any) => void; }; } export type ListRenderItem = ( info: ListRenderItemInfo, ) => React.ReactElement | null; export interface CellRendererProps { cellKey: string; children: React.ReactNode; index: number; item: ItemT; onFocusCapture?: ((event: FocusEvent) => void) | undefined; onLayout?: ((event: LayoutChangeEvent) => void) | undefined; style: StyleProp | undefined; } /** * @see https://reactnative.dev/docs/virtualizedlist */ export class VirtualizedList extends React.Component< VirtualizedListProps > { scrollToEnd: (params?: {animated?: boolean | undefined}) => void; scrollToIndex: (params: { animated?: boolean | undefined; index: number; viewOffset?: number | undefined; viewPosition?: number | undefined; }) => void; scrollToItem: (params: { animated?: boolean | undefined; item: ItemT; viewOffset?: number | undefined; viewPosition?: number | undefined; }) => void; /** * Scroll to a specific content pixel offset in the list. * Param `offset` expects the offset to scroll to. In case of horizontal is true, the * offset is the x-value, in any other case the offset is the y-value. * Param `animated` (true by default) defines whether the list should do an animation while scrolling. */ scrollToOffset: (params: { animated?: boolean | undefined; offset: number; }) => void; recordInteraction: () => void; getScrollRef: () => | React.ElementRef | React.ElementRef | null; getScrollResponder: () => ScrollResponderMixin | null; } /** * @see https://reactnative.dev/docs/virtualizedlist#props */ export interface VirtualizedListProps extends VirtualizedListWithoutRenderItemProps { renderItem: ListRenderItem | null | undefined; } export interface VirtualizedListWithoutRenderItemProps extends ScrollViewProps { /** * Rendered in between each item, but not at the top or bottom */ ItemSeparatorComponent?: React.ComponentType | null | undefined; /** * Rendered when the list is empty. Can be a React Component Class, a render function, or * a rendered element. */ ListEmptyComponent?: | React.ComponentType | React.ReactElement | null | undefined; /** * Rendered at the bottom of all the items. Can be a React Component Class, a render function, or * a rendered element. */ ListFooterComponent?: | React.ComponentType | React.ReactElement | null | undefined; /** * Styling for internal View for ListFooterComponent */ ListFooterComponentStyle?: StyleProp | undefined; /** * Rendered at the top of all the items. Can be a React Component Class, a render function, or * a rendered element. */ ListHeaderComponent?: | React.ComponentType | React.ReactElement | null | undefined; /** * Styling for internal View for ListHeaderComponent */ ListHeaderComponentStyle?: StyleProp | undefined; /** * The default accessor functions assume this is an Array<{key: string}> but you can override * getItem, getItemCount, and keyExtractor to handle any type of index-based data. */ data?: any | undefined; /** * `debug` will turn on extra logging and visual overlays to aid with debugging both usage and * implementation, but with a significant perf hit. */ debug?: boolean | undefined; /** * DEPRECATED: Virtualization provides significant performance and memory optimizations, but fully * unmounts react instances that are outside of the render window. You should only need to disable * this for debugging purposes. */ disableVirtualization?: boolean | undefined; /** * A marker property for telling the list to re-render (since it implements `PureComponent`). If * any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the * `data` prop, stick it here and treat it immutably. */ extraData?: any | undefined; /** * A generic accessor for extracting an item from any sort of data blob. */ getItem?: ((data: any, index: number) => ItemT) | undefined; /** * Determines how many items are in the data blob. */ getItemCount?: ((data: any) => number) | undefined; getItemLayout?: | (( data: any, index: number, ) => { length: number; offset: number; index: number; }) | undefined; horizontal?: boolean | null | undefined; /** * How many items to render in the initial batch. This should be enough to fill the screen but not * much more. Note these items will never be unmounted as part of the windowed rendering in order * to improve perceived performance of scroll-to-top actions. */ initialNumToRender?: number | undefined; /** * Instead of starting at the top with the first item, start at `initialScrollIndex`. This * disables the "scroll to top" optimization that keeps the first `initialNumToRender` items * always rendered and immediately renders the items starting at this initial index. Requires * `getItemLayout` to be implemented. */ initialScrollIndex?: number | null | undefined; /** * Reverses the direction of scroll. Uses scale transforms of -1. */ inverted?: boolean | null | undefined; keyExtractor?: ((item: ItemT, index: number) => string) | undefined; /** * The maximum number of items to render in each incremental render batch. The more rendered at * once, the better the fill rate, but responsiveness my suffer because rendering content may * interfere with responding to button taps or other interactions. */ maxToRenderPerBatch?: number | undefined; /** * Called once when the scroll position gets within within `onEndReachedThreshold` * from the logical end of the list. */ onEndReached?: ((info: {distanceFromEnd: number}) => void) | null | undefined; /** * How far from the end (in units of visible length of the list) the trailing edge of the * list must be from the end of the content to trigger the `onEndReached` callback. * Thus, a value of 0.5 will trigger `onEndReached` when the end of the content is * within half the visible length of the list. */ onEndReachedThreshold?: number | null | undefined; onLayout?: ((event: LayoutChangeEvent) => void) | undefined; /** * If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make * sure to also set the `refreshing` prop correctly. */ onRefresh?: (() => void) | null | undefined; /** * Used to handle failures when scrolling to an index that has not been measured yet. * Recommended action is to either compute your own offset and `scrollTo` it, or scroll as far * as possible and then try again after more items have been rendered. */ onScrollToIndexFailed?: | ((info: { index: number; highestMeasuredFrameIndex: number; averageItemLength: number; }) => void) | undefined; /** * Called once when the scroll position gets within within `onStartReachedThreshold` * from the logical start of the list. */ onStartReached?: | ((info: {distanceFromStart: number}) => void) | null | undefined; /** * How far from the start (in units of visible length of the list) the leading edge of the * list must be from the start of the content to trigger the `onStartReached` callback. * Thus, a value of 0.5 will trigger `onStartReached` when the start of the content is * within half the visible length of the list. */ onStartReachedThreshold?: number | null | undefined; /** * Called when the viewability of rows changes, as defined by the * `viewabilityConfig` prop. */ onViewableItemsChanged?: | ((info: { viewableItems: Array; changed: Array; }) => void) | null | undefined; /** * Set this when offset is needed for the loading indicator to show correctly. * @platform android */ progressViewOffset?: number | undefined; /** * Set this true while waiting for new data from a refresh. */ refreshing?: boolean | null | undefined; /** * Note: may have bugs (missing content) in some circumstances - use at your own risk. * * This may improve scroll performance for large lists. */ removeClippedSubviews?: boolean | undefined; /** * Render a custom scroll component, e.g. with a differently styled `RefreshControl`. */ renderScrollComponent?: | ((props: ScrollViewProps) => React.ReactElement) | undefined; /** * Amount of time between low-pri item render batches, e.g. for rendering items quite a ways off * screen. Similar fill rate/responsiveness tradeoff as `maxToRenderPerBatch`. */ updateCellsBatchingPeriod?: number | undefined; viewabilityConfig?: ViewabilityConfig | undefined; viewabilityConfigCallbackPairs?: ViewabilityConfigCallbackPairs | undefined; /** * Determines the maximum number of items rendered outside of the visible area, in units of * visible lengths. So if your list fills the screen, then `windowSize={21}` (the default) will * render the visible screen area plus up to 10 screens above and 10 below the viewport. Reducing * this number will reduce memory consumption and may improve performance, but will increase the * chance that fast scrolling may reveal momentary blank areas of unrendered content. */ windowSize?: number | undefined; /** * CellRendererComponent allows customizing how cells rendered by * `renderItem`/`ListItemComponent` are wrapped when placed into the * underlying ScrollView. This component must accept event handlers which * notify VirtualizedList of changes within the cell. */ CellRendererComponent?: | React.ComponentType> | null | undefined; }