UNPKG

react-gsap-animation-library

Version:

A comprehensive React component library that leverages GSAP for animations with official GSAP-React integration

196 lines (176 loc) 5.48 kB
import React, { useRef } from 'react'; import { useGSAP } from '@gsap/react'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; import { useAnimationSettings } from '../../context/AnimationContext'; /** * SlideIn component for creating slide-in animations with GSAP * * @param {Object} props - Component props * @param {React.ReactNode} props.children - Child elements to animate * @param {number} props.duration - Animation duration in seconds * @param {number} props.delay - Animation delay in seconds * @param {string} props.ease - GSAP easing function * @param {string} props.direction - Slide direction ('up', 'down', 'left', 'right') * @param {number} props.distance - Slide distance in pixels * @param {boolean} props.fade - Whether to fade in while sliding * @param {boolean} props.bounce - Whether to add a bounce effect at the end * @param {string} props.trigger - Animation trigger type ('scroll', 'load', 'none', 'hover', 'click') * @param {number} props.threshold - Viewport threshold to trigger animation (0-1) * @param {function} props.onStart - Callback when animation starts * @param {function} props.onComplete - Callback when animation completes * @param {string} props.className - Additional CSS class names * @param {Object} props.style - Custom styles */ const SlideIn = ({ children, duration = 0.8, delay = 0, ease, direction = 'up', distance = 100, fade = true, bounce = false, trigger = 'scroll', threshold = 0.2, onStart = () => {}, onComplete = () => {}, className = '', style = {}, ...otherProps }) => { const elementRef = useRef(null); const { disableAllAnimations, disableScrollAnimations } = useAnimationSettings(); // Set default ease based on bounce effect if (!ease) { ease = bounce ? "back.out(1.7)" : "power3.out"; } // Get direction-based animation properties const getDirectionalProps = () => { const baseProps = fade ? { opacity: 0 } : {}; switch (direction) { case 'up': return { ...baseProps, y: distance }; case 'down': return { ...baseProps, y: -distance }; case 'left': return { ...baseProps, x: -distance }; case 'right': return { ...baseProps, x: distance }; default: return { ...baseProps, y: distance }; } }; // Use GSAP React hook const { contextSafe } = useGSAP(() => { if (!elementRef.current) return; // Skip if animations disabled if (disableAllAnimations || (trigger === 'scroll' && disableScrollAnimations)) { // Make content visible gsap.set(elementRef.current, { opacity: 1, x: 0, y: 0 }); return; } // For load and scroll triggers if (trigger === 'load' || trigger === 'scroll') { // Get starting properties const fromProps = getDirectionalProps(); // Create the animation const tween = gsap.from(elementRef.current, { ...fromProps, duration, delay, ease, onStart, onComplete, paused: trigger === 'scroll' }); // Handle scroll trigger if (trigger === 'scroll' && !disableScrollAnimations) { ScrollTrigger.create({ trigger: elementRef.current, start: `top bottom-=${threshold * 100}%`, onEnter: () => tween.play() }); } else if (trigger === 'load') { // Play immediately for load trigger tween.play(); } } return () => { // Clean up ScrollTrigger instances on unmount if (trigger === 'scroll') { ScrollTrigger.getAll() .filter(st => st.vars.trigger === elementRef.current) .forEach(st => st.kill()); } }; }, { scope: elementRef, dependencies: [ direction, distance, duration, delay, ease, trigger, threshold, fade, bounce, disableAllAnimations, disableScrollAnimations ] }); // Play animation function for manual triggers const playAnimation = contextSafe(() => { if (disableAllAnimations) return; const fromProps = getDirectionalProps(); gsap.fromTo( elementRef.current, fromProps, { opacity: fade ? 1 : undefined, x: 0, y: 0, duration, ease, onStart, onComplete } ); }); // Get event handlers based on trigger type const getEventHandlers = () => { if (disableAllAnimations) return {}; if (trigger === 'hover') { return { onMouseEnter: playAnimation }; } if (trigger === 'click') { return { onClick: playAnimation }; } return {}; }; // Combined props for rendering const componentProps = { ref: elementRef, className: `react-gsap-slidein ${className}`, style, 'data-animation-direction': direction, 'data-fade': fade.toString(), 'data-bounce': bounce.toString(), ...getEventHandlers(), ...otherProps }; return ( <div {...componentProps}> {typeof children === 'function' ? children({ play: playAnimation }) : children } </div> ); }; export default SlideIn;