/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow strict-local * @format */ import type VirtualizedList from './VirtualizedList.js'; import * as React from 'react'; import {useMemo, useContext} from 'react'; type Frame = $ReadOnly<{ offset: number, length: number, index: number, inLayout: boolean, }>; export type ChildListState = $ReadOnly<{ first: number, last: number, frames: {[key: number]: Frame}, }>; // Data propagated through nested lists (regardless of orientation) that is // useful for producing diagnostics for usage errors involving nesting (e.g // missing/duplicate keys). export type ListDebugInfo = $ReadOnly<{ cellKey: string, listKey: string, parent: ?ListDebugInfo, // We include all ancestors regardless of orientation, so this is not always // identical to the child's orientation. horizontal: boolean, }>; type Context = $ReadOnly<{ cellKey: ?string, getScrollMetrics: () => { contentLength: number, dOffset: number, dt: number, offset: number, timestamp: number, velocity: number, visibleLength: number, }, horizontal: ?boolean, getOutermostParentListRef: () => VirtualizedList, getNestedChildState: string => ?ChildListState, registerAsNestedChild: ({ cellKey: string, key: string, ref: VirtualizedList, parentDebugInfo: ListDebugInfo, }) => ?ChildListState, unregisterAsNestedChild: ({ key: string, state: ChildListState, }) => void, debugInfo: ListDebugInfo, }>; export const VirtualizedListContext: React.Context = React.createContext( null, ); if (__DEV__) { VirtualizedListContext.displayName = 'VirtualizedListContext'; } /** * Resets the context. Intended for use by portal-like components (e.g. Modal). */ export function VirtualizedListContextResetter({ children, }: { children: React.Node, }): React.Node { return ( {children} ); } /** * Sets the context with memoization. Intended to be used by `VirtualizedList`. */ export function VirtualizedListContextProvider({ children, value, }: { children: React.Node, value: Context, }): React.Node { // Avoid setting a newly created context object if the values are identical. const context = useMemo( () => ({ cellKey: null, getScrollMetrics: value.getScrollMetrics, horizontal: value.horizontal, getOutermostParentListRef: value.getOutermostParentListRef, getNestedChildState: value.getNestedChildState, registerAsNestedChild: value.registerAsNestedChild, unregisterAsNestedChild: value.unregisterAsNestedChild, debugInfo: { cellKey: value.debugInfo.cellKey, horizontal: value.debugInfo.horizontal, listKey: value.debugInfo.listKey, parent: value.debugInfo.parent, }, }), [ value.getScrollMetrics, value.horizontal, value.getOutermostParentListRef, value.getNestedChildState, value.registerAsNestedChild, value.unregisterAsNestedChild, value.debugInfo.cellKey, value.debugInfo.horizontal, value.debugInfo.listKey, value.debugInfo.parent, ], ); return ( {children} ); } /** * Sets the `cellKey`. Intended to be used by `VirtualizedList` for each cell. */ export function VirtualizedListCellContextProvider({ cellKey, children, }: { cellKey: string, children: React.Node, }): React.Node { const context = useContext(VirtualizedListContext); return ( {children} ); }