@ccs-design/rc-pro
Version:
ccs design basic react component
181 lines (146 loc) • 6.94 kB
JavaScript
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
import * as React from 'react';
import { useState, useRef } from 'react';
var MIN_SWIPE_DISTANCE = 0.1;
var STOP_SWIPE_DISTANCE = 0.01;
var REFRESH_INTERVAL = 20;
var SPEED_OFF_MULTIPLE = Math.pow(0.995, REFRESH_INTERVAL); // ================================= Hook =================================
export default function useTouchMove(ref, onOffset) {
var _useState = useState(),
_useState2 = _slicedToArray(_useState, 2),
touchPosition = _useState2[0],
setTouchPosition = _useState2[1];
var _useState3 = useState(0),
_useState4 = _slicedToArray(_useState3, 2),
lastTimestamp = _useState4[0],
setLastTimestamp = _useState4[1];
var _useState5 = useState(0),
_useState6 = _slicedToArray(_useState5, 2),
lastTimeDiff = _useState6[0],
setLastTimeDiff = _useState6[1];
var _useState7 = useState(),
_useState8 = _slicedToArray(_useState7, 2),
lastOffset = _useState8[0],
setLastOffset = _useState8[1];
var motionRef = useRef(); // ========================= Events =========================
// >>> Touch events
function onTouchStart(e) {
var _e$touches$ = e.touches[0],
screenX = _e$touches$.screenX,
screenY = _e$touches$.screenY;
setTouchPosition({
x: screenX,
y: screenY
});
window.clearInterval(motionRef.current);
}
function onTouchMove(e) {
if (!touchPosition) return;
e.preventDefault();
var _e$touches$2 = e.touches[0],
screenX = _e$touches$2.screenX,
screenY = _e$touches$2.screenY;
setTouchPosition({
x: screenX,
y: screenY
});
var offsetX = screenX - touchPosition.x;
var offsetY = screenY - touchPosition.y;
onOffset(offsetX, offsetY);
var now = Date.now();
setLastTimestamp(now);
setLastTimeDiff(now - lastTimestamp);
setLastOffset({
x: offsetX,
y: offsetY
});
}
function onTouchEnd() {
if (!touchPosition) return;
setTouchPosition(null);
setLastOffset(null); // Swipe if needed
if (lastOffset) {
var distanceX = lastOffset.x / lastTimeDiff;
var distanceY = lastOffset.y / lastTimeDiff;
var absX = Math.abs(distanceX);
var absY = Math.abs(distanceY); // Skip swipe if low distance
if (Math.max(absX, absY) < MIN_SWIPE_DISTANCE) return;
var currentX = distanceX;
var currentY = distanceY;
motionRef.current = window.setInterval(function () {
if (Math.abs(currentX) < STOP_SWIPE_DISTANCE && Math.abs(currentY) < STOP_SWIPE_DISTANCE) {
window.clearInterval(motionRef.current);
return;
}
currentX *= SPEED_OFF_MULTIPLE;
currentY *= SPEED_OFF_MULTIPLE;
onOffset(currentX * REFRESH_INTERVAL, currentY * REFRESH_INTERVAL);
}, REFRESH_INTERVAL);
}
} // >>> Wheel event
var lastWheelDirectionRef = useRef();
function onWheel(e) {
var deltaX = e.deltaX,
deltaY = e.deltaY; // Convert both to x & y since wheel only happened on PC
var mixed = 0;
var absX = Math.abs(deltaX);
var absY = Math.abs(deltaY);
if (absX === absY) {
mixed = lastWheelDirectionRef.current === 'x' ? deltaX : deltaY;
} else if (absX > absY) {
mixed = deltaX;
lastWheelDirectionRef.current = 'x';
} else {
mixed = deltaY;
lastWheelDirectionRef.current = 'y';
}
if (onOffset(-mixed, -mixed)) {
e.preventDefault();
}
} // ========================= Effect =========================
var touchEventsRef = useRef(null);
touchEventsRef.current = {
onTouchStart: onTouchStart,
onTouchMove: onTouchMove,
onTouchEnd: onTouchEnd,
onWheel: onWheel
};
React.useEffect(function () {
var _ref$current, _ref$current2;
function onProxyTouchStart(e) {
var _touchEventsRef$curre;
(_touchEventsRef$curre = touchEventsRef.current) === null || _touchEventsRef$curre === void 0 ? void 0 : _touchEventsRef$curre.onTouchStart(e);
}
function onProxyTouchMove(e) {
var _touchEventsRef$curre2;
(_touchEventsRef$curre2 = touchEventsRef.current) === null || _touchEventsRef$curre2 === void 0 ? void 0 : _touchEventsRef$curre2.onTouchMove(e);
}
function onProxyTouchEnd(e) {
var _touchEventsRef$curre3;
(_touchEventsRef$curre3 = touchEventsRef.current) === null || _touchEventsRef$curre3 === void 0 ? void 0 : _touchEventsRef$curre3.onTouchEnd(e);
}
function onProxyWheel(e) {
var _touchEventsRef$curre4;
(_touchEventsRef$curre4 = touchEventsRef.current) === null || _touchEventsRef$curre4 === void 0 ? void 0 : _touchEventsRef$curre4.onWheel(e);
}
document.addEventListener('touchmove', onProxyTouchMove, {
passive: false
});
document.addEventListener('touchend', onProxyTouchEnd, {
passive: false
}); // No need to clean up since element removed
(_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.addEventListener('touchstart', onProxyTouchStart, {
passive: false
});
(_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.addEventListener('wheel', onProxyWheel);
return function () {
document.removeEventListener('touchmove', onProxyTouchMove);
document.removeEventListener('touchend', onProxyTouchEnd);
};
}, []);
}