reactbits-mcp-server
Version:
MCP Server for React Bits - Access 99+ React components with animations, backgrounds, and UI elements
76 lines (64 loc) • 2.01 kB
JSX
import { useState, useEffect, useRef } from "react";
const Magnet = ({
children,
padding = 100,
disabled = false,
magnetStrength = 2,
activeTransition = "transform 0.3s ease-out",
inactiveTransition = "transform 0.5s ease-in-out",
wrapperClassName = "",
innerClassName = "",
...props
}) => {
const [isActive, setIsActive] = useState(false);
const [position, setPosition] = useState({ x: 0, y: 0 });
const magnetRef = useRef(null);
useEffect(() => {
if (disabled) {
setPosition({ x: 0, y: 0 });
return;
}
const handleMouseMove = (e) => {
if (!magnetRef.current) return;
const { left, top, width, height } = magnetRef.current.getBoundingClientRect();
const centerX = left + width / 2;
const centerY = top + height / 2;
const distX = Math.abs(centerX - e.clientX);
const distY = Math.abs(centerY - e.clientY);
if (distX < width / 2 + padding && distY < height / 2 + padding) {
setIsActive(true);
const offsetX = (e.clientX - centerX) / magnetStrength;
const offsetY = (e.clientY - centerY) / magnetStrength;
setPosition({ x: offsetX, y: offsetY });
} else {
setIsActive(false);
setPosition({ x: 0, y: 0 });
}
};
window.addEventListener("mousemove", handleMouseMove);
return () => {
window.removeEventListener("mousemove", handleMouseMove);
};
}, [padding, disabled, magnetStrength]);
const transitionStyle = isActive ? activeTransition : inactiveTransition;
return (
<div
ref={magnetRef}
className={wrapperClassName}
style={{ position: "relative", display: "inline-block" }}
{...props}
>
<div
className={innerClassName}
style={{
transform: `translate3d(${position.x}px, ${position.y}px, 0)`,
transition: transitionStyle,
willChange: "transform",
}}
>
{children}
</div>
</div>
);
};
export default Magnet;