// Returns {x, y} normalized -1..1 from the center of `ref` element. Returns {0,0} when not hovering.
function useMouseOffset(ref) {
	const [pos, setPos] = React.useState({ x: 0, y: 0, hovering: false });
	React.useEffect(() => {
		const el = ref.current;
		if (!el) return;
		let raf = null;
		let target = { x: 0, y: 0, hovering: false };
		const onMove = (e) => {
			const r = el.getBoundingClientRect();
			const cx = r.left + r.width / 2;
			const cy = r.top + r.height / 2;
			target = {
				x: Math.max(-1, Math.min(1, (e.clientX - cx) / (r.width / 2))),
				y: Math.max(-1, Math.min(1, (e.clientY - cy) / (r.height / 2))),
				hovering: true,
			};
			if (!raf) raf = requestAnimationFrame(tick);
		};
		const onLeave = () => {
			target = { x: 0, y: 0, hovering: false };
			if (!raf) raf = requestAnimationFrame(tick);
		};
		let current = { x: 0, y: 0, hovering: false };
		const tick = () => {
			current = {
				x: current.x + (target.x - current.x) * 0.12,
				y: current.y + (target.y - current.y) * 0.12,
				hovering: target.hovering,
			};
			setPos(current);
			const dx = Math.abs(target.x - current.x);
			const dy = Math.abs(target.y - current.y);
			if (dx > 0.001 || dy > 0.001) {
				raf = requestAnimationFrame(tick);
			} else {
				raf = null;
			}
		};
		el.addEventListener('mousemove', onMove);
		el.addEventListener('mouseleave', onLeave);
		return () => {
			el.removeEventListener('mousemove', onMove);
			el.removeEventListener('mouseleave', onLeave);
			if (raf) cancelAnimationFrame(raf);
		};
	}, [ref]);
	return pos;
}

window.useMouseOffset = useMouseOffset;
