diff --git a/src/components/ResizeHandler.tsx b/src/components/ResizeHandler.tsx index 4c4442a..b8513a9 100644 --- a/src/components/ResizeHandler.tsx +++ b/src/components/ResizeHandler.tsx @@ -1,5 +1,6 @@ import { Icon } from 'components/Icon' import * as React from 'react' +import { ResizeState, useResizeHandler } from '../utils/hooks/useResizeHandler' import { Size2D } from './SideBarBodyWrapper' type Props = { @@ -10,8 +11,6 @@ type Props = { style?: React.CSSProperties } -type ResizeState = 'idle' | 'resizing' - export function ResizeHandler({ onResize, onResetSize, onResizeStateChange, size, style }: Props) { const { onPointerDown } = useResizeHandler(size, onResize, { onResizeStateChange }) @@ -26,63 +25,3 @@ export function ResizeHandler({ onResize, onResetSize, onResizeStateChange, size ) } - -export function useResizeHandler( - size: Size2D, - onResize: (size: Size2D) => void, - { - onResizeStateChange, - onClick, - }: Partial<{ - onResizeStateChange: (state: ResizeState) => void - onClick: (e: PointerEvent) => void - }> = {}, -) { - const pointerDown = React.useRef(false) - const pointerMoved = React.useRef(false) - const initialSizeRef = React.useRef([0, 0]) - const baseSize = React.useRef(size) - const latestPropSize = React.useRef(size) - - React.useEffect(() => { - latestPropSize.current = size - }, [size]) - - React.useEffect(() => { - const onPointerMove = ({ clientX, clientY }: PointerEvent) => { - if (!pointerDown.current) return - pointerMoved.current = true - const [x, y] = baseSize.current - onResize([x + clientX - initialSizeRef.current[0], y + clientY - initialSizeRef.current[1]]) - } - window.addEventListener('pointermove', onPointerMove) - return () => window.removeEventListener('pointermove', onPointerMove) - }, [onResize]) - - React.useEffect(() => { - const onPointerUp = (e: PointerEvent) => { - if (pointerDown.current) { - pointerDown.current = false - - if (!pointerMoved.current) onClick?.(e) - pointerMoved.current = false - - baseSize.current = latestPropSize.current - onResizeStateChange?.('idle') - } - } - window.addEventListener('pointerup', onPointerUp) - return () => window.removeEventListener('pointerup', onPointerUp) - }, []) - - const onPointerDown = React.useCallback((e: React.PointerEvent) => { - e.preventDefault() // Prevent unexpected selection when dragging in Safari - const { clientX, clientY } = e - pointerDown.current = true - initialSizeRef.current = [clientX, clientY] - baseSize.current = latestPropSize.current - onResizeStateChange?.('resizing') - }, []) - - return { onPointerDown } -} diff --git a/src/components/ToggleShowButton.tsx b/src/components/ToggleShowButton.tsx index fada7ec..fcd929e 100644 --- a/src/components/ToggleShowButton.tsx +++ b/src/components/ToggleShowButton.tsx @@ -3,8 +3,8 @@ import { useConfigs } from 'containers/ConfigsContext' import * as React from 'react' import { useDebounce, useWindowSize } from 'react-use' import { cx } from 'utils/cx' +import { useResizeHandler } from 'utils/hooks/useResizeHandler' import { Icon } from './Icon' -import { useResizeHandler } from './ResizeHandler' type Props = { error?: string | null diff --git a/src/utils/hooks/useResizeHandler.tsx b/src/utils/hooks/useResizeHandler.tsx new file mode 100644 index 0000000..65c70a9 --- /dev/null +++ b/src/utils/hooks/useResizeHandler.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import { Size2D } from '../../components/SideBarBodyWrapper'; + +export type ResizeState = 'idle' | 'resizing'; + +export function useResizeHandler( + size: Size2D, + onResize: (size: Size2D) => void, + { + onResizeStateChange, + onClick, + }: Partial<{ + onResizeStateChange: (state: ResizeState) => void; + onClick: (e: PointerEvent) => void; + }> = {} +) { + const pointerDown = React.useRef(false); + const pointerMoved = React.useRef(false); + const initialSizeRef = React.useRef([0, 0]); + const baseSize = React.useRef(size); + const latestPropSize = React.useRef(size); + + React.useEffect(() => { + latestPropSize.current = size; + }, [size]); + + React.useEffect(() => { + const onPointerMove = ({ clientX, clientY }: PointerEvent) => { + if (!pointerDown.current) + return; + pointerMoved.current = true; + const [x, y] = baseSize.current; + onResize([x + clientX - initialSizeRef.current[0], y + clientY - initialSizeRef.current[1]]); + }; + window.addEventListener('pointermove', onPointerMove); + return () => window.removeEventListener('pointermove', onPointerMove); + }, [onResize]); + + React.useEffect(() => { + const onPointerUp = (e: PointerEvent) => { + if (pointerDown.current) { + pointerDown.current = false; + + if (!pointerMoved.current) + onClick?.(e); + pointerMoved.current = false; + + baseSize.current = latestPropSize.current; + onResizeStateChange?.('idle'); + } + }; + window.addEventListener('pointerup', onPointerUp); + return () => window.removeEventListener('pointerup', onPointerUp); + }, []); + + const onPointerDown = React.useCallback((e: React.PointerEvent) => { + e.preventDefault(); // Prevent unexpected selection when dragging in Safari + const { clientX, clientY } = e; + pointerDown.current = true; + initialSizeRef.current = [clientX, clientY]; + baseSize.current = latestPropSize.current; + onResizeStateChange?.('resizing'); + }, []); + + return { onPointerDown }; +}