useDrag.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  9. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  10. var React = _interopRequireWildcard(require("react"));
  11. var _useEvent = _interopRequireDefault(require("rc-util/lib/hooks/useEvent"));
  12. var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
  13. var _context = require("../context");
  14. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  15. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  16. /** Drag to delete offset. It's a user experience number for dragging out */
  17. var REMOVE_DIST = 130;
  18. function getPosition(e) {
  19. var obj = 'targetTouches' in e ? e.targetTouches[0] : e;
  20. return {
  21. pageX: obj.pageX,
  22. pageY: obj.pageY
  23. };
  24. }
  25. function useDrag(containerRef, direction, rawValues, min, max, formatValue, triggerChange, finishChange, offsetValues, editable, minCount) {
  26. var _React$useState = React.useState(null),
  27. _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
  28. draggingValue = _React$useState2[0],
  29. setDraggingValue = _React$useState2[1];
  30. var _React$useState3 = React.useState(-1),
  31. _React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
  32. draggingIndex = _React$useState4[0],
  33. setDraggingIndex = _React$useState4[1];
  34. var _React$useState5 = React.useState(false),
  35. _React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
  36. draggingDelete = _React$useState6[0],
  37. setDraggingDelete = _React$useState6[1];
  38. var _React$useState7 = React.useState(rawValues),
  39. _React$useState8 = (0, _slicedToArray2.default)(_React$useState7, 2),
  40. cacheValues = _React$useState8[0],
  41. setCacheValues = _React$useState8[1];
  42. var _React$useState9 = React.useState(rawValues),
  43. _React$useState10 = (0, _slicedToArray2.default)(_React$useState9, 2),
  44. originValues = _React$useState10[0],
  45. setOriginValues = _React$useState10[1];
  46. var mouseMoveEventRef = React.useRef(null);
  47. var mouseUpEventRef = React.useRef(null);
  48. var touchEventTargetRef = React.useRef(null);
  49. var _React$useContext = React.useContext(_context.UnstableContext),
  50. onDragStart = _React$useContext.onDragStart,
  51. onDragChange = _React$useContext.onDragChange;
  52. (0, _useLayoutEffect.default)(function () {
  53. if (draggingIndex === -1) {
  54. setCacheValues(rawValues);
  55. }
  56. }, [rawValues, draggingIndex]);
  57. // Clean up event
  58. React.useEffect(function () {
  59. return function () {
  60. document.removeEventListener('mousemove', mouseMoveEventRef.current);
  61. document.removeEventListener('mouseup', mouseUpEventRef.current);
  62. if (touchEventTargetRef.current) {
  63. touchEventTargetRef.current.removeEventListener('touchmove', mouseMoveEventRef.current);
  64. touchEventTargetRef.current.removeEventListener('touchend', mouseUpEventRef.current);
  65. }
  66. };
  67. }, []);
  68. var flushValues = function flushValues(nextValues, nextValue, deleteMark) {
  69. // Perf: Only update state when value changed
  70. if (nextValue !== undefined) {
  71. setDraggingValue(nextValue);
  72. }
  73. setCacheValues(nextValues);
  74. var changeValues = nextValues;
  75. if (deleteMark) {
  76. changeValues = nextValues.filter(function (_, i) {
  77. return i !== draggingIndex;
  78. });
  79. }
  80. triggerChange(changeValues);
  81. if (onDragChange) {
  82. onDragChange({
  83. rawValues: nextValues,
  84. deleteIndex: deleteMark ? draggingIndex : -1,
  85. draggingIndex: draggingIndex,
  86. draggingValue: nextValue
  87. });
  88. }
  89. };
  90. var updateCacheValue = (0, _useEvent.default)(function (valueIndex, offsetPercent, deleteMark) {
  91. if (valueIndex === -1) {
  92. // >>>> Dragging on the track
  93. var startValue = originValues[0];
  94. var endValue = originValues[originValues.length - 1];
  95. var maxStartOffset = min - startValue;
  96. var maxEndOffset = max - endValue;
  97. // Get valid offset
  98. var offset = offsetPercent * (max - min);
  99. offset = Math.max(offset, maxStartOffset);
  100. offset = Math.min(offset, maxEndOffset);
  101. // Use first value to revert back of valid offset (like steps marks)
  102. var formatStartValue = formatValue(startValue + offset);
  103. offset = formatStartValue - startValue;
  104. var cloneCacheValues = originValues.map(function (val) {
  105. return val + offset;
  106. });
  107. flushValues(cloneCacheValues);
  108. } else {
  109. // >>>> Dragging on the handle
  110. var offsetDist = (max - min) * offsetPercent;
  111. // Always start with the valueIndex origin value
  112. var cloneValues = (0, _toConsumableArray2.default)(cacheValues);
  113. cloneValues[valueIndex] = originValues[valueIndex];
  114. var next = offsetValues(cloneValues, offsetDist, valueIndex, 'dist');
  115. flushValues(next.values, next.value, deleteMark);
  116. }
  117. });
  118. var onStartMove = function onStartMove(e, valueIndex, startValues) {
  119. e.stopPropagation();
  120. // 如果是点击 track 触发的,需要传入变化后的初始值,而不能直接用 rawValues
  121. var initialValues = startValues || rawValues;
  122. var originValue = initialValues[valueIndex];
  123. setDraggingIndex(valueIndex);
  124. setDraggingValue(originValue);
  125. setOriginValues(initialValues);
  126. setCacheValues(initialValues);
  127. setDraggingDelete(false);
  128. var _getPosition = getPosition(e),
  129. startX = _getPosition.pageX,
  130. startY = _getPosition.pageY;
  131. // We declare it here since closure can't get outer latest value
  132. var deleteMark = false;
  133. // Internal trigger event
  134. if (onDragStart) {
  135. onDragStart({
  136. rawValues: initialValues,
  137. draggingIndex: valueIndex,
  138. draggingValue: originValue
  139. });
  140. }
  141. // Moving
  142. var onMouseMove = function onMouseMove(event) {
  143. event.preventDefault();
  144. var _getPosition2 = getPosition(event),
  145. moveX = _getPosition2.pageX,
  146. moveY = _getPosition2.pageY;
  147. var offsetX = moveX - startX;
  148. var offsetY = moveY - startY;
  149. var _containerRef$current = containerRef.current.getBoundingClientRect(),
  150. width = _containerRef$current.width,
  151. height = _containerRef$current.height;
  152. var offSetPercent;
  153. var removeDist;
  154. switch (direction) {
  155. case 'btt':
  156. offSetPercent = -offsetY / height;
  157. removeDist = offsetX;
  158. break;
  159. case 'ttb':
  160. offSetPercent = offsetY / height;
  161. removeDist = offsetX;
  162. break;
  163. case 'rtl':
  164. offSetPercent = -offsetX / width;
  165. removeDist = offsetY;
  166. break;
  167. default:
  168. offSetPercent = offsetX / width;
  169. removeDist = offsetY;
  170. }
  171. // Check if need mark remove
  172. deleteMark = editable ? Math.abs(removeDist) > REMOVE_DIST && minCount < cacheValues.length : false;
  173. setDraggingDelete(deleteMark);
  174. updateCacheValue(valueIndex, offSetPercent, deleteMark);
  175. };
  176. // End
  177. var onMouseUp = function onMouseUp(event) {
  178. event.preventDefault();
  179. document.removeEventListener('mouseup', onMouseUp);
  180. document.removeEventListener('mousemove', onMouseMove);
  181. if (touchEventTargetRef.current) {
  182. touchEventTargetRef.current.removeEventListener('touchmove', mouseMoveEventRef.current);
  183. touchEventTargetRef.current.removeEventListener('touchend', mouseUpEventRef.current);
  184. }
  185. mouseMoveEventRef.current = null;
  186. mouseUpEventRef.current = null;
  187. touchEventTargetRef.current = null;
  188. finishChange(deleteMark);
  189. setDraggingIndex(-1);
  190. setDraggingDelete(false);
  191. };
  192. document.addEventListener('mouseup', onMouseUp);
  193. document.addEventListener('mousemove', onMouseMove);
  194. e.currentTarget.addEventListener('touchend', onMouseUp);
  195. e.currentTarget.addEventListener('touchmove', onMouseMove);
  196. mouseMoveEventRef.current = onMouseMove;
  197. mouseUpEventRef.current = onMouseUp;
  198. touchEventTargetRef.current = e.currentTarget;
  199. };
  200. // Only return cache value when it mapping with rawValues
  201. var returnValues = React.useMemo(function () {
  202. var sourceValues = (0, _toConsumableArray2.default)(rawValues).sort(function (a, b) {
  203. return a - b;
  204. });
  205. var targetValues = (0, _toConsumableArray2.default)(cacheValues).sort(function (a, b) {
  206. return a - b;
  207. });
  208. var counts = {};
  209. targetValues.forEach(function (val) {
  210. counts[val] = (counts[val] || 0) + 1;
  211. });
  212. sourceValues.forEach(function (val) {
  213. counts[val] = (counts[val] || 0) - 1;
  214. });
  215. var maxDiffCount = editable ? 1 : 0;
  216. var diffCount = Object.values(counts).reduce(function (prev, next) {
  217. return prev + Math.abs(next);
  218. }, 0);
  219. return diffCount <= maxDiffCount ? cacheValues : rawValues;
  220. }, [rawValues, cacheValues, editable]);
  221. return [draggingIndex, draggingValue, draggingDelete, returnValues, onStartMove];
  222. }
  223. var _default = exports.default = useDrag;