Skip to content

Commit

Permalink
fix(react-dom): expose only required options for InView
Browse files Browse the repository at this point in the history
  • Loading branch information
manudeli committed Nov 20, 2024
1 parent 324f428 commit 5d12190
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 28 deletions.
2 changes: 1 addition & 1 deletion examples/visualization/src/app/react-dom/FadeIn/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function Page() {
>
<SuspenseQuery {...query.user(userId)}>
{({ data: user }) => (
<FadeIn duration={200} inViewOptions={{ triggerOnce: true }} className="max-w-[344px]">
<FadeIn duration={200} className="max-w-[344px]" triggerOnce>
<h1 className="text-lg font-bold">{user.username}</h1>
<p className="text-xs">{user.userAgent}</p>
<p>{user.age}</p>
Expand Down
28 changes: 17 additions & 11 deletions packages/react-dom/src/FadeIn.test-d.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import type { CSSProperties, ComponentProps } from 'react'
import { FadeIn } from './FadeIn'
import type { OmitKeyof } from './utility-types'

const Example1 = ({}: { x: string }) => <></>
const Example2 = () => <></>

describe('<FadeIn/>', () => {
// eslint-disable-next-line vitest/expect-expect
it('type check', () => {
// @ts-expect-error ts(2322)
;(() => <FadeIn as="div" href="https://example.com"></FadeIn>)()
;(() => <FadeIn as="a" href="https://example.com"></FadeIn>)()
;(() => <FadeIn></FadeIn>)()
;(() => <FadeIn as={Example1} x="string"></FadeIn>)()
;(() => <FadeIn as="div" href="https://example.com" />)()
;(() => <FadeIn as="a" href="https://example.com" />)()
;(() => <FadeIn />)()
;(() => <FadeIn as={Example1} x="string" />)()
// @ts-expect-error ts(2322)
;(() => <FadeIn as={Example2} x="string"></FadeIn>)()
// @ts-expect-error ts(2353)
;(() => <FadeIn style={{ opacity: 1 }}></FadeIn>)()
;(() => <FadeIn as={Example2} x="string" />)()

expectTypeOf<keyof ComponentProps<typeof FadeIn<typeof Example2>>>().toEqualTypeOf<
'root' | 'rootMargin' | 'threshold' | 'triggerOnce' | 'delay' | 'style' | 'as' | 'duration' | 'timingFunction'
>()
expectTypeOf<ComponentProps<typeof FadeIn<typeof Example2>>['style']>().toEqualTypeOf<
OmitKeyof<CSSProperties, 'opacity' | 'willChange' | 'transition'> | undefined
>()
})
})

const Example1 = ({}: { x: string }) => <></>
const Example2 = () => <></>
35 changes: 19 additions & 16 deletions packages/react-dom/src/FadeIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,30 @@ import { type InViewOptions } from './useInView'
import { type OmitKeyof, type Override } from './utility-types'

type FadeInProps<TAs extends ElementType> = Override<
ComponentPropsWithoutRef<TAs>,
Override<
ComponentPropsWithoutRef<TAs>,
OmitKeyof<InViewOptions, 'fallbackInView' | 'initialInView' | 'skip' | 'onChange' | 'trackVisibility'>
>,
{
/**
* The element type to render.
* @default 'div'
*/
as?: TAs
/**
* The delay in milliseconds before the animation starts.
* The style of the element.
*/
delay?: number
style?: OmitKeyof<CSSProperties, 'opacity' | 'willChange' | 'transition'>
/**
* The duration in milliseconds of the animation.
* @default 200
*/
duration?: number
/**
* The timing function of the animation.
* @default 'linear'
*/
timingFunction?: CSSProperties['animationTimingFunction']
/**
* The style of the element.
*/
style?: OmitKeyof<CSSProperties, 'opacity' | 'willChange' | 'transition'>
/**
* The options for the `useInView` hook.
*/
inViewOptions?: InViewOptions
}
>

Expand All @@ -38,24 +36,29 @@ type FadeInProps<TAs extends ElementType> = Override<
*/
export function FadeIn<TAs extends ElementType = 'div'>({
as,
delay = 0,
style,
// fadeIn Options
duration = 200,
timingFunction = 'linear',
inViewOptions,
// inView options
delay,
rootMargin,
threshold,
triggerOnce,
...restProps
}: FadeInProps<TAs>) {
const Component = as ?? 'div'
return (
<InView {...inViewOptions}>
<InView rootMargin={rootMargin} delay={delay} threshold={threshold} triggerOnce={triggerOnce}>
{({ inView, ref }) => (
<Component
{...restProps}
ref={ref}
style={{
...restProps.style,
...style,
opacity: inView ? 1 : 0,
willChange: 'opacity',
transition: `opacity ${duration}ms ${timingFunction} ${delay}ms`,
transition: `opacity ${duration}ms ${timingFunction}`,
}}
/>
)}
Expand Down

0 comments on commit 5d12190

Please sign in to comment.