diff --git a/.changeset/lovely-countries-trade.md b/.changeset/lovely-countries-trade.md new file mode 100644 index 000000000..87c88b8bf --- /dev/null +++ b/.changeset/lovely-countries-trade.md @@ -0,0 +1,5 @@ +--- +"react-virtuoso": patch +--- + +correct TS types for custom component, context is always passed diff --git a/packages/react-virtuoso/src/TableVirtuoso.tsx b/packages/react-virtuoso/src/TableVirtuoso.tsx index b39ac6ecf..4b0f48765 100644 --- a/packages/react-virtuoso/src/TableVirtuoso.tsx +++ b/packages/react-virtuoso/src/TableVirtuoso.tsx @@ -298,7 +298,7 @@ const TableRoot: React.FC = /*#__PURE__*/ React.memo(function Ta ) : null return ( - + {theHead} diff --git a/packages/react-virtuoso/src/Virtuoso.tsx b/packages/react-virtuoso/src/Virtuoso.tsx index c72f29125..72c01e145 100644 --- a/packages/react-virtuoso/src/Virtuoso.tsx +++ b/packages/react-virtuoso/src/Virtuoso.tsx @@ -7,7 +7,7 @@ import useIsomorphicLayoutEffect from './hooks/useIsomorphicLayoutEffect' import useScrollTop from './hooks/useScrollTop' import useSize from './hooks/useSize' import useWindowViewportRectRef from './hooks/useWindowViewportRect' -import { Components, ComputeItemKey, GroupContent, GroupItemContent, ItemContent, ListRootProps } from './interfaces' +import { Components, ComputeItemKey, ContextProp, GroupContent, GroupItemContent, ItemContent, ListRootProps } from './interfaces' import { listSystem } from './listSystem' import { systemToComponent } from './react-urx' import * as u from './urx' @@ -236,8 +236,9 @@ const topItemListStyle: React.CSSProperties = { zIndex: 1, } -export function contextPropIfNotDomElement(element: unknown, context: unknown) { +export function contextPropIfNotDomElement(element: unknown, context: C): ContextProp { if (typeof element === 'string') { + // @ts-expect-error lie the type system, we don't want to return anything for dom elements return undefined } return { context } @@ -446,10 +447,11 @@ const ListRoot: React.FC = /*#__PURE__*/ React.memo(function Virt const useWindowScroll = useEmitterValue('useWindowScroll') const showTopList = useEmitterValue('topItemsIndexes').length > 0 const customScrollParent = useEmitterValue('customScrollParent') + const context = useEmitterValue('context') const TheScroller = customScrollParent || useWindowScroll ? WindowScroller : Scroller const TheViewport = customScrollParent || useWindowScroll ? WindowViewport : Viewport return ( - + {showTopList && ( diff --git a/packages/react-virtuoso/src/VirtuosoGrid.tsx b/packages/react-virtuoso/src/VirtuosoGrid.tsx index c9d8870f8..f9034d6f0 100644 --- a/packages/react-virtuoso/src/VirtuosoGrid.tsx +++ b/packages/react-virtuoso/src/VirtuosoGrid.tsx @@ -250,9 +250,10 @@ const GridRoot: React.FC = /*#__PURE__*/ React.memo(function Grid const customScrollParent = useEmitterValue('customScrollParent') const TheScroller = customScrollParent || useWindowScroll ? WindowScroller : Scroller const TheViewport = customScrollParent || useWindowScroll ? WindowViewport : Viewport + const context = useEmitterValue('context') return ( - +
diff --git a/packages/react-virtuoso/src/interfaces.ts b/packages/react-virtuoso/src/interfaces.ts index 7fd55c974..e0e489d35 100644 --- a/packages/react-virtuoso/src/interfaces.ts +++ b/packages/react-virtuoso/src/interfaces.ts @@ -12,6 +12,10 @@ export interface CalculateViewLocationParams { viewportTop: number } +export interface ContextProp { + context: C +} + /** * Customize the Virtuoso rendering by passing a set of custom components. */ @@ -19,48 +23,48 @@ export interface Components { /** * Set to render a custom UI when the list is empty. */ - EmptyPlaceholder?: React.ComponentType<{ context?: Context }> + EmptyPlaceholder?: React.ComponentType> /** * Set to render a component at the bottom of the list. */ - Footer?: React.ComponentType<{ context?: Context }> + Footer?: React.ComponentType> /** * Set to customize the group item wrapping element. Use only if you would like to render list from elements different than a `div`. */ - Group?: React.ComponentType + Group?: React.ComponentType> /** * Set to render a component at the top of the list. * * The header remains above the top items and does not remain sticky. */ - Header?: React.ComponentType<{ context?: Context }> + Header?: React.ComponentType> /** * Set to customize the item wrapping element. Use only if you would like to render list from elements different than a `div`. */ - Item?: React.ComponentType & { context?: Context }> + Item?: React.ComponentType & ContextProp> /** * Set to customize the items wrapper. Use only if you would like to render list from elements different than a `div`. */ - List?: React.ComponentType + List?: React.ComponentType> /** * Set to customize the outermost scrollable element. This should not be necessary in general, * as the component passes its HTML attribute props to it. */ - Scroller?: React.ComponentType + Scroller?: React.ComponentType> /** * Set to render an item placeholder when the user scrolls fast. See the `scrollSeek` property for more details. */ - ScrollSeekPlaceholder?: React.ComponentType + ScrollSeekPlaceholder?: React.ComponentType> /** * Set to customize the top list item wrapping element. Use if you would like to render list from elements different than a `div` * or you want to set a custom z-index for the sticky position. */ - TopItemList?: React.ComponentType + TopItemList?: React.ComponentType> } export type ComputeItemKey = (index: number, item: D, context: C) => React.Key @@ -95,36 +99,36 @@ export interface GridComponents { /** * Set to render a component at the bottom of the list. */ - Footer?: React.ComponentType<{ context?: Context }> + Footer?: React.ComponentType> /** * Set to render a component at the top of the list. * * The header remains above the top items and does not remain sticky. */ - Header?: React.ComponentType<{ context?: Context }> + Header?: React.ComponentType> /** * Set to customize the item wrapping element. Use only if you would like to render list from elements different than a `div`. */ - Item?: React.ComponentType + Item?: React.ComponentType> /** * Set to customize the items wrapper. Use only if you would like to render list from elements different than a `div`. */ - List?: React.ComponentType + List?: React.ComponentType> /** * Set to customize the outermost scrollable element. This should not be necessary in general, * as the component passes its HTML attribute props to it. */ - Scroller?: React.ComponentType + Scroller?: React.ComponentType> /** * Set to render an item placeholder when the user scrolls fast. * See the `scrollSeekConfiguration` property for more details. */ - ScrollSeekPlaceholder?: React.ComponentType + ScrollSeekPlaceholder?: React.ComponentType> } export type GridComputeItemKey = (index: number, item: D, context: C) => React.Key @@ -351,40 +355,40 @@ export interface TableComponents { /** * Set to render a custom UI when the list is empty. */ - EmptyPlaceholder?: React.ComponentType<{ context?: Context }> + EmptyPlaceholder?: React.ComponentType> /** * Set to render an empty item placeholder. */ - FillerRow?: React.ComponentType + FillerRow?: React.ComponentType> /** * Set to customize the outermost scrollable element. This should not be necessary in general, * as the component passes its HTML attribute props to it. */ - Scroller?: React.ComponentType + Scroller?: React.ComponentType> /** * Set to render an item placeholder when the user scrolls fast. See the `scrollSeek` property for more details. */ - ScrollSeekPlaceholder?: React.ComponentType + ScrollSeekPlaceholder?: React.ComponentType> /** * Set to customize the wrapping `table` element. * */ - Table?: React.ComponentType + Table?: React.ComponentType> /** * Set to customize the items wrapper. Default is `tbody`. */ - TableBody?: React.ComponentType + TableBody?: React.ComponentType> /** * Set to render a fixed footer at the bottom of the table (`tfoot`). use [[fixedFooterContent]] to set the contents */ TableFoot?: React.ComponentType< - Pick, 'children' | 'style'> & React.RefAttributes & { context?: Context } + Pick, 'children' | 'style'> & React.RefAttributes & ContextProp > /** @@ -392,13 +396,13 @@ export interface TableComponents { * */ TableHead?: React.ComponentType< - Pick, 'children' | 'style'> & React.RefAttributes & { context?: Context } + Pick, 'children' | 'style'> & React.RefAttributes & ContextProp > /** * Set to customize the item wrapping element. Default is `tr`. */ - TableRow?: React.ComponentType & { context?: Context }> + TableRow?: React.ComponentType & ContextProp> } export type TableProps = Pick, 'children' | 'style'>