UNPKG

@uiw/react-drag-event-interactive

Version:
73 lines (72 loc) 3.22 kB
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;