CSSMotion.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  2. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  3. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  4. import _typeof from "@babel/runtime/helpers/esm/typeof";
  5. /* eslint-disable react/default-props-match-prop-types, react/no-multi-comp, react/prop-types */
  6. import classNames from 'classnames';
  7. import findDOMNode from "rc-util/es/Dom/findDOMNode";
  8. import { fillRef, getNodeRef, supportRef } from "rc-util/es/ref";
  9. import * as React from 'react';
  10. import { useRef } from 'react';
  11. import { Context } from "./context";
  12. import DomWrapper from "./DomWrapper";
  13. import useStatus from "./hooks/useStatus";
  14. import { isActive } from "./hooks/useStepQueue";
  15. import { STATUS_NONE, STEP_PREPARE, STEP_START } from "./interface";
  16. import { getTransitionName, supportTransition } from "./util/motion";
  17. /**
  18. * `transitionSupport` is used for none transition test case.
  19. * Default we use browser transition event support check.
  20. */
  21. export function genCSSMotion(config) {
  22. var transitionSupport = config;
  23. if (_typeof(config) === 'object') {
  24. transitionSupport = config.transitionSupport;
  25. }
  26. function isSupportTransition(props, contextMotion) {
  27. return !!(props.motionName && transitionSupport && contextMotion !== false);
  28. }
  29. var CSSMotion = /*#__PURE__*/React.forwardRef(function (props, ref) {
  30. var _props$visible = props.visible,
  31. visible = _props$visible === void 0 ? true : _props$visible,
  32. _props$removeOnLeave = props.removeOnLeave,
  33. removeOnLeave = _props$removeOnLeave === void 0 ? true : _props$removeOnLeave,
  34. forceRender = props.forceRender,
  35. children = props.children,
  36. motionName = props.motionName,
  37. leavedClassName = props.leavedClassName,
  38. eventProps = props.eventProps;
  39. var _React$useContext = React.useContext(Context),
  40. contextMotion = _React$useContext.motion;
  41. var supportMotion = isSupportTransition(props, contextMotion);
  42. // Ref to the react node, it may be a HTMLElement
  43. var nodeRef = useRef();
  44. // Ref to the dom wrapper in case ref can not pass to HTMLElement
  45. var wrapperNodeRef = useRef();
  46. function getDomElement() {
  47. try {
  48. // Here we're avoiding call for findDOMNode since it's deprecated
  49. // in strict mode. We're calling it only when node ref is not
  50. // an instance of DOM HTMLElement. Otherwise use
  51. // findDOMNode as a final resort
  52. return nodeRef.current instanceof HTMLElement ? nodeRef.current : findDOMNode(wrapperNodeRef.current);
  53. } catch (e) {
  54. // Only happen when `motionDeadline` trigger but element removed.
  55. return null;
  56. }
  57. }
  58. var _useStatus = useStatus(supportMotion, visible, getDomElement, props),
  59. _useStatus2 = _slicedToArray(_useStatus, 4),
  60. status = _useStatus2[0],
  61. statusStep = _useStatus2[1],
  62. statusStyle = _useStatus2[2],
  63. mergedVisible = _useStatus2[3];
  64. // Record whether content has rendered
  65. // Will return null for un-rendered even when `removeOnLeave={false}`
  66. var renderedRef = React.useRef(mergedVisible);
  67. if (mergedVisible) {
  68. renderedRef.current = true;
  69. }
  70. // ====================== Refs ======================
  71. var setNodeRef = React.useCallback(function (node) {
  72. nodeRef.current = node;
  73. fillRef(ref, node);
  74. }, [ref]);
  75. // ===================== Render =====================
  76. var motionChildren;
  77. var mergedProps = _objectSpread(_objectSpread({}, eventProps), {}, {
  78. visible: visible
  79. });
  80. if (!children) {
  81. // No children
  82. motionChildren = null;
  83. } else if (status === STATUS_NONE) {
  84. // Stable children
  85. if (mergedVisible) {
  86. motionChildren = children(_objectSpread({}, mergedProps), setNodeRef);
  87. } else if (!removeOnLeave && renderedRef.current && leavedClassName) {
  88. motionChildren = children(_objectSpread(_objectSpread({}, mergedProps), {}, {
  89. className: leavedClassName
  90. }), setNodeRef);
  91. } else if (forceRender || !removeOnLeave && !leavedClassName) {
  92. motionChildren = children(_objectSpread(_objectSpread({}, mergedProps), {}, {
  93. style: {
  94. display: 'none'
  95. }
  96. }), setNodeRef);
  97. } else {
  98. motionChildren = null;
  99. }
  100. } else {
  101. // In motion
  102. var statusSuffix;
  103. if (statusStep === STEP_PREPARE) {
  104. statusSuffix = 'prepare';
  105. } else if (isActive(statusStep)) {
  106. statusSuffix = 'active';
  107. } else if (statusStep === STEP_START) {
  108. statusSuffix = 'start';
  109. }
  110. var motionCls = getTransitionName(motionName, "".concat(status, "-").concat(statusSuffix));
  111. motionChildren = children(_objectSpread(_objectSpread({}, mergedProps), {}, {
  112. className: classNames(getTransitionName(motionName, status), _defineProperty(_defineProperty({}, motionCls, motionCls && statusSuffix), motionName, typeof motionName === 'string')),
  113. style: statusStyle
  114. }), setNodeRef);
  115. }
  116. // Auto inject ref if child node not have `ref` props
  117. if ( /*#__PURE__*/React.isValidElement(motionChildren) && supportRef(motionChildren)) {
  118. var originNodeRef = getNodeRef(motionChildren);
  119. if (!originNodeRef) {
  120. motionChildren = /*#__PURE__*/React.cloneElement(motionChildren, {
  121. ref: setNodeRef
  122. });
  123. }
  124. }
  125. return /*#__PURE__*/React.createElement(DomWrapper, {
  126. ref: wrapperNodeRef
  127. }, motionChildren);
  128. });
  129. CSSMotion.displayName = 'CSSMotion';
  130. return CSSMotion;
  131. }
  132. export default genCSSMotion(supportTransition);