MotionThumb.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  3. import classNames from 'classnames';
  4. import CSSMotion from 'rc-motion';
  5. import useLayoutEffect from "rc-util/es/hooks/useLayoutEffect";
  6. import { composeRef } from "rc-util/es/ref";
  7. import * as React from 'react';
  8. var calcThumbStyle = function calcThumbStyle(targetElement, vertical) {
  9. if (!targetElement) return null;
  10. var style = {
  11. left: targetElement.offsetLeft,
  12. right: targetElement.parentElement.clientWidth - targetElement.clientWidth - targetElement.offsetLeft,
  13. width: targetElement.clientWidth,
  14. top: targetElement.offsetTop,
  15. bottom: targetElement.parentElement.clientHeight - targetElement.clientHeight - targetElement.offsetTop,
  16. height: targetElement.clientHeight
  17. };
  18. if (vertical) {
  19. // Adjusts positioning and size for vertical layout by setting horizontal properties to 0 and using vertical properties from the style object.
  20. return {
  21. left: 0,
  22. right: 0,
  23. width: 0,
  24. top: style.top,
  25. bottom: style.bottom,
  26. height: style.height
  27. };
  28. }
  29. return {
  30. left: style.left,
  31. right: style.right,
  32. width: style.width,
  33. top: 0,
  34. bottom: 0,
  35. height: 0
  36. };
  37. };
  38. var toPX = function toPX(value) {
  39. return value !== undefined ? "".concat(value, "px") : undefined;
  40. };
  41. export default function MotionThumb(props) {
  42. var prefixCls = props.prefixCls,
  43. containerRef = props.containerRef,
  44. value = props.value,
  45. getValueIndex = props.getValueIndex,
  46. motionName = props.motionName,
  47. onMotionStart = props.onMotionStart,
  48. onMotionEnd = props.onMotionEnd,
  49. direction = props.direction,
  50. _props$vertical = props.vertical,
  51. vertical = _props$vertical === void 0 ? false : _props$vertical;
  52. var thumbRef = React.useRef(null);
  53. var _React$useState = React.useState(value),
  54. _React$useState2 = _slicedToArray(_React$useState, 2),
  55. prevValue = _React$useState2[0],
  56. setPrevValue = _React$useState2[1];
  57. // =========================== Effect ===========================
  58. var findValueElement = function findValueElement(val) {
  59. var _containerRef$current;
  60. var index = getValueIndex(val);
  61. var ele = (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.querySelectorAll(".".concat(prefixCls, "-item"))[index];
  62. return (ele === null || ele === void 0 ? void 0 : ele.offsetParent) && ele;
  63. };
  64. var _React$useState3 = React.useState(null),
  65. _React$useState4 = _slicedToArray(_React$useState3, 2),
  66. prevStyle = _React$useState4[0],
  67. setPrevStyle = _React$useState4[1];
  68. var _React$useState5 = React.useState(null),
  69. _React$useState6 = _slicedToArray(_React$useState5, 2),
  70. nextStyle = _React$useState6[0],
  71. setNextStyle = _React$useState6[1];
  72. useLayoutEffect(function () {
  73. if (prevValue !== value) {
  74. var prev = findValueElement(prevValue);
  75. var next = findValueElement(value);
  76. var calcPrevStyle = calcThumbStyle(prev, vertical);
  77. var calcNextStyle = calcThumbStyle(next, vertical);
  78. setPrevValue(value);
  79. setPrevStyle(calcPrevStyle);
  80. setNextStyle(calcNextStyle);
  81. if (prev && next) {
  82. onMotionStart();
  83. } else {
  84. onMotionEnd();
  85. }
  86. }
  87. }, [value]);
  88. var thumbStart = React.useMemo(function () {
  89. if (vertical) {
  90. var _prevStyle$top;
  91. return toPX((_prevStyle$top = prevStyle === null || prevStyle === void 0 ? void 0 : prevStyle.top) !== null && _prevStyle$top !== void 0 ? _prevStyle$top : 0);
  92. }
  93. if (direction === 'rtl') {
  94. return toPX(-(prevStyle === null || prevStyle === void 0 ? void 0 : prevStyle.right));
  95. }
  96. return toPX(prevStyle === null || prevStyle === void 0 ? void 0 : prevStyle.left);
  97. }, [vertical, direction, prevStyle]);
  98. var thumbActive = React.useMemo(function () {
  99. if (vertical) {
  100. var _nextStyle$top;
  101. return toPX((_nextStyle$top = nextStyle === null || nextStyle === void 0 ? void 0 : nextStyle.top) !== null && _nextStyle$top !== void 0 ? _nextStyle$top : 0);
  102. }
  103. if (direction === 'rtl') {
  104. return toPX(-(nextStyle === null || nextStyle === void 0 ? void 0 : nextStyle.right));
  105. }
  106. return toPX(nextStyle === null || nextStyle === void 0 ? void 0 : nextStyle.left);
  107. }, [vertical, direction, nextStyle]);
  108. // =========================== Motion ===========================
  109. var onAppearStart = function onAppearStart() {
  110. if (vertical) {
  111. return {
  112. transform: 'translateY(var(--thumb-start-top))',
  113. height: 'var(--thumb-start-height)'
  114. };
  115. }
  116. return {
  117. transform: 'translateX(var(--thumb-start-left))',
  118. width: 'var(--thumb-start-width)'
  119. };
  120. };
  121. var onAppearActive = function onAppearActive() {
  122. if (vertical) {
  123. return {
  124. transform: 'translateY(var(--thumb-active-top))',
  125. height: 'var(--thumb-active-height)'
  126. };
  127. }
  128. return {
  129. transform: 'translateX(var(--thumb-active-left))',
  130. width: 'var(--thumb-active-width)'
  131. };
  132. };
  133. var onVisibleChanged = function onVisibleChanged() {
  134. setPrevStyle(null);
  135. setNextStyle(null);
  136. onMotionEnd();
  137. };
  138. // =========================== Render ===========================
  139. // No need motion when nothing exist in queue
  140. if (!prevStyle || !nextStyle) {
  141. return null;
  142. }
  143. return /*#__PURE__*/React.createElement(CSSMotion, {
  144. visible: true,
  145. motionName: motionName,
  146. motionAppear: true,
  147. onAppearStart: onAppearStart,
  148. onAppearActive: onAppearActive,
  149. onVisibleChanged: onVisibleChanged
  150. }, function (_ref, ref) {
  151. var motionClassName = _ref.className,
  152. motionStyle = _ref.style;
  153. var mergedStyle = _objectSpread(_objectSpread({}, motionStyle), {}, {
  154. '--thumb-start-left': thumbStart,
  155. '--thumb-start-width': toPX(prevStyle === null || prevStyle === void 0 ? void 0 : prevStyle.width),
  156. '--thumb-active-left': thumbActive,
  157. '--thumb-active-width': toPX(nextStyle === null || nextStyle === void 0 ? void 0 : nextStyle.width),
  158. '--thumb-start-top': thumbStart,
  159. '--thumb-start-height': toPX(prevStyle === null || prevStyle === void 0 ? void 0 : prevStyle.height),
  160. '--thumb-active-top': thumbActive,
  161. '--thumb-active-height': toPX(nextStyle === null || nextStyle === void 0 ? void 0 : nextStyle.height)
  162. });
  163. // It's little ugly which should be refactor when @umi/test update to latest jsdom
  164. var motionProps = {
  165. ref: composeRef(thumbRef, ref),
  166. style: mergedStyle,
  167. className: classNames("".concat(prefixCls, "-thumb"), motionClassName)
  168. };
  169. if (process.env.NODE_ENV === 'test') {
  170. motionProps['data-test-style'] = JSON.stringify(mergedStyle);
  171. }
  172. return /*#__PURE__*/React.createElement("div", motionProps);
  173. });
  174. }