import React, { ComponentType, useEffect, useMemo, useState } from 'react'; import { observer } from 'mobx-react-lite'; import { GridChildComponentProps, ReactElementType, VariableSizeGrid, } from 'react-window'; import { useScrollableContentContext } from '../../providers'; import { ReactWindowGridRef, VirtualGridRepeaterState, } from './VirtualGridRepeaterState'; import { RenderItem } from './RenderItem'; import { VirtualGridRepeaterContextProvider } from './VirtualGridRepeaterContext'; import { GridState } from './GridState'; export interface VirtualGridRepeaterBaseProps { gridState: GridState; renderItem: RenderItem; children: ComponentType>; innerElementType?: ReactElementType; outerElementType?: ReactElementType; } function _VirtualGridRepeaterBase(props: VirtualGridRepeaterBaseProps) { const { gridState, renderItem, innerElementType, outerElementType, children, } = props; const { scrollableContentRef } = useScrollableContentContext(); const [state] = useState(() => new VirtualGridRepeaterState({ gridState })); const { calcGridProps, rowCount, height, width, itemKeyRecycler: itemKey, } = state; const [onFullRenderEnd] = useState(() => state.gridState.toolbar.fedopsReporter.onFullRenderStart?.(), ); useEffect(() => { if (height && width) { onFullRenderEnd?.(); } }, [height && width]); const { columnCount, columnWidthIncludingGap, rowHeightIncludingGap, overscanCount, estimatedRowHeight, } = calcGridProps; useEffect(() => { const container = scrollableContentRef?.current; return state.init({ container, }); }, []); const style = useMemo( () => ({ overflow: 'visible', height: '100%', } as const), [], ); const context = useMemo( () => ({ state, renderItem, itemKey }), [renderItem, itemKey], ); useEffect(() => { state.gridRef?.resetAfterIndices({ columnIndex: 0, rowIndex: 0, shouldForceUpdate: true, }); }, [height, width, calcGridProps]); return ( { state.gridRef = el as ReactWindowGridRef; state.gridState.gridRef = el as ReactWindowGridRef; }} height={height} width={width} columnCount={columnCount} outerElementType={outerElementType} innerElementType={innerElementType} columnWidth={() => columnWidthIncludingGap(0)} rowHeight={(index: number) => rowHeightIncludingGap({ index, key: itemKey({ rowIndex: index, columnIndex: 0 }), }) ?? estimatedRowHeight } estimatedRowHeight={estimatedRowHeight} rowCount={height && width ? rowCount : 0} overscanRowCount={overscanCount} itemKey={itemKey} style={style} > {children} ); } export const VirtualGridRepeaterBase = observer(_VirtualGridRepeaterBase);