// Magnet — wraps a child element and translates it toward the cursor when the
// cursor enters a `padding`-px halo around the element. Releases back to origin
// with a slower transition when the cursor leaves.
//
// Props:
//   padding             px halo beyond the element rect that activates the pull
//   strength            divisor of cursor-distance — higher = subtler pull
//   activeTransition    CSS transition while the magnet is "grabbed"
//   inactiveTransition  CSS transition while releasing

const Magnet = ({
  children,
  padding = 100,
  strength = 2,
  activeTransition = 'transform 0.3s ease-out',
  inactiveTransition = 'transform 0.6s ease-in-out',
  style,
  ...rest
}) => {
  const ref = React.useRef(null);
  const [pos, setPos] = React.useState({ x: 0, y: 0 });
  const [active, setActive] = React.useState(false);

  React.useEffect(() => {
    const onMove = (e) => {
      const el = ref.current;
      if (!el) return;
      const rect = el.getBoundingClientRect();
      const cx = rect.left + rect.width / 2;
      const cy = rect.top + rect.height / 2;
      const dx = e.clientX - cx;
      const dy = e.clientY - cy;
      const within =
        e.clientX > rect.left - padding &&
        e.clientX < rect.right + padding &&
        e.clientY > rect.top - padding &&
        e.clientY < rect.bottom + padding;
      if (within) {
        setActive(true);
        setPos({ x: dx / strength, y: dy / strength });
      } else if (active || pos.x !== 0 || pos.y !== 0) {
        setActive(false);
        setPos({ x: 0, y: 0 });
      }
    };
    window.addEventListener('mousemove', onMove);
    return () => window.removeEventListener('mousemove', onMove);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [padding, strength]);

  return (
    <div
      ref={ref}
      style={{
        transform: `translate3d(${pos.x}px, ${pos.y}px, 0)`,
        transition: active ? activeTransition : inactiveTransition,
        willChange: 'transform',
        display: 'inline-block',
        ...style,
      }}
      {...rest}
    >
      {children}
    </div>
  );
};

window.Magnet = Magnet;
