({ estimatedWidth, estimatedHeight, isOpen, initialPosition }: UseModalDragOptions)
| 96 | } |
| 97 | |
| 98 | export function useModalDrag({ estimatedWidth, estimatedHeight, isOpen, initialPosition }: UseModalDragOptions) { |
| 99 | const initialEstimatedPosition = isOpen |
| 100 | ? getEstimatedModalPosition({ estimatedWidth, estimatedHeight, initialPosition }) |
| 101 | : { x: 0, y: 0 }; |
| 102 | const positionResetKey = getModalPositionResetKey({ estimatedWidth, estimatedHeight, isOpen, initialPosition }); |
| 103 | const [position, setPosition] = useResetKeyedState(positionResetKey, initialEstimatedPosition); |
| 104 | const panelRef = useRef<HTMLDivElement>(null); |
| 105 | const positionRef = useRef(position); |
| 106 | useEffect(() => { positionRef.current = position; }, [position]); |
| 107 | |
| 108 | const centerModal = useCallback(() => { |
| 109 | if (panelRef.current) { |
| 110 | const rect = panelRef.current.getBoundingClientRect(); |
| 111 | const viewportW = window.innerWidth; |
| 112 | const viewportH = window.innerHeight; |
| 113 | setPosition({ |
| 114 | x: (viewportW - rect.width) / 2, |
| 115 | y: Math.max(MODAL_POSITION.minTop, (viewportH - rect.height) / 2), |
| 116 | }); |
| 117 | } |
| 118 | }, [setPosition]); |
| 119 | |
| 120 | // Re-center on the measured DOM size after the estimated centered position renders. |
| 121 | useEffect(() => { |
| 122 | if (!isOpen || initialPosition) return; |
| 123 | |
| 124 | const frameId = requestAnimationFrame(centerModal); |
| 125 | return () => cancelAnimationFrame(frameId); |
| 126 | }, [isOpen, centerModal, initialPosition]); |
| 127 | |
| 128 | const handleDragStart = useCallback((event: ModalDragStartEvent) => { |
| 129 | const startX = event.clientX; |
| 130 | const startY = event.clientY; |
| 131 | const startPosX = positionRef.current.x; |
| 132 | const startPosY = positionRef.current.y; |
| 133 | |
| 134 | const onMove = (ev: PointerEvent) => { |
| 135 | setPosition({ |
| 136 | x: startPosX + ev.clientX - startX, |
| 137 | y: startPosY + ev.clientY - startY, |
| 138 | }); |
| 139 | }; |
| 140 | startCapturedPointerDrag({ event, onMove }); |
| 141 | }, [setPosition]); |
| 142 | |
| 143 | return { position, panelRef, handleDragStart, centerModal }; |
| 144 | } |
no test coverage detected