ComponentsAboutContactPrivacyTerms

Built by Lacy Morrow

    Close file
    Close file
    Close file
    'use client';
    
    import React, { useRef } from 'react';
    import {
      motion,
      useMotionTemplate,
      useMotionValue,
      useSpring,
      useTransform,
      MotionStyle,
      SpringOptions,
    } from 'motion/react';
    
    export type TiltProps = {
      children: React.ReactNode;
      className?: string;
      style?: MotionStyle;
      rotationFactor?: number;
      isRevese?: boolean;
      springOptions?: SpringOptions;
    };
    
    export function Tilt({
      children,
      className,
      style,
      rotationFactor = 15,
      isRevese = false,
      springOptions,
    }: TiltProps) {
      const ref = useRef<HTMLDivElement>(null);
    
      const x = useMotionValue(0);
      const y = useMotionValue(0);
    
      const xSpring = useSpring(x, springOptions);
      const ySpring = useSpring(y, springOptions);
    
      const rotateX = useTransform(
        ySpring,
        [-0.5, 0.5],
        isRevese
          ? [rotationFactor, -rotationFactor]
          : [-rotationFactor, rotationFactor]
      );
      const rotateY = useTransform(
        xSpring,
        [-0.5, 0.5],
        isRevese
          ? [-rotationFactor, rotationFactor]
          : [rotationFactor, -rotationFactor]
      );
    
      const transform = useMotionTemplate`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
    
      const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
        if (!ref.current) return;
    
        const rect = ref.current.getBoundingClientRect();
        const width = rect.width;
        const height = rect.height;
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;
    
        const xPos = mouseX / width - 0.5;
        const yPos = mouseY / height - 0.5;
    
        x.set(xPos);
        y.set(yPos);
      };
    
      const handleMouseLeave = () => {
        x.set(0);
        y.set(0);
      };
    
      return (
        <motion.div
          ref={ref}
          className={className}
          style={{
            transformStyle: 'preserve-3d',
            ...style,
            transform,
          }}
          onMouseMove={handleMouseMove}
          onMouseLeave={handleMouseLeave}
        >
          {children}
        </motion.div>
      );
    }