Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

354 řádky
11 KiB

  1. import _extends from 'babel-runtime/helpers/extends';
  2. import _defineProperty from 'babel-runtime/helpers/defineProperty';
  3. import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
  4. import _createClass from 'babel-runtime/helpers/createClass';
  5. import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
  6. import _inherits from 'babel-runtime/helpers/inherits';
  7. import React from 'react';
  8. import PropTypes from 'prop-types';
  9. import unsafeLifecyclesPolyfill from 'rc-util/es/unsafeLifecyclesPolyfill';
  10. import { toArrayChildren, mergeChildren, findShownChildInChildrenByKey, findChildInChildrenByKey, isSameChildren } from './ChildrenUtils';
  11. import AnimateChild from './AnimateChild';
  12. import animUtil from './util/animate';
  13. var defaultKey = 'rc_animate_' + Date.now();
  14. function getChildrenFromProps(props) {
  15. var children = props.children;
  16. if (React.isValidElement(children)) {
  17. if (!children.key) {
  18. return React.cloneElement(children, {
  19. key: defaultKey
  20. });
  21. }
  22. }
  23. return children;
  24. }
  25. function noop() {}
  26. var Animate = function (_React$Component) {
  27. _inherits(Animate, _React$Component);
  28. // eslint-disable-line
  29. function Animate(props) {
  30. _classCallCheck(this, Animate);
  31. var _this = _possibleConstructorReturn(this, (Animate.__proto__ || Object.getPrototypeOf(Animate)).call(this, props));
  32. _initialiseProps.call(_this);
  33. _this.currentlyAnimatingKeys = {};
  34. _this.keysToEnter = [];
  35. _this.keysToLeave = [];
  36. _this.state = {
  37. children: toArrayChildren(getChildrenFromProps(props))
  38. };
  39. _this.childrenRefs = {};
  40. return _this;
  41. }
  42. _createClass(Animate, [{
  43. key: 'componentDidMount',
  44. value: function componentDidMount() {
  45. var _this2 = this;
  46. var showProp = this.props.showProp;
  47. var children = this.state.children;
  48. if (showProp) {
  49. children = children.filter(function (child) {
  50. return !!child.props[showProp];
  51. });
  52. }
  53. children.forEach(function (child) {
  54. if (child) {
  55. _this2.performAppear(child.key);
  56. }
  57. });
  58. }
  59. }, {
  60. key: 'componentWillReceiveProps',
  61. value: function componentWillReceiveProps(nextProps) {
  62. var _this3 = this;
  63. this.nextProps = nextProps;
  64. var nextChildren = toArrayChildren(getChildrenFromProps(nextProps));
  65. var props = this.props;
  66. // exclusive needs immediate response
  67. if (props.exclusive) {
  68. Object.keys(this.currentlyAnimatingKeys).forEach(function (key) {
  69. _this3.stop(key);
  70. });
  71. }
  72. var showProp = props.showProp;
  73. var currentlyAnimatingKeys = this.currentlyAnimatingKeys;
  74. // last props children if exclusive
  75. var currentChildren = props.exclusive ? toArrayChildren(getChildrenFromProps(props)) : this.state.children;
  76. // in case destroy in showProp mode
  77. var newChildren = [];
  78. if (showProp) {
  79. currentChildren.forEach(function (currentChild) {
  80. var nextChild = currentChild && findChildInChildrenByKey(nextChildren, currentChild.key);
  81. var newChild = void 0;
  82. if ((!nextChild || !nextChild.props[showProp]) && currentChild.props[showProp]) {
  83. newChild = React.cloneElement(nextChild || currentChild, _defineProperty({}, showProp, true));
  84. } else {
  85. newChild = nextChild;
  86. }
  87. if (newChild) {
  88. newChildren.push(newChild);
  89. }
  90. });
  91. nextChildren.forEach(function (nextChild) {
  92. if (!nextChild || !findChildInChildrenByKey(currentChildren, nextChild.key)) {
  93. newChildren.push(nextChild);
  94. }
  95. });
  96. } else {
  97. newChildren = mergeChildren(currentChildren, nextChildren);
  98. }
  99. // need render to avoid update
  100. this.setState({
  101. children: newChildren
  102. });
  103. nextChildren.forEach(function (child) {
  104. var key = child && child.key;
  105. if (child && currentlyAnimatingKeys[key]) {
  106. return;
  107. }
  108. var hasPrev = child && findChildInChildrenByKey(currentChildren, key);
  109. if (showProp) {
  110. var showInNext = child.props[showProp];
  111. if (hasPrev) {
  112. var showInNow = findShownChildInChildrenByKey(currentChildren, key, showProp);
  113. if (!showInNow && showInNext) {
  114. _this3.keysToEnter.push(key);
  115. }
  116. } else if (showInNext) {
  117. _this3.keysToEnter.push(key);
  118. }
  119. } else if (!hasPrev) {
  120. _this3.keysToEnter.push(key);
  121. }
  122. });
  123. currentChildren.forEach(function (child) {
  124. var key = child && child.key;
  125. if (child && currentlyAnimatingKeys[key]) {
  126. return;
  127. }
  128. var hasNext = child && findChildInChildrenByKey(nextChildren, key);
  129. if (showProp) {
  130. var showInNow = child.props[showProp];
  131. if (hasNext) {
  132. var showInNext = findShownChildInChildrenByKey(nextChildren, key, showProp);
  133. if (!showInNext && showInNow) {
  134. _this3.keysToLeave.push(key);
  135. }
  136. } else if (showInNow) {
  137. _this3.keysToLeave.push(key);
  138. }
  139. } else if (!hasNext) {
  140. _this3.keysToLeave.push(key);
  141. }
  142. });
  143. }
  144. }, {
  145. key: 'componentDidUpdate',
  146. value: function componentDidUpdate() {
  147. var keysToEnter = this.keysToEnter;
  148. this.keysToEnter = [];
  149. keysToEnter.forEach(this.performEnter);
  150. var keysToLeave = this.keysToLeave;
  151. this.keysToLeave = [];
  152. keysToLeave.forEach(this.performLeave);
  153. }
  154. }, {
  155. key: 'isValidChildByKey',
  156. value: function isValidChildByKey(currentChildren, key) {
  157. var showProp = this.props.showProp;
  158. if (showProp) {
  159. return findShownChildInChildrenByKey(currentChildren, key, showProp);
  160. }
  161. return findChildInChildrenByKey(currentChildren, key);
  162. }
  163. }, {
  164. key: 'stop',
  165. value: function stop(key) {
  166. delete this.currentlyAnimatingKeys[key];
  167. var component = this.childrenRefs[key];
  168. if (component) {
  169. component.stop();
  170. }
  171. }
  172. }, {
  173. key: 'render',
  174. value: function render() {
  175. var _this4 = this;
  176. var props = this.props;
  177. this.nextProps = props;
  178. var stateChildren = this.state.children;
  179. var children = null;
  180. if (stateChildren) {
  181. children = stateChildren.map(function (child) {
  182. if (child === null || child === undefined) {
  183. return child;
  184. }
  185. if (!child.key) {
  186. throw new Error('must set key for <rc-animate> children');
  187. }
  188. return React.createElement(
  189. AnimateChild,
  190. {
  191. key: child.key,
  192. ref: function ref(node) {
  193. _this4.childrenRefs[child.key] = node;
  194. },
  195. animation: props.animation,
  196. transitionName: props.transitionName,
  197. transitionEnter: props.transitionEnter,
  198. transitionAppear: props.transitionAppear,
  199. transitionLeave: props.transitionLeave
  200. },
  201. child
  202. );
  203. });
  204. }
  205. var Component = props.component;
  206. if (Component) {
  207. var passedProps = props;
  208. if (typeof Component === 'string') {
  209. passedProps = _extends({
  210. className: props.className,
  211. style: props.style
  212. }, props.componentProps);
  213. }
  214. return React.createElement(
  215. Component,
  216. passedProps,
  217. children
  218. );
  219. }
  220. return children[0] || null;
  221. }
  222. }]);
  223. return Animate;
  224. }(React.Component);
  225. Animate.isAnimate = true;
  226. Animate.propTypes = {
  227. className: PropTypes.string,
  228. style: PropTypes.object,
  229. component: PropTypes.any,
  230. componentProps: PropTypes.object,
  231. animation: PropTypes.object,
  232. transitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  233. transitionEnter: PropTypes.bool,
  234. transitionAppear: PropTypes.bool,
  235. exclusive: PropTypes.bool,
  236. transitionLeave: PropTypes.bool,
  237. onEnd: PropTypes.func,
  238. onEnter: PropTypes.func,
  239. onLeave: PropTypes.func,
  240. onAppear: PropTypes.func,
  241. showProp: PropTypes.string,
  242. children: PropTypes.node
  243. };
  244. Animate.defaultProps = {
  245. animation: {},
  246. component: 'span',
  247. componentProps: {},
  248. transitionEnter: true,
  249. transitionLeave: true,
  250. transitionAppear: false,
  251. onEnd: noop,
  252. onEnter: noop,
  253. onLeave: noop,
  254. onAppear: noop
  255. };
  256. var _initialiseProps = function _initialiseProps() {
  257. var _this5 = this;
  258. this.performEnter = function (key) {
  259. // may already remove by exclusive
  260. if (_this5.childrenRefs[key]) {
  261. _this5.currentlyAnimatingKeys[key] = true;
  262. _this5.childrenRefs[key].componentWillEnter(_this5.handleDoneAdding.bind(_this5, key, 'enter'));
  263. }
  264. };
  265. this.performAppear = function (key) {
  266. if (_this5.childrenRefs[key]) {
  267. _this5.currentlyAnimatingKeys[key] = true;
  268. _this5.childrenRefs[key].componentWillAppear(_this5.handleDoneAdding.bind(_this5, key, 'appear'));
  269. }
  270. };
  271. this.handleDoneAdding = function (key, type) {
  272. var props = _this5.props;
  273. delete _this5.currentlyAnimatingKeys[key];
  274. // if update on exclusive mode, skip check
  275. if (props.exclusive && props !== _this5.nextProps) {
  276. return;
  277. }
  278. var currentChildren = toArrayChildren(getChildrenFromProps(props));
  279. if (!_this5.isValidChildByKey(currentChildren, key)) {
  280. // exclusive will not need this
  281. _this5.performLeave(key);
  282. } else if (type === 'appear') {
  283. if (animUtil.allowAppearCallback(props)) {
  284. props.onAppear(key);
  285. props.onEnd(key, true);
  286. }
  287. } else if (animUtil.allowEnterCallback(props)) {
  288. props.onEnter(key);
  289. props.onEnd(key, true);
  290. }
  291. };
  292. this.performLeave = function (key) {
  293. // may already remove by exclusive
  294. if (_this5.childrenRefs[key]) {
  295. _this5.currentlyAnimatingKeys[key] = true;
  296. _this5.childrenRefs[key].componentWillLeave(_this5.handleDoneLeaving.bind(_this5, key));
  297. }
  298. };
  299. this.handleDoneLeaving = function (key) {
  300. var props = _this5.props;
  301. delete _this5.currentlyAnimatingKeys[key];
  302. // if update on exclusive mode, skip check
  303. if (props.exclusive && props !== _this5.nextProps) {
  304. return;
  305. }
  306. var currentChildren = toArrayChildren(getChildrenFromProps(props));
  307. // in case state change is too fast
  308. if (_this5.isValidChildByKey(currentChildren, key)) {
  309. _this5.performEnter(key);
  310. } else {
  311. var end = function end() {
  312. if (animUtil.allowLeaveCallback(props)) {
  313. props.onLeave(key);
  314. props.onEnd(key, false);
  315. }
  316. };
  317. if (!isSameChildren(_this5.state.children, currentChildren, props.showProp)) {
  318. _this5.setState({
  319. children: currentChildren
  320. }, end);
  321. } else {
  322. end();
  323. }
  324. }
  325. };
  326. };
  327. export default unsafeLifecyclesPolyfill(Animate);