import { useGSAP } from "@gsap/react"; import { useRef, type HTMLAttributes, type ReactNode } from "react"; import { useGsapContext } from "~/app/_providers/GsapProvicer"; import { SplitText } from "gsap/SplitText"; import gsap from 'gsap' import { cn } from "~/lib/utils"; const AnimateTextIn = ({ children, animation = "type", position = 0, tlId = undefined, speed = 1, scrollOnly = false, className }: { children: ReactNode, animation?: "type" | "slide", position?: gsap.Position, tlId?: string, scrollOnly?: boolean, speed?: number, className?: HTMLAttributes['className'] }) => { const el = useRef(null) const gsapContext = useGsapContext(); useGSAP(() => { const rect = el.current?.getBoundingClientRect() const scroller = gsapContext?.getScroller() console.log(scroller) let viewportTop = 0 let viewportBottom = window.innerHeight if (scroller && scroller instanceof Element) { const scrollerRect = scroller.getBoundingClientRect() viewportTop = scrollerRect.top viewportBottom = scrollerRect.top + scrollerRect.height } const isInView = rect && rect.bottom > viewportTop && rect.top < viewportBottom console.log(isInView) const chars = new SplitText(el.current, { type: 'chars' }) gsapContext?.addAnimation(gsap.to(el.current, { opacity: 100, duration: 0 }), 0, tlId) const fromVars = animation === "slide" ? { opacity: 0, x: -10, duration: 0.2 * speed, stagger: { each: 0.08 * speed }, ease: 'bounce.inOut', onComplete: () => chars.revert() } : { opacity: 0, duration: 0.01 * speed, stagger: { each: 0.04 * speed }, ease: 'bounce.inOut', onComplete: () => chars.revert() } if (isInView && !scrollOnly) { gsapContext?.addAnimation(gsap.from(chars.chars, fromVars), position, tlId) } else { gsap.from(chars.chars, { ...fromVars, scrollTrigger: { trigger: el.current, start: 'top bottom', end: 'bottom top', toggleActions: "play reverse play reverse", scroller } }) } }, { dependencies: [] }) return (
{children}
) } export default AnimateTextIn;