import React, { useEffect, useRef, useState } from 'react' import { observer } from 'mobx-react' import type { MsaViewModel } from '../model.ts' export const VerticalResizeHandle = observer(function ({ model, }: { model: MsaViewModel }) { const { resizeHandleWidth } = model const [mouseDragging, setMouseDragging] = useState(false) const scheduled = useRef(false) const prevX = useRef(0) useEffect(() => { function globalMouseMove(event: MouseEvent) { event.preventDefault() const currX = event.clientX if (prevX.current === 0) { prevX.current = event.clientX } else { const distance = currX - prevX.current if (distance) { // use rAF to make it so multiple event handlers aren't fired per-frame // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/ if (!scheduled.current) { scheduled.current = true window.requestAnimationFrame(() => { model.setTreeAreaWidth(model.treeAreaWidth + distance) scheduled.current = false prevX.current = event.clientX }) } } } } function globalMouseUp() { prevX.current = 0 if (mouseDragging) { setMouseDragging(false) } } if (mouseDragging) { document.addEventListener('mousemove', globalMouseMove, true) document.addEventListener('mouseup', globalMouseUp, true) return () => { document.removeEventListener('mousemove', globalMouseMove, true) document.removeEventListener('mouseup', globalMouseUp, true) } } return () => {} }, [mouseDragging, model]) return (
{ setMouseDragging(true) }} style={{ cursor: 'ew-resize', height: '100%', width: resizeHandleWidth, background: 'rgba(200,200,200)', position: 'relative', }} />
) }) export const HorizontalResizeHandle = observer(function ({ model, }: { model: MsaViewModel }) { const { resizeHandleWidth } = model const [mouseDragging, setMouseDragging] = useState(false) const scheduled = useRef(false) const prevY = useRef(0) useEffect(() => { function globalMouseMove(event: MouseEvent) { event.preventDefault() const currY = event.clientY if (prevY.current === 0) { prevY.current = event.clientY } else { const distance = currY - prevY.current if (distance) { // use rAF to make it so multiple event handlers aren't fired per-frame // see https://calendar.perfplanet.com/2013/the-runtime-performance-checklist/ if (!scheduled.current) { scheduled.current = true window.requestAnimationFrame(() => { model.setHeight(model.height + distance) scheduled.current = false prevY.current = event.clientY }) } } } } function globalMouseUp() { prevY.current = 0 if (mouseDragging) { setMouseDragging(false) } } if (mouseDragging) { document.addEventListener('mousemove', globalMouseMove, true) document.addEventListener('mouseup', globalMouseUp, true) return () => { document.removeEventListener('mousemove', globalMouseMove, true) document.removeEventListener('mouseup', globalMouseUp, true) } } return () => {} }, [mouseDragging, model]) return (
{ setMouseDragging(true) }} style={{ cursor: 'ns-resize', width: '100%', height: resizeHandleWidth, background: 'rgba(200,200,200)', position: 'relative', }} />
) })