Socket
Socket
Sign inDemoInstall

rc-animate

Package Overview
Dependencies
Maintainers
3
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rc-animate - npm Package Compare versions

Comparing version 2.4.4 to 3.0.0-rc.0

460

es/Animate.js
import _extends from 'babel-runtime/helpers/extends';
import _defineProperty from 'babel-runtime/helpers/defineProperty';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';

@@ -9,346 +7,204 @@ import _inherits from 'babel-runtime/helpers/inherits';

import PropTypes from 'prop-types';
import { toArrayChildren, mergeChildren, findShownChildInChildrenByKey, findChildInChildrenByKey, isSameChildren } from './ChildrenUtils';
import { polyfill } from 'react-lifecycles-compat';
import toArray from 'rc-util/es/Children/toArray';
import warning from 'fbjs/lib/warning';
import AnimateChild from './AnimateChild';
import { cloneProps, mergeChildren } from './util';
var defaultKey = 'rc_animate_' + Date.now();
import animUtil from './util';
var clonePropList = ['children'];
function getChildrenFromProps(props) {
var children = props.children;
if (React.isValidElement(children)) {
if (!children.key) {
return React.cloneElement(children, {
key: defaultKey
});
}
}
return children;
}
/**
* Default use `AnimateChild` as component.
* Here can also pass customize `ChildComponent` for test usage.
*/
export function genAnimate(ChildComponent) {
var Animate = function (_React$Component) {
_inherits(Animate, _React$Component);
function noop() {}
function Animate() {
var _temp, _this, _ret;
var Animate = function (_React$Component) {
_inherits(Animate, _React$Component);
_classCallCheck(this, Animate);
// eslint-disable-line
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
function Animate(props) {
_classCallCheck(this, Animate);
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.state = {
appeared: true,
mergedChildren: []
}, _this.onChildLeaved = function (key) {
// Remove child which not exist anymore
if (!_this.hasChild(key)) {
var mergedChildren = _this.state.mergedChildren;
var _this = _possibleConstructorReturn(this, (Animate.__proto__ || Object.getPrototypeOf(Animate)).call(this, props));
_this.setState({
mergedChildren: mergedChildren.filter(function (node) {
return node.key !== key;
})
});
}
}, _this.hasChild = function (key) {
var children = _this.props.children;
_initialiseProps.call(_this);
_this.currentlyAnimatingKeys = {};
_this.keysToEnter = [];
_this.keysToLeave = [];
return toArray(children).some(function (node) {
return node && node.key === key;
});
}, _temp), _possibleConstructorReturn(_this, _ret);
}
// [Legacy] Not sure usage
// commit: https://github.com/react-component/animate/commit/0a1cbfd647407498b10a8c6602a2dea80b42e324
// eslint-disable-line
_this.state = {
children: toArrayChildren(getChildrenFromProps(props))
};
Animate.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
var _prevState$prevProps = prevState.prevProps,
prevProps = _prevState$prevProps === undefined ? {} : _prevState$prevProps;
_this.childrenRefs = {};
return _this;
}
var newState = {
prevProps: cloneProps(nextProps, clonePropList)
};
var showProp = nextProps.showProp;
_createClass(Animate, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
var showProp = this.props.showProp;
var children = this.state.children;
if (showProp) {
children = children.filter(function (child) {
return !!child.props[showProp];
});
function processState(propName, updater) {
if (prevProps[propName] !== nextProps[propName]) {
updater(nextProps[propName]);
return true;
}
return false;
}
children.forEach(function (child) {
if (child) {
_this2.performAppear(child.key);
}
});
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this3 = this;
this.nextProps = nextProps;
var nextChildren = toArrayChildren(getChildrenFromProps(nextProps));
var props = this.props;
// exclusive needs immediate response
if (props.exclusive) {
Object.keys(this.currentlyAnimatingKeys).forEach(function (key) {
_this3.stop(key);
processState('children', function (children) {
var currentChildren = toArray(children).filter(function (node) {
return node;
});
}
var showProp = props.showProp;
var currentlyAnimatingKeys = this.currentlyAnimatingKeys;
// last props children if exclusive
var currentChildren = props.exclusive ? toArrayChildren(getChildrenFromProps(props)) : this.state.children;
// in case destroy in showProp mode
var newChildren = [];
if (showProp) {
currentChildren.forEach(function (currentChild) {
var nextChild = currentChild && findChildInChildrenByKey(nextChildren, currentChild.key);
var newChild = void 0;
if ((!nextChild || !nextChild.props[showProp]) && currentChild.props[showProp]) {
newChild = React.cloneElement(nextChild || currentChild, _defineProperty({}, showProp, true));
} else {
newChild = nextChild;
var prevChildren = prevState.mergedChildren.filter(function (node) {
// Remove prev child if not show anymore
if (currentChildren.every(function (_ref) {
var key = _ref.key;
return key !== node.key;
}) && showProp && !node.props[showProp]) {
return false;
}
if (newChild) {
newChildren.push(newChild);
}
return true;
});
nextChildren.forEach(function (nextChild) {
if (!nextChild || !findChildInChildrenByKey(currentChildren, nextChild.key)) {
newChildren.push(nextChild);
}
});
} else {
newChildren = mergeChildren(currentChildren, nextChildren);
}
// need render to avoid update
this.setState({
children: newChildren
// Merge prev children to keep the animation
newState.mergedChildren = mergeChildren(prevChildren, currentChildren);
});
nextChildren.forEach(function (child) {
var key = child && child.key;
if (child && currentlyAnimatingKeys[key]) {
return;
return newState;
};
Animate.prototype.componentDidMount = function componentDidMount() {
// No need to re-render
this.state.appeared = false;
};
Animate.prototype.render = function render() {
var _this2 = this;
var _state = this.state,
appeared = _state.appeared,
mergedChildren = _state.mergedChildren;
var _props = this.props,
Component = _props.component,
componentProps = _props.componentProps,
className = _props.className,
style = _props.style,
showProp = _props.showProp;
var $children = mergedChildren.map(function (node) {
if (mergedChildren.length > 1 && !node.key) {
warning(false, 'must set key for <rc-animate> children');
return null;
}
var hasPrev = child && findChildInChildrenByKey(currentChildren, key);
if (showProp) {
var showInNext = child.props[showProp];
if (hasPrev) {
var showInNow = findShownChildInChildrenByKey(currentChildren, key, showProp);
if (!showInNow && showInNext) {
_this3.keysToEnter.push(key);
}
} else if (showInNext) {
_this3.keysToEnter.push(key);
}
} else if (!hasPrev) {
_this3.keysToEnter.push(key);
var show = true;
if (!_this2.hasChild(node.key)) {
show = false;
} else if (showProp) {
show = node.props[showProp];
}
});
currentChildren.forEach(function (child) {
var key = child && child.key;
if (child && currentlyAnimatingKeys[key]) {
return;
}
var hasNext = child && findChildInChildrenByKey(nextChildren, key);
if (showProp) {
var showInNow = child.props[showProp];
if (hasNext) {
var showInNext = findShownChildInChildrenByKey(nextChildren, key, showProp);
if (!showInNext && showInNow) {
_this3.keysToLeave.push(key);
}
} else if (showInNow) {
_this3.keysToLeave.push(key);
}
} else if (!hasNext) {
_this3.keysToLeave.push(key);
}
var key = node.key || defaultKey;
return React.createElement(
ChildComponent,
_extends({}, _this2.props, {
appeared: appeared,
show: show,
className: node.props.className,
style: node.props.style,
key: key,
animateKey: node.key // Keep trans origin key
, onChildLeaved: _this2.onChildLeaved
}),
node
);
});
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
var keysToEnter = this.keysToEnter;
this.keysToEnter = [];
keysToEnter.forEach(this.performEnter);
var keysToLeave = this.keysToLeave;
this.keysToLeave = [];
keysToLeave.forEach(this.performLeave);
}
}, {
key: 'isValidChildByKey',
value: function isValidChildByKey(currentChildren, key) {
var showProp = this.props.showProp;
if (showProp) {
return findShownChildInChildrenByKey(currentChildren, key, showProp);
}
return findChildInChildrenByKey(currentChildren, key);
}
}, {
key: 'stop',
value: function stop(key) {
delete this.currentlyAnimatingKeys[key];
var component = this.childrenRefs[key];
if (component) {
component.stop();
}
}
}, {
key: 'render',
value: function render() {
var _this4 = this;
var props = this.props;
this.nextProps = props;
var stateChildren = this.state.children;
var children = null;
if (stateChildren) {
children = stateChildren.map(function (child) {
if (child === null || child === undefined) {
return child;
}
if (!child.key) {
throw new Error('must set key for <rc-animate> children');
}
return React.createElement(
AnimateChild,
{
key: child.key,
ref: function ref(node) {
return _this4.childrenRefs[child.key] = node;
},
animation: props.animation,
transitionName: props.transitionName,
transitionEnter: props.transitionEnter,
transitionAppear: props.transitionAppear,
transitionLeave: props.transitionLeave
},
child
);
});
}
var Component = props.component;
// Wrap with component
if (Component) {
var passedProps = props;
var passedProps = this.props;
if (typeof Component === 'string') {
passedProps = _extends({
className: props.className,
style: props.style
}, props.componentProps);
className: className,
style: style
}, componentProps);
}
return React.createElement(
Component,
passedProps,
children
$children
);
}
return children[0] || null;
}
}]);
return Animate;
}(React.Component);
return $children[0] || null;
};
Animate.isAnimate = true;
Animate.propTypes = {
component: PropTypes.any,
componentProps: PropTypes.object,
animation: PropTypes.object,
transitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
transitionEnter: PropTypes.bool,
transitionAppear: PropTypes.bool,
exclusive: PropTypes.bool,
transitionLeave: PropTypes.bool,
onEnd: PropTypes.func,
onEnter: PropTypes.func,
onLeave: PropTypes.func,
onAppear: PropTypes.func,
showProp: PropTypes.string
};
Animate.defaultProps = {
animation: {},
component: 'span',
componentProps: {},
transitionEnter: true,
transitionLeave: true,
transitionAppear: false,
onEnd: noop,
onEnter: noop,
onLeave: noop,
onAppear: noop
};
return Animate;
}(React.Component);
var _initialiseProps = function _initialiseProps() {
var _this5 = this;
this.performEnter = function (key) {
// may already remove by exclusive
if (_this5.childrenRefs[key]) {
_this5.currentlyAnimatingKeys[key] = true;
_this5.childrenRefs[key].componentWillEnter(_this5.handleDoneAdding.bind(_this5, key, 'enter'));
}
Animate.isAnimate = true;
Animate.propTypes = {
component: PropTypes.any,
componentProps: PropTypes.object,
animation: PropTypes.object,
transitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
transitionEnter: PropTypes.bool,
transitionAppear: PropTypes.bool,
exclusive: PropTypes.bool,
transitionLeave: PropTypes.bool,
onEnd: PropTypes.func,
onEnter: PropTypes.func,
onLeave: PropTypes.func,
onAppear: PropTypes.func,
showProp: PropTypes.string,
children: PropTypes.node,
style: PropTypes.object,
className: PropTypes.string
};
this.performAppear = function (key) {
if (_this5.childrenRefs[key]) {
_this5.currentlyAnimatingKeys[key] = true;
_this5.childrenRefs[key].componentWillAppear(_this5.handleDoneAdding.bind(_this5, key, 'appear'));
}
Animate.defaultProps = {
animation: {},
component: 'span',
componentProps: {},
transitionEnter: true,
transitionLeave: true,
transitionAppear: false
};
this.handleDoneAdding = function (key, type) {
var props = _this5.props;
delete _this5.currentlyAnimatingKeys[key];
// if update on exclusive mode, skip check
if (props.exclusive && props !== _this5.nextProps) {
return;
}
var currentChildren = toArrayChildren(getChildrenFromProps(props));
if (!_this5.isValidChildByKey(currentChildren, key)) {
// exclusive will not need this
_this5.performLeave(key);
} else {
if (type === 'appear') {
if (animUtil.allowAppearCallback(props)) {
props.onAppear(key);
props.onEnd(key, true);
}
} else {
if (animUtil.allowEnterCallback(props)) {
props.onEnter(key);
props.onEnd(key, true);
}
}
}
};
this.performLeave = function (key) {
// may already remove by exclusive
if (_this5.childrenRefs[key]) {
_this5.currentlyAnimatingKeys[key] = true;
_this5.childrenRefs[key].componentWillLeave(_this5.handleDoneLeaving.bind(_this5, key));
}
};
polyfill(Animate);
this.handleDoneLeaving = function (key) {
var props = _this5.props;
delete _this5.currentlyAnimatingKeys[key];
// if update on exclusive mode, skip check
if (props.exclusive && props !== _this5.nextProps) {
return;
}
var currentChildren = toArrayChildren(getChildrenFromProps(props));
// in case state change is too fast
if (_this5.isValidChildByKey(currentChildren, key)) {
_this5.performEnter(key);
} else {
var end = function end() {
if (animUtil.allowLeaveCallback(props)) {
props.onLeave(key);
props.onEnd(key, false);
}
};
if (!isSameChildren(_this5.state.children, currentChildren, props.showProp)) {
_this5.setState({
children: currentChildren
}, end);
} else {
end();
}
}
};
};
return Animate;
}
export default Animate;
export default genAnimate(AnimateChild);

@@ -1,4 +0,2 @@

import _typeof from 'babel-runtime/helpers/typeof';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';

@@ -9,105 +7,440 @@ import _inherits from 'babel-runtime/helpers/inherits';

import PropTypes from 'prop-types';
import cssAnimate, { isCssAnimationSupported } from 'css-animation';
import animUtil from './util';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import classes from 'component-classes';
import raf from 'raf';
var transitionMap = {
enter: 'transitionEnter',
appear: 'transitionAppear',
leave: 'transitionLeave'
};
import { getStyleValue, cloneProps, getTransitionName, supportTransition, animationEndName, transitionEndName } from './util';
var AnimateChild = function (_React$Component) {
_inherits(AnimateChild, _React$Component);
var clonePropList = ['appeared', 'show', 'exclusive', 'children', 'animation'];
function AnimateChild() {
_classCallCheck(this, AnimateChild);
/**
* AnimateChild only accept one child node.
* `transitionSupport` is used for none transition test case.
* Default we use browser transition event support check.
*/
export function genAnimateChild(transitionSupport) {
var AnimateChild = function (_React$Component) {
_inherits(AnimateChild, _React$Component);
return _possibleConstructorReturn(this, (AnimateChild.__proto__ || Object.getPrototypeOf(AnimateChild)).apply(this, arguments));
}
function AnimateChild() {
_classCallCheck(this, AnimateChild);
_createClass(AnimateChild, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.stop();
// [Legacy] Since old code addListener on the element.
// To avoid break the behaviour that component not handle animation/transition
// also can handle the animate, let keep the logic.
var _this = _possibleConstructorReturn(this, _React$Component.call(this));
_this.state = {
child: null,
eventQueue: [],
eventActive: false
};
_this.onDomUpdated = function () {
var eventActive = _this.state.eventActive;
var _this$props = _this.props,
transitionName = _this$props.transitionName,
animation = _this$props.animation,
onChildLeaved = _this$props.onChildLeaved,
animateKey = _this$props.animateKey;
var $ele = _this.getDomElement();
// Skip if dom element not ready
if (!$ele) return;
// [Legacy] Add animation/transition event by dom level
if (transitionSupport && _this.$prevEle !== $ele) {
_this.cleanDomEvent();
_this.$prevEle = $ele;
_this.$prevEle.addEventListener(animationEndName, _this.onMotionEnd);
_this.$prevEle.addEventListener(transitionEndName, _this.onMotionEnd);
}
var currentEvent = _this.getCurrentEvent();
if (currentEvent.empty) {
// Additional process the leave event
if (currentEvent.lastEventType === 'leave') {
onChildLeaved(animateKey);
}
return;
}
var eventType = currentEvent.eventType,
restQueue = currentEvent.restQueue;
var nodeClasses = classes($ele);
// [Legacy] Since origin code use js to set `className`.
// This caused that any component without support `className` can be forced set.
// Let's keep the logic.
function legacyAppendClass() {
if (!transitionSupport) return;
var basicClassName = getTransitionName(transitionName, '' + eventType);
if (basicClassName) nodeClasses.add(basicClassName);
if (eventActive) {
var activeClassName = getTransitionName(transitionName, eventType + '-active');
if (activeClassName) nodeClasses.add(activeClassName);
}
}
if (_this.currentEvent && _this.currentEvent.type === eventType) {
legacyAppendClass();
return;
}
// Clear timeout for legacy check
clearTimeout(_this.timeout);
// Clean up last event environment
if (_this.currentEvent && _this.currentEvent.animateObj && _this.currentEvent.animateObj.stop) {
_this.currentEvent.animateObj.stop();
}
// Clean up last transition class
if (_this.currentEvent) {
var basicClassName = getTransitionName(transitionName, '' + _this.currentEvent.type);
var activeClassName = getTransitionName(transitionName, _this.currentEvent.type + '-active');
if (basicClassName) nodeClasses.remove(basicClassName);
if (activeClassName) nodeClasses.remove(activeClassName);
}
// New event come
_this.currentEvent = {
type: eventType
};
var animationHandler = (animation || {})[eventType];
// =============== Check if has customize animation ===============
if (animationHandler) {
_this.currentEvent.animateObj = animationHandler($ele, function () {
_this.onMotionEnd({ target: $ele });
});
// Do next step if not animate object provided
if (!_this.currentEvent.animateObj) {
_this.nextEvent(restQueue);
}
// ==================== Use transition instead ====================
} else if (transitionSupport) {
legacyAppendClass();
if (!eventActive) {
// Trigger `eventActive` in next frame
raf(function () {
if (_this.currentEvent && _this.currentEvent.type === eventType && !_this._destroy) {
_this.setState({ eventActive: true }, function () {
// [Legacy] Handle timeout if browser transition event not handle
var transitionDelay = getStyleValue($ele, 'transition-delay') || 0;
var transitionDuration = getStyleValue($ele, 'transition-duration') || 0;
var animationDelay = getStyleValue($ele, 'animation-delay') || 0;
var animationDuration = getStyleValue($ele, 'animation-duration') || 0;
var totalTime = Math.max(transitionDuration + transitionDelay, animationDuration + animationDelay);
if (totalTime >= 0) {
_this.timeout = setTimeout(function () {
_this.onMotionEnd({ target: $ele });
}, totalTime * 1000);
}
});
}
});
}
// ======================= Just next action =======================
} else {
_this.onMotionEnd({ target: $ele });
}
};
_this.onMotionEnd = function (_ref) {
var target = _ref.target;
var _this$props2 = _this.props,
transitionName = _this$props2.transitionName,
onChildLeaved = _this$props2.onChildLeaved,
animateKey = _this$props2.animateKey,
onAppear = _this$props2.onAppear,
onEnter = _this$props2.onEnter,
onLeave = _this$props2.onLeave,
onEnd = _this$props2.onEnd;
var currentEvent = _this.getCurrentEvent();
if (currentEvent.empty) return;
// Clear timeout for legacy check
clearTimeout(_this.timeout);
var restQueue = currentEvent.restQueue;
var $ele = _this.getDomElement();
if (!_this.currentEvent || $ele !== target) return;
if (_this.currentEvent.animateObj && _this.currentEvent.animateObj.stop) {
_this.currentEvent.animateObj.stop();
}
// [Legacy] Same as above, we need call js to remove the class
if (transitionSupport && _this.currentEvent) {
var basicClassName = getTransitionName(transitionName, _this.currentEvent.type);
var activeClassName = getTransitionName(transitionName, _this.currentEvent.type + '-active');
var nodeClasses = classes($ele);
if (basicClassName) nodeClasses.remove(basicClassName);
if (activeClassName) nodeClasses.remove(activeClassName);
}
// Additional process the leave event
if (_this.currentEvent && _this.currentEvent.type === 'leave') {
onChildLeaved(animateKey);
}
// [Legacy] Trigger on event when it's last event
if (_this.currentEvent && !restQueue.length) {
if (_this.currentEvent.type === 'appear' && onAppear) {
onAppear(animateKey);
} else if (_this.currentEvent.type === 'enter' && onEnter) {
onEnter(animateKey);
} else if (_this.currentEvent.type === 'leave' && onLeave) {
onLeave(animateKey);
}
if (onEnd) {
// OnEnd(key, isShow)
onEnd(animateKey, _this.currentEvent.type !== 'leave');
}
}
_this.currentEvent = null;
// Next queue
_this.nextEvent(restQueue);
};
_this.getDomElement = function () {
if (_this._destroy) return null;
return ReactDOM.findDOMNode(_this);
};
_this.getCurrentEvent = function () {
var _this$state$eventQueu = _this.state.eventQueue,
eventQueue = _this$state$eventQueu === undefined ? [] : _this$state$eventQueu;
var _this$props3 = _this.props,
animation = _this$props3.animation,
exclusive = _this$props3.exclusive,
transitionAppear = _this$props3.transitionAppear,
transitionEnter = _this$props3.transitionEnter,
transitionLeave = _this$props3.transitionLeave;
function hasEventHandler(eventType) {
return eventType === 'appear' && (transitionAppear || animation.appear) || eventType === 'enter' && (transitionEnter || animation.enter) || eventType === 'leave' && (transitionLeave || animation.leave);
}
var event = null;
// If is exclusive, only check the last event
if (exclusive) {
var eventType = eventQueue[eventQueue.length - 1];
if (hasEventHandler(eventType)) {
event = {
eventType: eventType,
restQueue: []
};
}
} else {
// Loop check the queue until find match
var cloneQueue = eventQueue.slice();
while (cloneQueue.length) {
var _cloneQueue = cloneQueue,
_eventType = _cloneQueue[0],
restQueue = _cloneQueue.slice(1);
if (hasEventHandler(_eventType)) {
event = {
eventType: _eventType,
restQueue: restQueue
};
break;
}
cloneQueue = restQueue;
}
}
if (!event) {
event = {
empty: true,
lastEventType: eventQueue[eventQueue.length - 1]
};
}
return event;
};
_this.nextEvent = function (restQueue) {
// Next queue
if (!_this._destroy) {
_this.setState({
eventQueue: restQueue,
eventActive: false
});
}
};
_this.cleanDomEvent = function () {
if (_this.$prevEle && transitionSupport) {
_this.$prevEle.removeEventListener(animationEndName, _this.onMotionEnd);
_this.$prevEle.removeEventListener(transitionEndName, _this.onMotionEnd);
}
};
_this.$prevEle = null;
_this.currentEvent = null;
_this.timeout = null;
return _this;
}
}, {
key: 'componentWillEnter',
value: function componentWillEnter(done) {
if (animUtil.isEnterSupported(this.props)) {
this.transition('enter', done);
} else {
done();
AnimateChild.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
var _prevState$prevProps = prevState.prevProps,
prevProps = _prevState$prevProps === undefined ? {} : _prevState$prevProps;
var appeared = nextProps.appeared;
var newState = {
prevProps: cloneProps(nextProps, clonePropList)
};
function processState(propName, updater) {
if (prevProps[propName] !== nextProps[propName]) {
if (updater) {
updater(nextProps[propName]);
}
return true;
}
return false;
}
}
}, {
key: 'componentWillAppear',
value: function componentWillAppear(done) {
if (animUtil.isAppearSupported(this.props)) {
this.transition('appear', done);
} else {
done();
function pushEvent(eventType) {
var eventQueue = newState.eventQueue || prevState.eventQueue.slice();
var matchIndex = eventQueue.indexOf(eventType);
// Clean the rest event if eventType match
if (matchIndex !== -1) {
eventQueue = eventQueue.slice(0, matchIndex);
}
eventQueue.push(eventType);
newState.eventQueue = eventQueue;
}
}
}, {
key: 'componentWillLeave',
value: function componentWillLeave(done) {
if (animUtil.isLeaveSupported(this.props)) {
this.transition('leave', done);
// Child update. Only set child.
processState('children', function (child) {
newState.child = child;
});
processState('appeared', function (isAppeared) {
if (isAppeared) {
pushEvent('appear');
}
});
// Show update
processState('show', function (show) {
if (!appeared) {
if (show) {
pushEvent('enter');
} else {
pushEvent('leave');
}
}
});
return newState;
};
AnimateChild.prototype.componentDidMount = function componentDidMount() {
this.onDomUpdated();
};
AnimateChild.prototype.componentDidUpdate = function componentDidUpdate() {
this.onDomUpdated();
};
AnimateChild.prototype.componentWillUnmount = function componentWillUnmount() {
clearTimeout(this.timeout);
this._destroy = true;
this.cleanDomEvent();
};
AnimateChild.prototype.render = function render() {
var _state = this.state,
child = _state.child,
eventActive = _state.eventActive;
var _props = this.props,
showProp = _props.showProp,
transitionName = _props.transitionName;
var _ref2 = child.props || {},
className = _ref2.className;
var currentEvent = this.getCurrentEvent();
// Class name
var connectClassName = transitionSupport && this.currentEvent ? classNames(className, getTransitionName(transitionName, this.currentEvent.type), eventActive && getTransitionName(transitionName, this.currentEvent.type + '-active')) : className;
var show = true;
// Keep show when is in transition or has customize animate
if (transitionSupport && (!currentEvent.empty || this.currentEvent && this.currentEvent.animateObj)) {
show = true;
} else {
// always sync, do not interupt with react component life cycle
// update hidden -> animate hidden ->
// didUpdate -> animate leave -> unmount (if animate is none)
done();
show = child.props[showProp];
}
}
}, {
key: 'transition',
value: function transition(animationType, finishCallback) {
var _this2 = this;
var node = ReactDOM.findDOMNode(this);
var props = this.props;
var transitionName = props.transitionName;
var nameIsObj = (typeof transitionName === 'undefined' ? 'undefined' : _typeof(transitionName)) === 'object';
this.stop();
var end = function end() {
_this2.stopper = null;
finishCallback();
// Clone child
var newChildProps = {
className: connectClassName
};
if ((isCssAnimationSupported || !props.animation[animationType]) && transitionName && props[transitionMap[animationType]]) {
var name = nameIsObj ? transitionName[animationType] : transitionName + '-' + animationType;
var activeName = name + '-active';
if (nameIsObj && transitionName[animationType + 'Active']) {
activeName = transitionName[animationType + 'Active'];
}
this.stopper = cssAnimate(node, {
name: name,
active: activeName
}, end);
} else {
this.stopper = props.animation[animationType](node, end);
if (showProp) {
newChildProps[showProp] = show;
}
}
}, {
key: 'stop',
value: function stop() {
var stopper = this.stopper;
if (stopper) {
this.stopper = null;
stopper.stop();
}
}
}, {
key: 'render',
value: function render() {
return this.props.children;
}
}]);
return React.cloneElement(child, newChildProps);
};
return AnimateChild;
}(React.Component);
AnimateChild.propTypes = {
transitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
transitionAppear: PropTypes.bool,
transitionEnter: PropTypes.bool,
transitionLeave: PropTypes.bool,
exclusive: PropTypes.bool,
appeared: PropTypes.bool,
showProp: PropTypes.string,
animateKey: PropTypes.any,
animation: PropTypes.object,
onChildLeaved: PropTypes.func,
onEnd: PropTypes.func,
onAppear: PropTypes.func,
onEnter: PropTypes.func,
onLeave: PropTypes.func
};
polyfill(AnimateChild);
return AnimateChild;
}(React.Component);
}
AnimateChild.propTypes = {
children: PropTypes.any
};
export default AnimateChild;
export default genAnimateChild(supportTransition);

@@ -1,21 +0,164 @@

var util = {
isAppearSupported: function isAppearSupported(props) {
return props.transitionName && props.transitionAppear || props.animation.appear;
},
isEnterSupported: function isEnterSupported(props) {
return props.transitionName && props.transitionEnter || props.animation.enter;
},
isLeaveSupported: function isLeaveSupported(props) {
return props.transitionName && props.transitionLeave || props.animation.leave;
},
allowAppearCallback: function allowAppearCallback(props) {
return props.transitionAppear || props.animation.appear;
},
allowEnterCallback: function allowEnterCallback(props) {
return props.transitionEnter || props.animation.enter;
},
allowLeaveCallback: function allowLeaveCallback(props) {
return props.transitionLeave || props.animation.leave;
import toArray from 'rc-util/es/Children/toArray';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
// =================== Style ====================
var stylePrefixes = ['-webkit-', '-moz-', '-o-', 'ms-', ''];
export function getStyleProperty(node, name) {
// old ff need null, https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
var style = window.getComputedStyle(node, null);
var ret = '';
for (var i = 0; i < stylePrefixes.length; i++) {
ret = style.getPropertyValue(stylePrefixes[i] + name);
if (ret) {
break;
}
}
};
export default util;
return ret;
}
export function getStyleValue(node, name) {
return parseFloat(getStyleProperty(node, name));
}
// ================= Transition =================
// Event wrapper. Copy from react source code
function makePrefixMap(styleProp, eventName) {
var prefixes = {};
prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
prefixes['Webkit' + styleProp] = 'webkit' + eventName;
prefixes['Moz' + styleProp] = 'moz' + eventName;
prefixes['ms' + styleProp] = 'MS' + eventName;
prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();
return prefixes;
}
export function getVendorPrefixes(domSupport, win) {
var prefixes = {
animationend: makePrefixMap('Animation', 'AnimationEnd'),
transitionend: makePrefixMap('Transition', 'TransitionEnd')
};
if (domSupport) {
if (!('AnimationEvent' in win)) {
delete prefixes.animationend.animation;
}
if (!('TransitionEvent' in win)) {
delete prefixes.transitionend.transition;
}
}
return prefixes;
}
var vendorPrefixes = getVendorPrefixes(canUseDOM, window);
var style = {};
if (canUseDOM) {
style = document.createElement('div').style;
}
var prefixedEventNames = {};
export function getVendorPrefixedEventName(eventName) {
if (prefixedEventNames[eventName]) {
return prefixedEventNames[eventName];
}
var prefixMap = vendorPrefixes[eventName];
if (prefixMap) {
var stylePropList = Object.keys(prefixMap);
var len = stylePropList.length;
for (var i = 0; i < len; i += 1) {
var styleProp = stylePropList[i];
if (Object.prototype.hasOwnProperty.call(prefixMap, styleProp) && styleProp in style) {
prefixedEventNames[eventName] = prefixMap[styleProp];
return prefixedEventNames[eventName];
}
}
}
return '';
}
export var animationEndName = getVendorPrefixedEventName('animationend');
export var transitionEndName = getVendorPrefixedEventName('transitionend');
export var supportTransition = !!(animationEndName && transitionEndName);
// ==================== Node ====================
/**
* [Legacy] Find the same children in both prev & next list.
* Insert not find one before the find one, otherwise in the end. For example:
* - prev: [1,2,3]
* - next: [2,4]
* -> [1,2,4,3]
*/
export function mergeChildren(prev, next) {
var prevList = toArray(prev);
var nextList = toArray(next);
// Skip if is single children
if (prevList.length === 1 && nextList.length === 1 && prevList[0].key === nextList[0].key) {
return nextList;
}
var mergeList = [];
var nextChildrenMap = {};
var missMatchChildrenList = [];
// Fill matched prev node into next node map
prevList.forEach(function (prevNode) {
if (prevNode && nextList.some(function (_ref) {
var key = _ref.key;
return key === prevNode.key;
})) {
if (missMatchChildrenList.length) {
nextChildrenMap[prevNode.key] = missMatchChildrenList;
missMatchChildrenList = [];
}
} else {
missMatchChildrenList.push(prevNode);
}
});
// Insert prev node before the matched next node
nextList.forEach(function (nextNode) {
if (nextNode && nextChildrenMap[nextNode.key]) {
mergeList = mergeList.concat(nextChildrenMap[nextNode.key]);
}
mergeList.push(nextNode);
});
mergeList = mergeList.concat(missMatchChildrenList);
return mergeList;
}
export function cloneProps(props, propList) {
var newProps = {};
propList.forEach(function (prop) {
if (prop in props) {
newProps[prop] = props[prop];
}
});
return newProps;
}
export function getTransitionName(transitionName, transitionType) {
if (!transitionName) return null;
if (typeof transitionName === 'object') {
var type = transitionType.replace(/-\w/g, function (match) {
return match[1].toUpperCase();
});
return transitionName[type];
}
return transitionName + '-' + transitionType;
}
# History
----
## 3.0.0 / 2018-06-11
- refactor realization
## 2.3.0 / 2016-07-05

@@ -5,0 +9,0 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__esModule = true;

@@ -11,6 +9,2 @@ var _extends2 = require('babel-runtime/helpers/extends');

var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

@@ -20,6 +14,2 @@

var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

@@ -33,2 +23,4 @@

exports.genAnimate = genAnimate;
var _react = require('react');

@@ -42,4 +34,12 @@

var _ChildrenUtils = require('./ChildrenUtils');
var _reactLifecyclesCompat = require('react-lifecycles-compat');
var _toArray = require('rc-util/lib/Children/toArray');
var _toArray2 = _interopRequireDefault(_toArray);
var _warning = require('fbjs/lib/warning');
var _warning2 = _interopRequireDefault(_warning);
var _AnimateChild = require('./AnimateChild');

@@ -51,348 +51,199 @@

var _util2 = _interopRequireDefault(_util);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var defaultKey = 'rc_animate_' + Date.now();
var clonePropList = ['children'];
/**
* Default use `AnimateChild` as component.
* Here can also pass customize `ChildComponent` for test usage.
*/
function genAnimate(ChildComponent) {
var Animate = function (_React$Component) {
(0, _inherits3['default'])(Animate, _React$Component);
function getChildrenFromProps(props) {
var children = props.children;
if (_react2['default'].isValidElement(children)) {
if (!children.key) {
return _react2['default'].cloneElement(children, {
key: defaultKey
});
}
}
return children;
}
function Animate() {
var _temp, _this, _ret;
function noop() {}
(0, _classCallCheck3['default'])(this, Animate);
var Animate = function (_React$Component) {
(0, _inherits3['default'])(Animate, _React$Component);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
// eslint-disable-line
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.state = {
appeared: true,
mergedChildren: []
}, _this.onChildLeaved = function (key) {
// Remove child which not exist anymore
if (!_this.hasChild(key)) {
var mergedChildren = _this.state.mergedChildren;
function Animate(props) {
(0, _classCallCheck3['default'])(this, Animate);
_this.setState({
mergedChildren: mergedChildren.filter(function (node) {
return node.key !== key;
})
});
}
}, _this.hasChild = function (key) {
var children = _this.props.children;
var _this = (0, _possibleConstructorReturn3['default'])(this, (Animate.__proto__ || Object.getPrototypeOf(Animate)).call(this, props));
_initialiseProps.call(_this);
return (0, _toArray2['default'])(children).some(function (node) {
return node && node.key === key;
});
}, _temp), (0, _possibleConstructorReturn3['default'])(_this, _ret);
}
// [Legacy] Not sure usage
// commit: https://github.com/react-component/animate/commit/0a1cbfd647407498b10a8c6602a2dea80b42e324
// eslint-disable-line
_this.currentlyAnimatingKeys = {};
_this.keysToEnter = [];
_this.keysToLeave = [];
Animate.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
var _prevState$prevProps = prevState.prevProps,
prevProps = _prevState$prevProps === undefined ? {} : _prevState$prevProps;
_this.state = {
children: (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props))
};
var newState = {
prevProps: (0, _util.cloneProps)(nextProps, clonePropList)
};
var showProp = nextProps.showProp;
_this.childrenRefs = {};
return _this;
}
(0, _createClass3['default'])(Animate, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
var showProp = this.props.showProp;
var children = this.state.children;
if (showProp) {
children = children.filter(function (child) {
return !!child.props[showProp];
});
function processState(propName, updater) {
if (prevProps[propName] !== nextProps[propName]) {
updater(nextProps[propName]);
return true;
}
return false;
}
children.forEach(function (child) {
if (child) {
_this2.performAppear(child.key);
}
});
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this3 = this;
this.nextProps = nextProps;
var nextChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(nextProps));
var props = this.props;
// exclusive needs immediate response
if (props.exclusive) {
Object.keys(this.currentlyAnimatingKeys).forEach(function (key) {
_this3.stop(key);
processState('children', function (children) {
var currentChildren = (0, _toArray2['default'])(children).filter(function (node) {
return node;
});
}
var showProp = props.showProp;
var currentlyAnimatingKeys = this.currentlyAnimatingKeys;
// last props children if exclusive
var currentChildren = props.exclusive ? (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props)) : this.state.children;
// in case destroy in showProp mode
var newChildren = [];
if (showProp) {
currentChildren.forEach(function (currentChild) {
var nextChild = currentChild && (0, _ChildrenUtils.findChildInChildrenByKey)(nextChildren, currentChild.key);
var newChild = void 0;
if ((!nextChild || !nextChild.props[showProp]) && currentChild.props[showProp]) {
newChild = _react2['default'].cloneElement(nextChild || currentChild, (0, _defineProperty3['default'])({}, showProp, true));
} else {
newChild = nextChild;
var prevChildren = prevState.mergedChildren.filter(function (node) {
// Remove prev child if not show anymore
if (currentChildren.every(function (_ref) {
var key = _ref.key;
return key !== node.key;
}) && showProp && !node.props[showProp]) {
return false;
}
if (newChild) {
newChildren.push(newChild);
}
return true;
});
nextChildren.forEach(function (nextChild) {
if (!nextChild || !(0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, nextChild.key)) {
newChildren.push(nextChild);
}
});
} else {
newChildren = (0, _ChildrenUtils.mergeChildren)(currentChildren, nextChildren);
}
// need render to avoid update
this.setState({
children: newChildren
// Merge prev children to keep the animation
newState.mergedChildren = (0, _util.mergeChildren)(prevChildren, currentChildren);
});
nextChildren.forEach(function (child) {
var key = child && child.key;
if (child && currentlyAnimatingKeys[key]) {
return;
return newState;
};
Animate.prototype.componentDidMount = function componentDidMount() {
// No need to re-render
this.state.appeared = false;
};
Animate.prototype.render = function render() {
var _this2 = this;
var _state = this.state,
appeared = _state.appeared,
mergedChildren = _state.mergedChildren;
var _props = this.props,
Component = _props.component,
componentProps = _props.componentProps,
className = _props.className,
style = _props.style,
showProp = _props.showProp;
var $children = mergedChildren.map(function (node) {
if (mergedChildren.length > 1 && !node.key) {
(0, _warning2['default'])(false, 'must set key for <rc-animate> children');
return null;
}
var hasPrev = child && (0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, key);
if (showProp) {
var showInNext = child.props[showProp];
if (hasPrev) {
var showInNow = (0, _ChildrenUtils.findShownChildInChildrenByKey)(currentChildren, key, showProp);
if (!showInNow && showInNext) {
_this3.keysToEnter.push(key);
}
} else if (showInNext) {
_this3.keysToEnter.push(key);
}
} else if (!hasPrev) {
_this3.keysToEnter.push(key);
var show = true;
if (!_this2.hasChild(node.key)) {
show = false;
} else if (showProp) {
show = node.props[showProp];
}
});
currentChildren.forEach(function (child) {
var key = child && child.key;
if (child && currentlyAnimatingKeys[key]) {
return;
}
var hasNext = child && (0, _ChildrenUtils.findChildInChildrenByKey)(nextChildren, key);
if (showProp) {
var showInNow = child.props[showProp];
if (hasNext) {
var showInNext = (0, _ChildrenUtils.findShownChildInChildrenByKey)(nextChildren, key, showProp);
if (!showInNext && showInNow) {
_this3.keysToLeave.push(key);
}
} else if (showInNow) {
_this3.keysToLeave.push(key);
}
} else if (!hasNext) {
_this3.keysToLeave.push(key);
}
var key = node.key || defaultKey;
return _react2['default'].createElement(
ChildComponent,
(0, _extends3['default'])({}, _this2.props, {
appeared: appeared,
show: show,
className: node.props.className,
style: node.props.style,
key: key,
animateKey: node.key // Keep trans origin key
, onChildLeaved: _this2.onChildLeaved
}),
node
);
});
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
var keysToEnter = this.keysToEnter;
this.keysToEnter = [];
keysToEnter.forEach(this.performEnter);
var keysToLeave = this.keysToLeave;
this.keysToLeave = [];
keysToLeave.forEach(this.performLeave);
}
}, {
key: 'isValidChildByKey',
value: function isValidChildByKey(currentChildren, key) {
var showProp = this.props.showProp;
if (showProp) {
return (0, _ChildrenUtils.findShownChildInChildrenByKey)(currentChildren, key, showProp);
}
return (0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, key);
}
}, {
key: 'stop',
value: function stop(key) {
delete this.currentlyAnimatingKeys[key];
var component = this.childrenRefs[key];
if (component) {
component.stop();
}
}
}, {
key: 'render',
value: function render() {
var _this4 = this;
var props = this.props;
this.nextProps = props;
var stateChildren = this.state.children;
var children = null;
if (stateChildren) {
children = stateChildren.map(function (child) {
if (child === null || child === undefined) {
return child;
}
if (!child.key) {
throw new Error('must set key for <rc-animate> children');
}
return _react2['default'].createElement(
_AnimateChild2['default'],
{
key: child.key,
ref: function ref(node) {
return _this4.childrenRefs[child.key] = node;
},
animation: props.animation,
transitionName: props.transitionName,
transitionEnter: props.transitionEnter,
transitionAppear: props.transitionAppear,
transitionLeave: props.transitionLeave
},
child
);
});
}
var Component = props.component;
// Wrap with component
if (Component) {
var passedProps = props;
var passedProps = this.props;
if (typeof Component === 'string') {
passedProps = (0, _extends3['default'])({
className: props.className,
style: props.style
}, props.componentProps);
className: className,
style: style
}, componentProps);
}
return _react2['default'].createElement(
Component,
passedProps,
children
$children
);
}
return children[0] || null;
}
}]);
return Animate;
}(_react2['default'].Component);
Animate.isAnimate = true;
Animate.propTypes = {
component: _propTypes2['default'].any,
componentProps: _propTypes2['default'].object,
animation: _propTypes2['default'].object,
transitionName: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].object]),
transitionEnter: _propTypes2['default'].bool,
transitionAppear: _propTypes2['default'].bool,
exclusive: _propTypes2['default'].bool,
transitionLeave: _propTypes2['default'].bool,
onEnd: _propTypes2['default'].func,
onEnter: _propTypes2['default'].func,
onLeave: _propTypes2['default'].func,
onAppear: _propTypes2['default'].func,
showProp: _propTypes2['default'].string
};
Animate.defaultProps = {
animation: {},
component: 'span',
componentProps: {},
transitionEnter: true,
transitionLeave: true,
transitionAppear: false,
onEnd: noop,
onEnter: noop,
onLeave: noop,
onAppear: noop
};
return $children[0] || null;
};
var _initialiseProps = function _initialiseProps() {
var _this5 = this;
return Animate;
}(_react2['default'].Component);
this.performEnter = function (key) {
// may already remove by exclusive
if (_this5.childrenRefs[key]) {
_this5.currentlyAnimatingKeys[key] = true;
_this5.childrenRefs[key].componentWillEnter(_this5.handleDoneAdding.bind(_this5, key, 'enter'));
}
Animate.isAnimate = true;
Animate.propTypes = {
component: _propTypes2['default'].any,
componentProps: _propTypes2['default'].object,
animation: _propTypes2['default'].object,
transitionName: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].object]),
transitionEnter: _propTypes2['default'].bool,
transitionAppear: _propTypes2['default'].bool,
exclusive: _propTypes2['default'].bool,
transitionLeave: _propTypes2['default'].bool,
onEnd: _propTypes2['default'].func,
onEnter: _propTypes2['default'].func,
onLeave: _propTypes2['default'].func,
onAppear: _propTypes2['default'].func,
showProp: _propTypes2['default'].string,
children: _propTypes2['default'].node,
style: _propTypes2['default'].object,
className: _propTypes2['default'].string
};
this.performAppear = function (key) {
if (_this5.childrenRefs[key]) {
_this5.currentlyAnimatingKeys[key] = true;
_this5.childrenRefs[key].componentWillAppear(_this5.handleDoneAdding.bind(_this5, key, 'appear'));
}
Animate.defaultProps = {
animation: {},
component: 'span',
componentProps: {},
transitionEnter: true,
transitionLeave: true,
transitionAppear: false
};
this.handleDoneAdding = function (key, type) {
var props = _this5.props;
delete _this5.currentlyAnimatingKeys[key];
// if update on exclusive mode, skip check
if (props.exclusive && props !== _this5.nextProps) {
return;
}
var currentChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props));
if (!_this5.isValidChildByKey(currentChildren, key)) {
// exclusive will not need this
_this5.performLeave(key);
} else {
if (type === 'appear') {
if (_util2['default'].allowAppearCallback(props)) {
props.onAppear(key);
props.onEnd(key, true);
}
} else {
if (_util2['default'].allowEnterCallback(props)) {
props.onEnter(key);
props.onEnd(key, true);
}
}
}
};
this.performLeave = function (key) {
// may already remove by exclusive
if (_this5.childrenRefs[key]) {
_this5.currentlyAnimatingKeys[key] = true;
_this5.childrenRefs[key].componentWillLeave(_this5.handleDoneLeaving.bind(_this5, key));
}
};
(0, _reactLifecyclesCompat.polyfill)(Animate);
this.handleDoneLeaving = function (key) {
var props = _this5.props;
delete _this5.currentlyAnimatingKeys[key];
// if update on exclusive mode, skip check
if (props.exclusive && props !== _this5.nextProps) {
return;
}
var currentChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props));
// in case state change is too fast
if (_this5.isValidChildByKey(currentChildren, key)) {
_this5.performEnter(key);
} else {
var end = function end() {
if (_util2['default'].allowLeaveCallback(props)) {
props.onLeave(key);
props.onEnd(key, false);
}
};
if (!(0, _ChildrenUtils.isSameChildren)(_this5.state.children, currentChildren, props.showProp)) {
_this5.setState({
children: currentChildren
}, end);
} else {
end();
}
}
};
};
return Animate;
}
exports['default'] = Animate;
module.exports = exports['default'];
exports['default'] = genAnimate(_AnimateChild2['default']);
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__esModule = true;
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

@@ -15,6 +9,2 @@

var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

@@ -28,2 +18,4 @@

exports.genAnimateChild = genAnimateChild;
var _react = require('react');

@@ -41,111 +33,451 @@

var _cssAnimation = require('css-animation');
var _reactLifecyclesCompat = require('react-lifecycles-compat');
var _cssAnimation2 = _interopRequireDefault(_cssAnimation);
var _classnames = require('classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _componentClasses = require('component-classes');
var _componentClasses2 = _interopRequireDefault(_componentClasses);
var _raf = require('raf');
var _raf2 = _interopRequireDefault(_raf);
var _util = require('./util');
var _util2 = _interopRequireDefault(_util);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var transitionMap = {
enter: 'transitionEnter',
appear: 'transitionAppear',
leave: 'transitionLeave'
};
var clonePropList = ['appeared', 'show', 'exclusive', 'children', 'animation'];
var AnimateChild = function (_React$Component) {
(0, _inherits3['default'])(AnimateChild, _React$Component);
/**
* AnimateChild only accept one child node.
* `transitionSupport` is used for none transition test case.
* Default we use browser transition event support check.
*/
function genAnimateChild(transitionSupport) {
var AnimateChild = function (_React$Component) {
(0, _inherits3['default'])(AnimateChild, _React$Component);
function AnimateChild() {
(0, _classCallCheck3['default'])(this, AnimateChild);
return (0, _possibleConstructorReturn3['default'])(this, (AnimateChild.__proto__ || Object.getPrototypeOf(AnimateChild)).apply(this, arguments));
}
function AnimateChild() {
(0, _classCallCheck3['default'])(this, AnimateChild);
(0, _createClass3['default'])(AnimateChild, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.stop();
// [Legacy] Since old code addListener on the element.
// To avoid break the behaviour that component not handle animation/transition
// also can handle the animate, let keep the logic.
var _this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call(this));
_this.state = {
child: null,
eventQueue: [],
eventActive: false
};
_this.onDomUpdated = function () {
var eventActive = _this.state.eventActive;
var _this$props = _this.props,
transitionName = _this$props.transitionName,
animation = _this$props.animation,
onChildLeaved = _this$props.onChildLeaved,
animateKey = _this$props.animateKey;
var $ele = _this.getDomElement();
// Skip if dom element not ready
if (!$ele) return;
// [Legacy] Add animation/transition event by dom level
if (transitionSupport && _this.$prevEle !== $ele) {
_this.cleanDomEvent();
_this.$prevEle = $ele;
_this.$prevEle.addEventListener(_util.animationEndName, _this.onMotionEnd);
_this.$prevEle.addEventListener(_util.transitionEndName, _this.onMotionEnd);
}
var currentEvent = _this.getCurrentEvent();
if (currentEvent.empty) {
// Additional process the leave event
if (currentEvent.lastEventType === 'leave') {
onChildLeaved(animateKey);
}
return;
}
var eventType = currentEvent.eventType,
restQueue = currentEvent.restQueue;
var nodeClasses = (0, _componentClasses2['default'])($ele);
// [Legacy] Since origin code use js to set `className`.
// This caused that any component without support `className` can be forced set.
// Let's keep the logic.
function legacyAppendClass() {
if (!transitionSupport) return;
var basicClassName = (0, _util.getTransitionName)(transitionName, '' + eventType);
if (basicClassName) nodeClasses.add(basicClassName);
if (eventActive) {
var activeClassName = (0, _util.getTransitionName)(transitionName, eventType + '-active');
if (activeClassName) nodeClasses.add(activeClassName);
}
}
if (_this.currentEvent && _this.currentEvent.type === eventType) {
legacyAppendClass();
return;
}
// Clear timeout for legacy check
clearTimeout(_this.timeout);
// Clean up last event environment
if (_this.currentEvent && _this.currentEvent.animateObj && _this.currentEvent.animateObj.stop) {
_this.currentEvent.animateObj.stop();
}
// Clean up last transition class
if (_this.currentEvent) {
var basicClassName = (0, _util.getTransitionName)(transitionName, '' + _this.currentEvent.type);
var activeClassName = (0, _util.getTransitionName)(transitionName, _this.currentEvent.type + '-active');
if (basicClassName) nodeClasses.remove(basicClassName);
if (activeClassName) nodeClasses.remove(activeClassName);
}
// New event come
_this.currentEvent = {
type: eventType
};
var animationHandler = (animation || {})[eventType];
// =============== Check if has customize animation ===============
if (animationHandler) {
_this.currentEvent.animateObj = animationHandler($ele, function () {
_this.onMotionEnd({ target: $ele });
});
// Do next step if not animate object provided
if (!_this.currentEvent.animateObj) {
_this.nextEvent(restQueue);
}
// ==================== Use transition instead ====================
} else if (transitionSupport) {
legacyAppendClass();
if (!eventActive) {
// Trigger `eventActive` in next frame
(0, _raf2['default'])(function () {
if (_this.currentEvent && _this.currentEvent.type === eventType && !_this._destroy) {
_this.setState({ eventActive: true }, function () {
// [Legacy] Handle timeout if browser transition event not handle
var transitionDelay = (0, _util.getStyleValue)($ele, 'transition-delay') || 0;
var transitionDuration = (0, _util.getStyleValue)($ele, 'transition-duration') || 0;
var animationDelay = (0, _util.getStyleValue)($ele, 'animation-delay') || 0;
var animationDuration = (0, _util.getStyleValue)($ele, 'animation-duration') || 0;
var totalTime = Math.max(transitionDuration + transitionDelay, animationDuration + animationDelay);
if (totalTime >= 0) {
_this.timeout = setTimeout(function () {
_this.onMotionEnd({ target: $ele });
}, totalTime * 1000);
}
});
}
});
}
// ======================= Just next action =======================
} else {
_this.onMotionEnd({ target: $ele });
}
};
_this.onMotionEnd = function (_ref) {
var target = _ref.target;
var _this$props2 = _this.props,
transitionName = _this$props2.transitionName,
onChildLeaved = _this$props2.onChildLeaved,
animateKey = _this$props2.animateKey,
onAppear = _this$props2.onAppear,
onEnter = _this$props2.onEnter,
onLeave = _this$props2.onLeave,
onEnd = _this$props2.onEnd;
var currentEvent = _this.getCurrentEvent();
if (currentEvent.empty) return;
// Clear timeout for legacy check
clearTimeout(_this.timeout);
var restQueue = currentEvent.restQueue;
var $ele = _this.getDomElement();
if (!_this.currentEvent || $ele !== target) return;
if (_this.currentEvent.animateObj && _this.currentEvent.animateObj.stop) {
_this.currentEvent.animateObj.stop();
}
// [Legacy] Same as above, we need call js to remove the class
if (transitionSupport && _this.currentEvent) {
var basicClassName = (0, _util.getTransitionName)(transitionName, _this.currentEvent.type);
var activeClassName = (0, _util.getTransitionName)(transitionName, _this.currentEvent.type + '-active');
var nodeClasses = (0, _componentClasses2['default'])($ele);
if (basicClassName) nodeClasses.remove(basicClassName);
if (activeClassName) nodeClasses.remove(activeClassName);
}
// Additional process the leave event
if (_this.currentEvent && _this.currentEvent.type === 'leave') {
onChildLeaved(animateKey);
}
// [Legacy] Trigger on event when it's last event
if (_this.currentEvent && !restQueue.length) {
if (_this.currentEvent.type === 'appear' && onAppear) {
onAppear(animateKey);
} else if (_this.currentEvent.type === 'enter' && onEnter) {
onEnter(animateKey);
} else if (_this.currentEvent.type === 'leave' && onLeave) {
onLeave(animateKey);
}
if (onEnd) {
// OnEnd(key, isShow)
onEnd(animateKey, _this.currentEvent.type !== 'leave');
}
}
_this.currentEvent = null;
// Next queue
_this.nextEvent(restQueue);
};
_this.getDomElement = function () {
if (_this._destroy) return null;
return _reactDom2['default'].findDOMNode(_this);
};
_this.getCurrentEvent = function () {
var _this$state$eventQueu = _this.state.eventQueue,
eventQueue = _this$state$eventQueu === undefined ? [] : _this$state$eventQueu;
var _this$props3 = _this.props,
animation = _this$props3.animation,
exclusive = _this$props3.exclusive,
transitionAppear = _this$props3.transitionAppear,
transitionEnter = _this$props3.transitionEnter,
transitionLeave = _this$props3.transitionLeave;
function hasEventHandler(eventType) {
return eventType === 'appear' && (transitionAppear || animation.appear) || eventType === 'enter' && (transitionEnter || animation.enter) || eventType === 'leave' && (transitionLeave || animation.leave);
}
var event = null;
// If is exclusive, only check the last event
if (exclusive) {
var eventType = eventQueue[eventQueue.length - 1];
if (hasEventHandler(eventType)) {
event = {
eventType: eventType,
restQueue: []
};
}
} else {
// Loop check the queue until find match
var cloneQueue = eventQueue.slice();
while (cloneQueue.length) {
var _cloneQueue = cloneQueue,
_eventType = _cloneQueue[0],
restQueue = _cloneQueue.slice(1);
if (hasEventHandler(_eventType)) {
event = {
eventType: _eventType,
restQueue: restQueue
};
break;
}
cloneQueue = restQueue;
}
}
if (!event) {
event = {
empty: true,
lastEventType: eventQueue[eventQueue.length - 1]
};
}
return event;
};
_this.nextEvent = function (restQueue) {
// Next queue
if (!_this._destroy) {
_this.setState({
eventQueue: restQueue,
eventActive: false
});
}
};
_this.cleanDomEvent = function () {
if (_this.$prevEle && transitionSupport) {
_this.$prevEle.removeEventListener(_util.animationEndName, _this.onMotionEnd);
_this.$prevEle.removeEventListener(_util.transitionEndName, _this.onMotionEnd);
}
};
_this.$prevEle = null;
_this.currentEvent = null;
_this.timeout = null;
return _this;
}
}, {
key: 'componentWillEnter',
value: function componentWillEnter(done) {
if (_util2['default'].isEnterSupported(this.props)) {
this.transition('enter', done);
} else {
done();
AnimateChild.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
var _prevState$prevProps = prevState.prevProps,
prevProps = _prevState$prevProps === undefined ? {} : _prevState$prevProps;
var appeared = nextProps.appeared;
var newState = {
prevProps: (0, _util.cloneProps)(nextProps, clonePropList)
};
function processState(propName, updater) {
if (prevProps[propName] !== nextProps[propName]) {
if (updater) {
updater(nextProps[propName]);
}
return true;
}
return false;
}
}
}, {
key: 'componentWillAppear',
value: function componentWillAppear(done) {
if (_util2['default'].isAppearSupported(this.props)) {
this.transition('appear', done);
} else {
done();
function pushEvent(eventType) {
var eventQueue = newState.eventQueue || prevState.eventQueue.slice();
var matchIndex = eventQueue.indexOf(eventType);
// Clean the rest event if eventType match
if (matchIndex !== -1) {
eventQueue = eventQueue.slice(0, matchIndex);
}
eventQueue.push(eventType);
newState.eventQueue = eventQueue;
}
}
}, {
key: 'componentWillLeave',
value: function componentWillLeave(done) {
if (_util2['default'].isLeaveSupported(this.props)) {
this.transition('leave', done);
// Child update. Only set child.
processState('children', function (child) {
newState.child = child;
});
processState('appeared', function (isAppeared) {
if (isAppeared) {
pushEvent('appear');
}
});
// Show update
processState('show', function (show) {
if (!appeared) {
if (show) {
pushEvent('enter');
} else {
pushEvent('leave');
}
}
});
return newState;
};
AnimateChild.prototype.componentDidMount = function componentDidMount() {
this.onDomUpdated();
};
AnimateChild.prototype.componentDidUpdate = function componentDidUpdate() {
this.onDomUpdated();
};
AnimateChild.prototype.componentWillUnmount = function componentWillUnmount() {
clearTimeout(this.timeout);
this._destroy = true;
this.cleanDomEvent();
};
AnimateChild.prototype.render = function render() {
var _state = this.state,
child = _state.child,
eventActive = _state.eventActive;
var _props = this.props,
showProp = _props.showProp,
transitionName = _props.transitionName;
var _ref2 = child.props || {},
className = _ref2.className;
var currentEvent = this.getCurrentEvent();
// Class name
var connectClassName = transitionSupport && this.currentEvent ? (0, _classnames2['default'])(className, (0, _util.getTransitionName)(transitionName, this.currentEvent.type), eventActive && (0, _util.getTransitionName)(transitionName, this.currentEvent.type + '-active')) : className;
var show = true;
// Keep show when is in transition or has customize animate
if (transitionSupport && (!currentEvent.empty || this.currentEvent && this.currentEvent.animateObj)) {
show = true;
} else {
// always sync, do not interupt with react component life cycle
// update hidden -> animate hidden ->
// didUpdate -> animate leave -> unmount (if animate is none)
done();
show = child.props[showProp];
}
}
}, {
key: 'transition',
value: function transition(animationType, finishCallback) {
var _this2 = this;
var node = _reactDom2['default'].findDOMNode(this);
var props = this.props;
var transitionName = props.transitionName;
var nameIsObj = (typeof transitionName === 'undefined' ? 'undefined' : (0, _typeof3['default'])(transitionName)) === 'object';
this.stop();
var end = function end() {
_this2.stopper = null;
finishCallback();
// Clone child
var newChildProps = {
className: connectClassName
};
if ((_cssAnimation.isCssAnimationSupported || !props.animation[animationType]) && transitionName && props[transitionMap[animationType]]) {
var name = nameIsObj ? transitionName[animationType] : transitionName + '-' + animationType;
var activeName = name + '-active';
if (nameIsObj && transitionName[animationType + 'Active']) {
activeName = transitionName[animationType + 'Active'];
}
this.stopper = (0, _cssAnimation2['default'])(node, {
name: name,
active: activeName
}, end);
} else {
this.stopper = props.animation[animationType](node, end);
if (showProp) {
newChildProps[showProp] = show;
}
}
}, {
key: 'stop',
value: function stop() {
var stopper = this.stopper;
if (stopper) {
this.stopper = null;
stopper.stop();
}
}
}, {
key: 'render',
value: function render() {
return this.props.children;
}
}]);
return _react2['default'].cloneElement(child, newChildProps);
};
return AnimateChild;
}(_react2['default'].Component);
AnimateChild.propTypes = {
transitionName: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].object]),
transitionAppear: _propTypes2['default'].bool,
transitionEnter: _propTypes2['default'].bool,
transitionLeave: _propTypes2['default'].bool,
exclusive: _propTypes2['default'].bool,
appeared: _propTypes2['default'].bool,
showProp: _propTypes2['default'].string,
animateKey: _propTypes2['default'].any,
animation: _propTypes2['default'].object,
onChildLeaved: _propTypes2['default'].func,
onEnd: _propTypes2['default'].func,
onAppear: _propTypes2['default'].func,
onEnter: _propTypes2['default'].func,
onLeave: _propTypes2['default'].func
};
(0, _reactLifecyclesCompat.polyfill)(AnimateChild);
return AnimateChild;
}(_react2['default'].Component);
}
AnimateChild.propTypes = {
children: _propTypes2['default'].any
};
exports['default'] = AnimateChild;
module.exports = exports['default'];
exports['default'] = genAnimateChild(_util.supportTransition);

@@ -1,27 +0,181 @@

"use strict";
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var util = {
isAppearSupported: function isAppearSupported(props) {
return props.transitionName && props.transitionAppear || props.animation.appear;
},
isEnterSupported: function isEnterSupported(props) {
return props.transitionName && props.transitionEnter || props.animation.enter;
},
isLeaveSupported: function isLeaveSupported(props) {
return props.transitionName && props.transitionLeave || props.animation.leave;
},
allowAppearCallback: function allowAppearCallback(props) {
return props.transitionAppear || props.animation.appear;
},
allowEnterCallback: function allowEnterCallback(props) {
return props.transitionEnter || props.animation.enter;
},
allowLeaveCallback: function allowLeaveCallback(props) {
return props.transitionLeave || props.animation.leave;
exports.__esModule = true;
exports.supportTransition = exports.transitionEndName = exports.animationEndName = undefined;
exports.getStyleProperty = getStyleProperty;
exports.getStyleValue = getStyleValue;
exports.getVendorPrefixes = getVendorPrefixes;
exports.getVendorPrefixedEventName = getVendorPrefixedEventName;
exports.mergeChildren = mergeChildren;
exports.cloneProps = cloneProps;
exports.getTransitionName = getTransitionName;
var _toArray = require('rc-util/lib/Children/toArray');
var _toArray2 = _interopRequireDefault(_toArray);
var _ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
// =================== Style ====================
var stylePrefixes = ['-webkit-', '-moz-', '-o-', 'ms-', ''];
function getStyleProperty(node, name) {
// old ff need null, https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
var style = window.getComputedStyle(node, null);
var ret = '';
for (var i = 0; i < stylePrefixes.length; i++) {
ret = style.getPropertyValue(stylePrefixes[i] + name);
if (ret) {
break;
}
}
};
exports["default"] = util;
module.exports = exports['default'];
return ret;
}
function getStyleValue(node, name) {
return parseFloat(getStyleProperty(node, name));
}
// ================= Transition =================
// Event wrapper. Copy from react source code
function makePrefixMap(styleProp, eventName) {
var prefixes = {};
prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
prefixes['Webkit' + styleProp] = 'webkit' + eventName;
prefixes['Moz' + styleProp] = 'moz' + eventName;
prefixes['ms' + styleProp] = 'MS' + eventName;
prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();
return prefixes;
}
function getVendorPrefixes(domSupport, win) {
var prefixes = {
animationend: makePrefixMap('Animation', 'AnimationEnd'),
transitionend: makePrefixMap('Transition', 'TransitionEnd')
};
if (domSupport) {
if (!('AnimationEvent' in win)) {
delete prefixes.animationend.animation;
}
if (!('TransitionEvent' in win)) {
delete prefixes.transitionend.transition;
}
}
return prefixes;
}
var vendorPrefixes = getVendorPrefixes(_ExecutionEnvironment.canUseDOM, window);
var style = {};
if (_ExecutionEnvironment.canUseDOM) {
style = document.createElement('div').style;
}
var prefixedEventNames = {};
function getVendorPrefixedEventName(eventName) {
if (prefixedEventNames[eventName]) {
return prefixedEventNames[eventName];
}
var prefixMap = vendorPrefixes[eventName];
if (prefixMap) {
var stylePropList = Object.keys(prefixMap);
var len = stylePropList.length;
for (var i = 0; i < len; i += 1) {
var styleProp = stylePropList[i];
if (Object.prototype.hasOwnProperty.call(prefixMap, styleProp) && styleProp in style) {
prefixedEventNames[eventName] = prefixMap[styleProp];
return prefixedEventNames[eventName];
}
}
}
return '';
}
var animationEndName = exports.animationEndName = getVendorPrefixedEventName('animationend');
var transitionEndName = exports.transitionEndName = getVendorPrefixedEventName('transitionend');
var supportTransition = exports.supportTransition = !!(animationEndName && transitionEndName);
// ==================== Node ====================
/**
* [Legacy] Find the same children in both prev & next list.
* Insert not find one before the find one, otherwise in the end. For example:
* - prev: [1,2,3]
* - next: [2,4]
* -> [1,2,4,3]
*/
function mergeChildren(prev, next) {
var prevList = (0, _toArray2['default'])(prev);
var nextList = (0, _toArray2['default'])(next);
// Skip if is single children
if (prevList.length === 1 && nextList.length === 1 && prevList[0].key === nextList[0].key) {
return nextList;
}
var mergeList = [];
var nextChildrenMap = {};
var missMatchChildrenList = [];
// Fill matched prev node into next node map
prevList.forEach(function (prevNode) {
if (prevNode && nextList.some(function (_ref) {
var key = _ref.key;
return key === prevNode.key;
})) {
if (missMatchChildrenList.length) {
nextChildrenMap[prevNode.key] = missMatchChildrenList;
missMatchChildrenList = [];
}
} else {
missMatchChildrenList.push(prevNode);
}
});
// Insert prev node before the matched next node
nextList.forEach(function (nextNode) {
if (nextNode && nextChildrenMap[nextNode.key]) {
mergeList = mergeList.concat(nextChildrenMap[nextNode.key]);
}
mergeList.push(nextNode);
});
mergeList = mergeList.concat(missMatchChildrenList);
return mergeList;
}
function cloneProps(props, propList) {
var newProps = {};
propList.forEach(function (prop) {
if (prop in props) {
newProps[prop] = props[prop];
}
});
return newProps;
}
function getTransitionName(transitionName, transitionType) {
if (!transitionName) return null;
if (typeof transitionName === 'object') {
var type = transitionType.replace(/-\w/g, function (match) {
return match[1].toUpperCase();
});
return transitionName[type];
}
return transitionName + '-' + transitionType;
}
{
"name": "rc-animate",
"version": "2.4.4",
"version": "3.0.0-rc.0",
"description": "css-transition ui component for react",

@@ -46,8 +46,7 @@ "keywords": [

"expect.js": "0.3.x",
"jquery": "~1.11.3",
"object-assign": "4.x",
"jquery": "^3.3.1",
"pre-commit": "1.x",
"rc-test": "6.x",
"rc-tools": "6.x",
"react": "^16.0.0",
"rc-tools": "8.x",
"react": "^16.3.0",
"react-dom": "^16.0.0",

@@ -61,5 +60,10 @@ "velocity-animate": "~1.2.2"

"babel-runtime": "6.x",
"css-animation": "^1.3.2",
"prop-types": "15.x"
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
"fbjs": "^0.8.16",
"prop-types": "15.x",
"raf": "^3.4.0",
"rc-util": "^4.5.0",
"react-lifecycles-compat": "^3.0.4"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc