import { useState, useEffect, ComponentType, useRef } from "react"
import { motion, useMotionValue, useSpring, useInView } from "framer-motion"
const withIntensity = (Component, maxDistancePercentage): ComponentType => {
const SPRING_CONFIG = { damping: 100, stiffness: 400 }
return (props) => {
const x = useMotionValue(0)
const y = useMotionValue(0)
const ref = useRef(null)
const springX = useSpring(x, SPRING_CONFIG)
const springY = useSpring(y, SPRING_CONFIG)
const isInView = useInView(ref)
useEffect(() => {
if (!isInView) {
x.set(0)
y.set(0)
}
}, [isInView])
useEffect(() => {
const calculateDistance = (e) => {
if (ref.current && isInView) {
const rect = ref.current.getBoundingClientRect()
const centerX = rect.left + rect.width / 2
const centerY = rect.top + rect.height / 2
const distanceX = e.clientX - centerX
const distanceY = e.clientY - centerY
x.set(distanceX * (maxDistancePercentage / 100))
y.set(distanceY * (maxDistancePercentage / 100))
}
}
document.addEventListener("mousemove", calculateDistance)
return () => {
document.removeEventListener("mousemove", calculateDistance)
}
}, [ref, isInView])
return (
<Component
{...props}
ref={ref}
style={{
x: springX,
y: springY,
}}
/>
)
}
}
export const withIntensity10 = (Component): ComponentType =>
withIntensity(Component, 10)
export const withIntensity5 = (Component): ComponentType =>
withIntensity(Component, 5)
export const withIntensity1 = (Component): ComponentType =>
withIntensity(Component, 1)