/** * 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 { ListRenderItemInfo, VirtualizedListWithoutRenderItemProps, } from '@react-native/virtualized-lists'; import type { ScrollView, ScrollViewProps, } from '../Components/ScrollView/ScrollView'; import {NodeHandle} from '../ReactNative/RendererProxy'; import {StyleProp} from '../StyleSheet/StyleSheet'; import {ViewStyle} from '../StyleSheet/StyleSheetTypes'; /** * @see https://reactnative.dev/docs/sectionlist */ type DefaultSectionT = { [key: string]: any; }; export interface SectionBase { data: ReadonlyArray; key?: string | undefined; renderItem?: SectionListRenderItem | undefined; ItemSeparatorComponent?: React.ComponentType | null | undefined; keyExtractor?: ((item: ItemT, index: number) => string) | undefined; } export type SectionListData = SectionBase< ItemT, SectionT > & SectionT; /** * @see https://reactnative.dev/docs/sectionlist.html#props */ export interface SectionListRenderItemInfo extends ListRenderItemInfo { section: SectionListData; } export type SectionListRenderItem = ( info: SectionListRenderItemInfo, ) => React.ReactElement | null; export interface SectionListProps extends VirtualizedListWithoutRenderItemProps { /** * Rendered in between each section. */ SectionSeparatorComponent?: | React.ComponentType | React.ReactElement | null | 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; /** * `getItemLayout` is an optional optimization that lets us skip measurement of dynamic * content if you know the height of items a priori. getItemLayout is the most efficient, * and is easy to use if you have fixed height items, for example: * ``` * getItemLayout={(data, index) => ( * {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index} * )} * ``` */ getItemLayout?: | (( data: SectionListData[] | null, index: number, ) => {length: number; offset: number; index: number}) | undefined; /** * How many items to render in the initial batch */ initialNumToRender?: number | undefined; /** * Reverses the direction of scroll. Uses scale transforms of -1. */ inverted?: boolean | null | undefined; /** * Used to extract a unique key for a given item at the specified index. Key is used for caching * and as the react key to track item re-ordering. The default extractor checks `item.key`, then * falls back to using the index, like React does. */ keyExtractor?: ((item: ItemT, index: number) => string) | undefined; /** * Called once when the scroll position gets within onEndReachedThreshold of the rendered content. */ onEndReached?: ((info: {distanceFromEnd: number}) => void) | null | undefined; /** * How far from the end (in units of visible length of the list) the bottom 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; /** * 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; /** * Set this true while waiting for new data from a refresh. */ refreshing?: boolean | null | undefined; /** * Default renderer for every item in every section. Can be over-ridden on a per-section basis. */ renderItem?: SectionListRenderItem | undefined; /** * Rendered at the top of each section. Sticky headers are not yet supported. */ renderSectionHeader?: | ((info: { section: SectionListData; }) => React.ReactElement | null) | undefined; /** * Rendered at the bottom of each section. */ renderSectionFooter?: | ((info: { section: SectionListData; }) => React.ReactElement | null) | undefined; /** * An array of objects with data for each section. */ sections: ReadonlyArray>; /** * Render a custom scroll component, e.g. with a differently styled `RefreshControl`. */ renderScrollComponent?: | ((props: ScrollViewProps) => React.ReactElement) | 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; /** * Makes section headers stick to the top of the screen until the next one pushes it off. * Only enabled by default on iOS because that is the platform standard there. */ stickySectionHeadersEnabled?: boolean | undefined; /** * Uses legacy MetroListView instead of default VirtualizedSectionList */ legacyImplementation?: boolean | undefined; } export interface SectionListScrollParams { animated?: boolean | undefined; itemIndex: number; sectionIndex: number; viewOffset?: number | undefined; viewPosition?: number | undefined; } export abstract class SectionListComponent< Props, > extends React.Component { /** * Scrolls to the item at the specified sectionIndex and itemIndex (within the section) * positioned in the viewable area such that viewPosition 0 places it at the top * (and may be covered by a sticky header), 1 at the bottom, and 0.5 centered in the middle. */ scrollToLocation(params: SectionListScrollParams): void; /** * Tells the list an interaction has occurred, which should trigger viewability calculations, e.g. * if `waitForInteractions` is true and the user has not scrolled. This is typically called by * taps on items or by navigation actions. */ recordInteraction(): void; /** * Displays the scroll indicators momentarily. * * @platform ios */ flashScrollIndicators(): void; /** * Provides a handle to the underlying scroll responder. */ getScrollResponder(): ScrollView | undefined; /** * Provides a handle to the underlying scroll node. */ getScrollableNode(): NodeHandle | undefined; } export class SectionList< ItemT = any, SectionT = DefaultSectionT, > extends SectionListComponent> {} /* This definition is deprecated because it extends the wrong base type */ export interface SectionListStatic extends React.ComponentClass> { /** * Scrolls to the item at the specified sectionIndex and itemIndex (within the section) * positioned in the viewable area such that viewPosition 0 places it at the top * (and may be covered by a sticky header), 1 at the bottom, and 0.5 centered in the middle. */ scrollToLocation?(params: SectionListScrollParams): void; }