ahooks
Version:
react hooks library
227 lines (226 loc) • 8.92 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _react = require("react");
var _useLatest = _interopRequireDefault(require("../useLatest"));
var _domTarget = require("../utils/domTarget");
var _useEffectWithTarget = _interopRequireDefault(require("../utils/useEffectWithTarget"));
function useLongPress(onLongPress, target) {
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref$delay = _ref.delay,
delay = _ref$delay === void 0 ? 300 : _ref$delay,
moveThreshold = _ref.moveThreshold,
onClick = _ref.onClick,
onLongPressEnd = _ref.onLongPressEnd;
var onLongPressRef = (0, _useLatest["default"])(onLongPress);
var onClickRef = (0, _useLatest["default"])(onClick);
var onLongPressEndRef = (0, _useLatest["default"])(onLongPressEnd);
var timerRef = (0, _react.useRef)(undefined);
var isTriggeredRef = (0, _react.useRef)(false);
var pervPositionRef = (0, _react.useRef)({
x: 0,
y: 0
});
var activePointerIdRef = (0, _react.useRef)(undefined);
var mousePressed = (0, _react.useRef)(false);
var touchPressed = (0, _react.useRef)(false);
var hasMoveThreshold = !!((moveThreshold === null || moveThreshold === void 0 ? void 0 : moveThreshold.x) && moveThreshold.x > 0 || (moveThreshold === null || moveThreshold === void 0 ? void 0 : moveThreshold.y) && moveThreshold.y > 0);
(0, _useEffectWithTarget["default"])(function () {
var targetElement = (0, _domTarget.getTargetElement)(target);
if (!(targetElement === null || targetElement === void 0 ? void 0 : targetElement.addEventListener)) {
return;
}
var supportPointerEvent = typeof window !== 'undefined' && typeof window.PointerEvent === 'function';
var overThreshold = function overThreshold(event) {
var _getClientPosition = getClientPosition(event),
clientX = _getClientPosition.clientX,
clientY = _getClientPosition.clientY;
var offsetX = Math.abs(clientX - pervPositionRef.current.x);
var offsetY = Math.abs(clientY - pervPositionRef.current.y);
return !!((moveThreshold === null || moveThreshold === void 0 ? void 0 : moveThreshold.x) && offsetX > moveThreshold.x || (moveThreshold === null || moveThreshold === void 0 ? void 0 : moveThreshold.y) && offsetY > moveThreshold.y);
};
function getClientPosition(event) {
if ('TouchEvent' in window && event instanceof TouchEvent) {
return {
clientX: event.touches[0].clientX,
clientY: event.touches[0].clientY
};
}
if (event instanceof MouseEvent) {
return {
clientX: event.clientX,
clientY: event.clientY
};
}
return {
clientX: 0,
clientY: 0
};
}
var createTimer = function createTimer(event) {
timerRef.current = setTimeout(function () {
onLongPressRef.current(event);
isTriggeredRef.current = true;
}, delay);
};
var clearTimer = function clearTimer() {
if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = undefined;
}
};
var finishPress = function finishPress(event) {
var triggerClick = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var _a;
clearTimer();
if (isTriggeredRef.current) {
(_a = onLongPressEndRef.current) === null || _a === void 0 ? void 0 : _a.call(onLongPressEndRef, event);
} else if (triggerClick && onClickRef.current) {
onClickRef.current(event);
}
isTriggeredRef.current = false;
};
var onPointerDown = function onPointerDown(event) {
if (activePointerIdRef.current !== undefined || event.isPrimary === false) {
return;
}
activePointerIdRef.current = event.pointerId;
if (hasMoveThreshold) {
pervPositionRef.current.x = event.clientX;
pervPositionRef.current.y = event.clientY;
}
createTimer(event);
};
var onPointerUp = function onPointerUp(event) {
if (activePointerIdRef.current !== event.pointerId) {
return;
}
activePointerIdRef.current = undefined;
finishPress(event);
};
var onPointerCancel = function onPointerCancel(event) {
if (activePointerIdRef.current !== event.pointerId) {
return;
}
activePointerIdRef.current = undefined;
finishPress(event, false);
};
var onPointerMove = function onPointerMove(event) {
if (activePointerIdRef.current === event.pointerId) {
onMove(event);
}
};
var onTouchStart = function onTouchStart(event) {
if (touchPressed.current) {
return;
}
touchPressed.current = true;
if (hasMoveThreshold) {
var _getClientPosition2 = getClientPosition(event),
clientX = _getClientPosition2.clientX,
clientY = _getClientPosition2.clientY;
pervPositionRef.current.x = clientX;
pervPositionRef.current.y = clientY;
}
createTimer(event);
};
var onMouseDown = function onMouseDown(event) {
var _a;
if ((_a = event === null || event === void 0 ? void 0 : event.sourceCapabilities) === null || _a === void 0 ? void 0 : _a.firesTouchEvents) {
return;
}
mousePressed.current = true;
if (hasMoveThreshold) {
pervPositionRef.current.x = event.clientX;
pervPositionRef.current.y = event.clientY;
}
createTimer(event);
};
var onMove = function onMove(event) {
if (timerRef.current && overThreshold(event)) {
clearTimer();
}
};
var onTouchEnd = function onTouchEnd(event) {
if (!touchPressed.current) {
return;
}
touchPressed.current = false;
finishPress(event);
};
var onMouseUp = function onMouseUp(event) {
var _a;
if ((_a = event === null || event === void 0 ? void 0 : event.sourceCapabilities) === null || _a === void 0 ? void 0 : _a.firesTouchEvents) {
return;
}
if (!mousePressed.current) {
return;
}
mousePressed.current = false;
finishPress(event);
};
var onMouseLeave = function onMouseLeave(event) {
if (!mousePressed.current) {
return;
}
mousePressed.current = false;
finishPress(event, false);
};
if (supportPointerEvent) {
targetElement.addEventListener('pointerdown', onPointerDown);
targetElement.addEventListener('pointerup', onPointerUp);
targetElement.addEventListener('pointerleave', onPointerCancel);
targetElement.addEventListener('pointercancel', onPointerCancel);
if (hasMoveThreshold) {
targetElement.addEventListener('pointermove', onPointerMove);
}
return function () {
clearTimer();
isTriggeredRef.current = false;
activePointerIdRef.current = undefined;
targetElement.removeEventListener('pointerdown', onPointerDown);
targetElement.removeEventListener('pointerup', onPointerUp);
targetElement.removeEventListener('pointerleave', onPointerCancel);
targetElement.removeEventListener('pointercancel', onPointerCancel);
if (hasMoveThreshold) {
targetElement.removeEventListener('pointermove', onPointerMove);
}
};
}
var onTouchCancel = function onTouchCancel(event) {
if (!touchPressed.current) {
return;
}
touchPressed.current = false;
finishPress(event, false);
};
targetElement.addEventListener('mousedown', onMouseDown);
targetElement.addEventListener('mouseup', onMouseUp);
targetElement.addEventListener('mouseleave', onMouseLeave);
targetElement.addEventListener('touchstart', onTouchStart);
targetElement.addEventListener('touchend', onTouchEnd);
targetElement.addEventListener('touchcancel', onTouchCancel);
if (hasMoveThreshold) {
targetElement.addEventListener('mousemove', onMove);
targetElement.addEventListener('touchmove', onMove);
}
return function () {
clearTimer();
isTriggeredRef.current = false;
targetElement.removeEventListener('mousedown', onMouseDown);
targetElement.removeEventListener('mouseup', onMouseUp);
targetElement.removeEventListener('mouseleave', onMouseLeave);
targetElement.removeEventListener('touchstart', onTouchStart);
targetElement.removeEventListener('touchend', onTouchEnd);
targetElement.removeEventListener('touchcancel', onTouchCancel);
if (hasMoveThreshold) {
targetElement.removeEventListener('mousemove', onMove);
targetElement.removeEventListener('touchmove', onMove);
}
};
}, [], target);
}
var _default = exports["default"] = useLongPress;