Skip to content

Commit

Permalink
Improve type definition for HOC (#105)
Browse files Browse the repository at this point in the history
* Improve type definition for HOC
  • Loading branch information
roderickhsiao committed Mar 30, 2022
1 parent 8646cff commit 2d08bfd
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 23 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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 <roderickhsiao@gmail.com>",
"license": "MIT",
Expand Down
58 changes: 36 additions & 22 deletions src/lib/handleViewport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<any>;
}>;

type OmittedProps = 'onEnterViewport' | 'onLeaveViewport';
type RestPropsRef = Omit<Props, OmittedProps>;

function handleViewport<P extends Props>(
TargetComponent: React.ElementType | React.ComponentClass<P>,
options: Options = defaultOptions,
config: Config = defaultConfig,
) {
const ForwardedRefComponent = forwardRef<
React.Ref<any>,
{
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<P>)
&& !isFunctionalComponent(TargetComponent)
? {
ref,
}
: {}),
};
return <TargetComponent {...props} {...refProps} />;
return (
<TargetComponent
{...(props as RestPropsRef)}
{...(refProps as RefProps)}
/>
);
});

function InViewport({
onEnterViewport = noop,
onLeaveViewport = noop,
...restProps
}: Props) {
const node = useRef();
}) {
const node = useRef<any>();
const { inViewport, enterCount, leaveCount } = useInViewport(
node,
options,
Expand All @@ -59,14 +73,14 @@ function handleViewport(
},
);

const injectedProps: InjectedProps = {
inViewport,
enterCount,
leaveCount,
};

return (
<ForwardedRefComponent
{...restProps}
inViewport={inViewport}
enterCount={enterCount}
leaveCount={leaveCount}
ref={node}
/>
<ForwardedRefComponent {...restProps} {...injectedProps} ref={node} />
);
}

Expand Down

0 comments on commit 2d08bfd

Please sign in to comment.