lightswind
Version:
A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.
57 lines • 3.4 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MagneticButton = MagneticButton;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const framer_motion_1 = require("framer-motion");
const utils_1 = require("@/components/lib/utils");
function MagneticButton({ children, strength = 0.4, radius = 80, variant = "primary", size = "md", onClick, className, }) {
const buttonRef = (0, react_1.useRef)(null);
const [isHovered, setIsHovered] = (0, react_1.useState)(false);
// Spring config — snappy but elastic
const springConfig = { stiffness: 200, damping: 18, mass: 0.6 };
const rawX = (0, framer_motion_1.useSpring)(0, springConfig);
const rawY = (0, framer_motion_1.useSpring)(0, springConfig);
// Inner text moves slightly less than the container (parallax depth)
const textX = (0, framer_motion_1.useTransform)(rawX, (v) => v * 0.4);
const textY = (0, framer_motion_1.useTransform)(rawY, (v) => v * 0.4);
const handleMouseMove = (e) => {
const rect = buttonRef.current?.getBoundingClientRect();
if (!rect)
return;
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const distX = e.clientX - centerX;
const distY = e.clientY - centerY;
const dist = Math.sqrt(distX ** 2 + distY ** 2);
if (dist < radius) {
rawX.set(distX * strength);
rawY.set(distY * strength);
setIsHovered(true);
}
else {
rawX.set(0);
rawY.set(0);
setIsHovered(false);
}
};
const handleMouseLeave = () => {
rawX.set(0);
rawY.set(0);
setIsHovered(false);
};
const variants = {
primary: "bg-primary text-primary-foreground hover:bg-primary/90 shadow-lg shadow-primary/20",
outline: "border-2 border-foreground text-foreground hover:bg-foreground/5",
ghost: "text-foreground hover:bg-foreground/8",
dark: "bg-foreground text-background shadow-lg",
};
const sizes = {
sm: "h-9 px-5 text-sm rounded-full",
md: "h-12 px-8 text-base rounded-full",
lg: "h-14 px-12 text-lg rounded-full",
};
return ((0, jsx_runtime_1.jsx)("div", { ref: buttonRef, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, style: { display: "inline-flex", padding: radius * 0.25 }, children: (0, jsx_runtime_1.jsxs)(framer_motion_1.motion.button, { type: "button", onClick: onClick, style: { x: rawX, y: rawY }, animate: { scale: isHovered ? 1.04 : 1 }, transition: { type: "spring", stiffness: 300, damping: 20 }, className: (0, utils_1.cn)("relative inline-flex items-center justify-center font-semibold tracking-tight transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring overflow-hidden", variants[variant], sizes[size], className), children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { animate: { opacity: isHovered ? 1 : 0 }, transition: { duration: 0.25 }, className: "pointer-events-none absolute inset-0 rounded-full bg-white/10" }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { style: { x: textX, y: textY }, className: "relative z-10 flex items-center gap-2", children: children })] }) }));
}
//# sourceMappingURL=magnetic-button.js.map