@uiw/react-drag-event-interactive
Version:
react drag event interactive
73 lines (72 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';
import { jsx as _jsx } from "react/jsx-runtime";
export * from './utils';
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 user moves the pointer outside of the window or iframe bounds and release it there,
// `mouseup`/`touchend` won't be fired. In order to stop the picker from following the cursor
// after the user has moved the mouse/finger back to the document, we check `event.buttons`
// and `event.touches`. It allows us to detect that the user is just moving his pointer
// without pressing it down
var isDown = isTouch(event) ? event.touches.length > 0 : event.buttons > 0;
if (isDown && container.current) {
onMoveCallback && onMoveCallback(getRelativePosition(container.current, event), event);
} else {
setDragging(false);
}
}, [onMoveCallback]);
var handleMoveEnd = useCallback(() => setDragging(false), []);
var toggleDocumentEvents = useCallback(state => {
var toggleEvent = state ? window.addEventListener : window.removeEventListener;
toggleEvent(hasTouched.current ? 'touchmove' : 'mousemove', handleMove);
toggleEvent(hasTouched.current ? 'touchend' : 'mouseup', handleMoveEnd);
}, []);
useEffect(() => {
toggleDocumentEvents(isDragging);
return () => {
isDragging && toggleDocumentEvents(false);
};
}, [isDragging, toggleDocumentEvents]);
var handleMoveStart = useCallback(event => {
preventDefaultMove(event.nativeEvent);
if (!isValid(event.nativeEvent)) return;
onKeyCallback && 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;