import { useSpring, animated, config } from "@react-spring/web"; import { useDrag } from "@use-gesture/react"; import { ReactNode, useEffect, useRef, useState } from "react"; interface MobilePositionProps { children?: ReactNode; className?: string; onClose?: () => void; } export function FloatingCardMobilePosition(props: MobilePositionProps) { const ref = useRef(null); const closing = useRef(false); const [cardRect, setCardRect] = useState(null); const [{ y }, api] = useSpring(() => ({ y: 0, onRest() { if (!closing.current) return; if (props.onClose) props.onClose(); }, })); const bind = useDrag( ({ last, velocity: [, vy], direction: [, dy], movement: [, my] }) => { if (closing.current) return; const height = cardRect?.height ?? 0; if (last) { // if past half height downwards // OR Y velocity is past 0.5 AND going down AND 20 pixels below start position if (my > height * 0.5 || (vy > 0.5 && dy > 0 && my > 20)) { api.start({ y: height * 1.2, immediate: false, config: { ...config.wobbly, velocity: vy, clamp: true }, }); closing.current = true; } else { api.start({ y: 0, immediate: false, config: config.wobbly, }); } } else { api.start({ y: my, immediate: true }); } }, { from: () => [0, y.get()], filterTaps: true, bounds: { top: 0 }, rubberband: true, } ); useEffect(() => { if (!ref.current) return; function checkBox() { const divRect = ref.current?.getBoundingClientRect(); setCardRect(divRect ?? null); } checkBox(); const observer = new ResizeObserver(checkBox); observer.observe(ref.current); return () => { observer.disconnect(); }; }, []); return (
{props.children}
); }