diff --git a/package.json b/package.json index 349df26..2e55e0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-in-viewport", - "version": "1.0.0-alpha.24", + "version": "1.0.0-alpha.25", "description": "Track React component in viewport using Intersection Observer API", "author": "Roderick Hsiao ", "license": "MIT", diff --git a/src/lib/handleViewport.tsx b/src/lib/handleViewport.tsx index 5604955..20e39d4 100644 --- a/src/lib/handleViewport.tsx +++ b/src/lib/handleViewport.tsx @@ -6,49 +6,63 @@ import useInViewport from './useInViewport'; import { noop, defaultOptions, defaultConfig } from './constants'; -const isFunctionalComponent = (Component) => { +const isFunctionalComponent = (Component: React.ElementType) => { return ( typeof Component === 'function' && !(Component.prototype && Component.prototype.render) ); }; -const isReactComponent = (Component) => { +const isReactComponent = (Component: React.ComponentClass) => { return Component.prototype && Component.prototype.isReactComponent; }; -function handleViewport( - TargetComponent: React.ElementType | React.ComponentClass, +type InjectedProps = { + enterCount: number; + inViewport: boolean; + leaveCount: number; +}; + +type RefProps = React.PropsWithRef<{ + forwardedRef?: React.ForwardedRef; +}>; + +type OmittedProps = 'onEnterViewport' | 'onLeaveViewport'; +type RestPropsRef = Omit; + +function handleViewport

( + TargetComponent: React.ElementType | React.ComponentClass

, options: Options = defaultOptions, config: Config = defaultConfig, ) { const ForwardedRefComponent = forwardRef< - React.Ref, - { - inViewport: boolean; - enterCount: number; - leaveCount: number; - } + any, + InjectedProps & RefProps & RestPropsRef >((props, ref) => { - const refProps = { + const refProps: RefProps = { forwardedRef: ref, // pass both ref/forwardedRef for class component for backward compatibility - ...(isReactComponent(TargetComponent) + ...(isReactComponent(TargetComponent as React.ComponentClass

) && !isFunctionalComponent(TargetComponent) ? { ref, } : {}), }; - return ; + return ( + + ); }); function InViewport({ onEnterViewport = noop, onLeaveViewport = noop, ...restProps - }: Props) { - const node = useRef(); + }) { + const node = useRef(); const { inViewport, enterCount, leaveCount } = useInViewport( node, options, @@ -59,14 +73,14 @@ function handleViewport( }, ); + const injectedProps: InjectedProps = { + inViewport, + enterCount, + leaveCount, + }; + return ( - + ); }