Как реализовано и в целом работает.
const LONG_CLICK_TOLERANCE_MS = 250;
const HEIGHT_TOLERANCE = 45;
const getCurrentTimeMS = () => {
return (new Date()).getTime();
};
const getClientY = (e) => {
if (e.clientY !== undefined) {
return e.clientY;
}
return e.touches[0].clientY;
};
const getDefaultMouseMove = () => {
return {
startedAtMS: null,
y: null,
initialHeight: null,
};
};
handleMoveStart = e => {
this.mouseMove = {
startedAtMS: getCurrentTimeMS(),
y: getClientY(e),
initialHeight: this.state.height,
};
document.addEventListener('mousemove', this.handleMoveProcess);
document.addEventListener('touchmove', this.handleMoveProcess);
document.addEventListener('mouseup', this.handleMoveEnd);
document.addEventListener('touchend', this.handleMoveEnd);
};
handleMoveProcess = e => {
if (this.mouseMove.startedAtMS === null) {
return;
}
if (getCurrentTimeMS() - this.mouseMove.startedAtMS >= LONG_CLICK_TOLERANCE_MS) {
const clientY = getClientY(e);
const heightChange = this.mouseMove.y - clientY;
const newHeight = this.mouseMove.initialHeight + heightChange;
if (document.body.clientHeight < newHeight + HEIGHT_TOLERANCE * 1.5) {
return;
}
if (newHeight < HEIGHT_TOLERANCE) {
return;
}
this.setState({
height: newHeight,
isResizing: true,
});
}
};
handleMoveEnd = e => {
if (getCurrentTimeMS() - this.mouseMove.startedAtMS < LONG_CLICK_TOLERANCE_MS) {
const newValue = !this.props.open;
this.setState({
height: newValue ? parseInt(document.body.clientHeight / 2) : HEIGHT_TOLERANCE,
isResizing: false,
}, () => {
this.props.onToggle(newValue);
});
}
this.mouseMove = getDefaultMouseMove();
document.removeEventListener('mousemove', this.handleMoveProcess);
document.removeEventListener('touchmove', this.handleMoveProcess);
document.removeEventListener('mouseup', this.handleMoveEnd);
document.removeEventListener('touchend', this.handleMoveEnd);
};
Таким образом, если длительность нажатия на элемент DOM дольше чем LONG_CLICK_TOLERANCE_MS, то handleMoveProcess начинает изменять высоту элемента, который нужно тянуть. Если длительность нажатия меньше, то считаем, что был просто клик и открывается тянущийся элемент на нужную высоту (полэкрана).
HEIGHT_TOLERANCE = 45 - высота, на сколько выдвигается "язычок" элемента, за который можно потянуть или кликнуть, чтобы показать его целиком.