UNPKG

@uiw/react-drag-event-interactive

Version:
78 lines (77 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.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;