UNPKG

react-addons

Version:

Simple packaging of react addons to avoid fiddly 'react/addons' npm module.

139 lines (111 loc) 3.83 kB
/** * Copyright 2013-2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @typechecks * @providesModule ReactCSSTransitionGroupChild */ "use strict"; var React = require("react"); var CSSCore = require("./CSSCore"); var ReactTransitionEvents = require("./ReactTransitionEvents"); var onlyChild = require("./onlyChild"); // We don't remove the element from the DOM until we receive an animationend or // transitionend event. If the user screws up and forgets to add an animation // their node will be stuck in the DOM forever, so we detect if an animation // does not start and if it doesn't, we just call the end listener immediately. var TICK = 17; var NO_EVENT_TIMEOUT = 5000; var noEventListener = null; if ("production" !== process.env.NODE_ENV) { noEventListener = function() { console.warn( 'transition(): tried to perform an animation without ' + 'an animationend or transitionend event after timeout (' + NO_EVENT_TIMEOUT + 'ms). You should either disable this ' + 'transition in JS or add a CSS animation/transition.' ); }; } var ReactCSSTransitionGroupChild = React.createClass({ transition: function(animationType, finishCallback) { var node = this.getDOMNode(); var className = this.props.name + '-' + animationType; var activeClassName = className + '-active'; var noEventTimeout = null; var endListener = function() { if ("production" !== process.env.NODE_ENV) { clearTimeout(noEventTimeout); } CSSCore.removeClass(node, className); CSSCore.removeClass(node, activeClassName); ReactTransitionEvents.removeEndEventListener(node, endListener); // Usually this optional callback is used for informing an owner of // a leave animation and telling it to remove the child. finishCallback && finishCallback(); }; ReactTransitionEvents.addEndEventListener(node, endListener); CSSCore.addClass(node, className); // Need to do this to actually trigger a transition. this.queueClass(activeClassName); if ("production" !== process.env.NODE_ENV) { noEventTimeout = setTimeout(noEventListener, NO_EVENT_TIMEOUT); } }, queueClass: function(className) { this.classNameQueue.push(className); if (this.props.runNextTick) { this.props.runNextTick(this.flushClassNameQueue); return; } if (!this.timeout) { this.timeout = setTimeout(this.flushClassNameQueue, TICK); } }, flushClassNameQueue: function() { if (this.isMounted()) { this.classNameQueue.forEach( CSSCore.addClass.bind(CSSCore, this.getDOMNode()) ); } this.classNameQueue.length = 0; this.timeout = null; }, componentWillMount: function() { this.classNameQueue = []; }, componentWillUnmount: function() { if (this.timeout) { clearTimeout(this.timeout); } }, componentWillEnter: function(done) { if (this.props.enter) { this.transition('enter', done); } else { done(); } }, componentWillLeave: function(done) { if (this.props.leave) { this.transition('leave', done); } else { done(); } }, render: function() { return onlyChild(this.props.children); } }); module.exports = ReactCSSTransitionGroupChild;