Skip to content

Instantly share code, notes, and snippets.

@kitze
Created December 17, 2019 12:13
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kitze/b25a5b7c86a5287aac07ab9c647588da to your computer and use it in GitHub Desktop.
Save kitze/b25a5b7c86a5287aac07ab9c647588da to your computer and use it in GitHub Desktop.
A hook that gives you resize logic that you can attach to an element
import { useLocalStore } from 'mobx-react-lite';
import { clamp } from 'lodash';
type Props = {
height: number;
maxHeight?: number;
minWidth: number;
minHeight: number;
measureWidth?: boolean;
measureHeight?: boolean;
maxWidth?: number;
onResize?: ({ size: Size, dragging: boolean }) => void;
onResizeFinish?: () => void;
width: number;
};
export const useResizer = (props: Props) => {
const { onResize, onResizeFinish } = props;
const state = useLocalStore((source: Props) => {
return {
fullScreen: false,
dragging: false,
measureWidth: true,
measureHeight: true,
originalHeight: source.height,
originalWidth: source.width,
startY: 0,
startX: 0,
heightBeforeMinimize: 0,
onMouseDown: e => {
state.dragging = true;
if (source.measureWidth) {
state.startX = e.clientX;
state.originalWidth = source.width;
}
if (source.measureHeight) {
state.startY = e.clientY;
state.originalHeight = source.height;
}
window.document.body.classList.add('no-select');
document.addEventListener('mousemove', state.onMouseMove);
document.addEventListener('mouseup', state.onMouseUp);
},
measureSide: (
name,
currentPosition,
startPosition,
original,
min,
max,
currentSize
) => {
const verticalDistance = currentPosition - startPosition;
const difference = original - verticalDistance;
const newMeasure = clamp(difference, min, max);
const sizeHasChanged = newMeasure !== currentSize;
if (sizeHasChanged) {
const newSize = { [name]: newMeasure };
onResize && onResize({ size: newSize, dragging: state.dragging });
state[name] = newMeasure;
}
},
onMouseMove: e => {
if (state.dragging) {
if (source.measureHeight) {
state.measureSide(
'height',
e.clientY,
state.startY,
state.originalHeight,
source.minHeight,
source.maxHeight,
source.height
);
}
if (source.measureWidth) {
state.measureSide(
'width',
e.clientX,
state.startX,
state.originalWidth,
source.minWidth,
source.maxWidth,
source.height
);
}
}
},
onMouseUp: () => {
state.dragging = false;
window.document.body.classList.remove('no-select');
document.removeEventListener('mousemove', state.onMouseMove);
document.removeEventListener('mouseup', state.onMouseUp);
onResizeFinish && onResizeFinish();
},
};
}, props);
return state;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment