@uiw/react-drag-event-interactive
Version:
react drag event interactive
78 lines (77 loc) • 3.22 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
var _excluded = ["prefixCls", "className", "onMove", "onDown"];
import React, { useRef, useState, useCallback, useEffect } from 'react';
import { isTouch, preventDefaultMove, getRelativePosition, useEventCallback } from "./utils.js";
import { jsx as _jsx } from "react/jsx-runtime";
export * from "./utils.js";
var Interactive = /*#__PURE__*/React.forwardRef((props, ref) => {
var {
prefixCls = 'w-color-interactive',
className,
onMove,
onDown
} = props,
reset = _objectWithoutPropertiesLoose(props, _excluded);
var container = useRef(null);
var hasTouched = useRef(false);
var [isDragging, setDragging] = useState(false);
var onMoveCallback = useEventCallback(onMove);
var onKeyCallback = useEventCallback(onDown);
// Prevent mobile browsers from handling mouse events (conflicting with touch ones).
// If we detected a touch interaction before, we prefer reacting to touch events only.
var isValid = event => {
if (hasTouched.current && !isTouch(event)) return false;
hasTouched.current = isTouch(event);
return true;
};
var handleMove = useCallback(event => {
preventDefaultMove(event);
if (!container.current) return;
var isDown = isTouch(event) ? event.touches.length > 0 : event.buttons > 0;
if (!isDown) {
setDragging(false);
return;
}
onMoveCallback == null || onMoveCallback(getRelativePosition(container.current, event), event);
}, [onMoveCallback]);
var handleMoveEnd = useCallback(() => setDragging(false), []);
var toggleDocumentEvents = useCallback(state => {
if (state) {
window.addEventListener(hasTouched.current ? 'touchmove' : 'mousemove', handleMove);
window.addEventListener(hasTouched.current ? 'touchend' : 'mouseup', handleMoveEnd);
} else {
window.removeEventListener('mousemove', handleMove);
window.removeEventListener('mouseup', handleMoveEnd);
window.removeEventListener('touchmove', handleMove);
window.removeEventListener('touchend', handleMoveEnd);
}
}, [handleMove, handleMoveEnd]);
useEffect(() => {
toggleDocumentEvents(isDragging);
return () => {
toggleDocumentEvents(false);
};
}, [isDragging, handleMove, handleMoveEnd, toggleDocumentEvents]);
var handleMoveStart = useCallback(event => {
var activeEl = document.activeElement;
activeEl == null || activeEl.blur();
preventDefaultMove(event.nativeEvent);
if (!isValid(event.nativeEvent)) return;
if (!container.current) return;
onKeyCallback == null || onKeyCallback(getRelativePosition(container.current, event.nativeEvent), event.nativeEvent);
setDragging(true);
}, [onKeyCallback]);
return /*#__PURE__*/_jsx("div", _extends({}, reset, {
className: [prefixCls, className || ''].filter(Boolean).join(' '),
style: _extends({}, reset.style, {
touchAction: 'none'
}),
ref: container,
tabIndex: 0,
onMouseDown: handleMoveStart,
onTouchStart: handleMoveStart
}));
});
Interactive.displayName = 'Interactive';
export default Interactive;