react 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -228
- package/ReactJSErrors.js +40 -0
- package/addons.js +4 -0
- package/lib/$.js +46 -0
- package/lib/CSSCore.js +114 -0
- package/lib/CSSProperty.js +90 -0
- package/lib/CSSPropertyOperations.js +97 -0
- package/lib/CallbackRegistry.js +91 -0
- package/lib/ChangeEventPlugin.js +365 -0
- package/lib/CompositionEventPlugin.js +212 -0
- package/lib/DOMChildrenOperations.js +135 -0
- package/lib/DOMProperty.js +266 -0
- package/lib/DOMPropertyOperations.js +168 -0
- package/lib/Danger.js +186 -0
- package/lib/DefaultDOMPropertyConfig.js +187 -0
- package/lib/DefaultEventPluginOrder.js +44 -0
- package/lib/EnterLeaveEventPlugin.js +112 -0
- package/lib/EventConstants.js +73 -0
- package/lib/EventListener.js +61 -0
- package/lib/EventPluginHub.js +190 -0
- package/lib/EventPluginRegistry.js +237 -0
- package/lib/EventPluginUtils.js +185 -0
- package/lib/EventPropagators.js +179 -0
- package/lib/ExecutionEnvironment.js +41 -0
- package/lib/LinkedStateMixin.js +46 -0
- package/lib/LinkedValueMixin.js +68 -0
- package/lib/MobileSafariClickEventPlugin.js +63 -0
- package/lib/PooledClass.js +113 -0
- package/lib/React.js +71 -0
- package/lib/ReactChildren.js +132 -0
- package/lib/ReactComponent.js +515 -0
- package/lib/ReactComponentBrowserEnvironment.js +140 -0
- package/lib/ReactComponentEnvironment.js +24 -0
- package/lib/ReactCompositeComponent.js +1020 -0
- package/lib/ReactCurrentOwner.js +39 -0
- package/lib/ReactDOM.js +194 -0
- package/lib/ReactDOMButton.js +64 -0
- package/lib/ReactDOMComponent.js +374 -0
- package/lib/ReactDOMForm.js +52 -0
- package/lib/ReactDOMIDOperations.js +173 -0
- package/lib/ReactDOMInput.js +169 -0
- package/lib/ReactDOMOption.js +50 -0
- package/lib/ReactDOMSelect.js +160 -0
- package/lib/ReactDOMSelection.js +189 -0
- package/lib/ReactDOMTextarea.js +136 -0
- package/lib/ReactDefaultBatchingStrategy.js +75 -0
- package/lib/ReactDefaultInjection.js +91 -0
- package/lib/ReactDefaultPerf.js +407 -0
- package/lib/ReactErrorUtils.js +46 -0
- package/lib/ReactEventEmitter.js +341 -0
- package/lib/ReactEventEmitterMixin.js +89 -0
- package/lib/ReactEventTopLevelCallback.js +89 -0
- package/lib/ReactInputSelection.js +140 -0
- package/lib/ReactInstanceHandles.js +322 -0
- package/lib/ReactLink.js +54 -0
- package/lib/ReactMarkupChecksum.js +53 -0
- package/lib/ReactMount.js +617 -0
- package/lib/ReactMountReady.js +95 -0
- package/lib/ReactMultiChild.js +441 -0
- package/lib/ReactMultiChildUpdateTypes.js +36 -0
- package/lib/ReactOwner.js +146 -0
- package/lib/ReactPerf.js +88 -0
- package/lib/ReactPropTransferer.js +128 -0
- package/lib/ReactPropTypes.js +158 -0
- package/lib/ReactReconcileTransaction.js +161 -0
- package/lib/ReactServerRendering.js +62 -0
- package/lib/ReactStateSetters.js +111 -0
- package/lib/ReactTextComponent.js +94 -0
- package/lib/ReactTransitionEvents.js +97 -0
- package/lib/ReactTransitionGroup.js +112 -0
- package/lib/ReactTransitionKeySet.js +111 -0
- package/lib/ReactTransitionableChild.js +152 -0
- package/lib/ReactUpdates.js +145 -0
- package/lib/ReactWithAddons.js +41 -0
- package/lib/SelectEventPlugin.js +217 -0
- package/lib/SimpleEventPlugin.js +365 -0
- package/lib/SyntheticClipboardEvent.js +45 -0
- package/lib/SyntheticCompositionEvent.js +51 -0
- package/lib/SyntheticEvent.js +163 -0
- package/lib/SyntheticFocusEvent.js +44 -0
- package/lib/SyntheticKeyboardEvent.js +56 -0
- package/lib/SyntheticMouseEvent.js +85 -0
- package/lib/SyntheticTouchEvent.js +50 -0
- package/lib/SyntheticUIEvent.js +45 -0
- package/lib/SyntheticWheelEvent.js +63 -0
- package/lib/Transaction.js +251 -0
- package/lib/ViewportMetrics.js +37 -0
- package/lib/accumulate.js +54 -0
- package/lib/adler32.js +39 -0
- package/lib/containsNode.js +49 -0
- package/lib/copyProperties.js +54 -0
- package/lib/createArrayFrom.js +94 -0
- package/lib/createNodesFromMarkup.js +93 -0
- package/lib/createObjectFrom.js +61 -0
- package/lib/cx.js +44 -0
- package/lib/dangerousStyleValue.js +57 -0
- package/lib/emptyFunction.js +43 -0
- package/lib/escapeTextForBrowser.js +47 -0
- package/lib/ex.js +49 -0
- package/lib/filterAttributes.js +45 -0
- package/lib/flattenChildren.js +54 -0
- package/lib/forEachAccumulated.js +36 -0
- package/lib/ge.js +76 -0
- package/lib/getActiveElement.js +33 -0
- package/lib/getEventTarget.js +36 -0
- package/lib/getMarkupWrap.js +108 -0
- package/lib/getNodeForCharacterOffset.js +80 -0
- package/lib/getReactRootElementInContainer.js +40 -0
- package/lib/getTextContentAccessor.js +40 -0
- package/lib/getUnboundedScrollPosition.js +45 -0
- package/lib/hyphenate.js +35 -0
- package/lib/invariant.js +54 -0
- package/lib/isEventSupported.js +74 -0
- package/lib/isNode.js +33 -0
- package/lib/isTextInputElement.js +49 -0
- package/lib/isTextNode.js +30 -0
- package/lib/joinClasses.js +44 -0
- package/lib/keyMirror.js +58 -0
- package/lib/keyOf.js +41 -0
- package/lib/memoizeStringOnly.js +39 -0
- package/lib/merge.js +37 -0
- package/lib/mergeHelpers.js +137 -0
- package/lib/mergeInto.js +45 -0
- package/lib/mixInto.js +34 -0
- package/lib/mutateHTMLNodeWithMarkup.js +100 -0
- package/lib/objMap.js +47 -0
- package/lib/objMapKeyVal.js +47 -0
- package/lib/performanceNow.js +42 -0
- package/lib/shallowEqual.js +49 -0
- package/lib/traverseAllChildren.js +127 -0
- package/package.json +33 -31
- package/react.js +4 -0
- package/.npmignore +0 -7
- package/.travis.yml +0 -7
- package/Jakefile.js +0 -39
- package/LICENSE +0 -19
- package/browser-test/dist.html +0 -90
- package/browser-test/index.html +0 -86
- package/browser-test/min.html +0 -90
- package/dist/react.js +0 -3141
- package/dist/react.min.js +0 -22
- package/doc/advanced.md +0 -175
- package/doc/color-def.graffle +0 -938
- package/doc/color-def.png +0 -0
- package/doc/simple.dot +0 -25
- package/doc/simple.png +0 -0
- package/examples/longer-example.js +0 -41
- package/examples/simple.js +0 -45
- package/examples/using-ast-directly.js +0 -30
- package/examples/using-events1.js +0 -79
- package/examples/using-log-events.js +0 -43
- package/lib/base-task.js +0 -120
- package/lib/cb-task.js +0 -84
- package/lib/core.js +0 -138
- package/lib/dsl.js +0 -138
- package/lib/error.js +0 -55
- package/lib/event-collector.js +0 -81
- package/lib/event-manager.js +0 -89
- package/lib/eventemitter.js +0 -20
- package/lib/finalcb-first-task.js +0 -68
- package/lib/finalcb-task.js +0 -65
- package/lib/id.js +0 -22
- package/lib/input-parser.js +0 -56
- package/lib/log-events.js +0 -101
- package/lib/parse.js +0 -41
- package/lib/promise-resolve.js +0 -50
- package/lib/promise-task.js +0 -93
- package/lib/react.js +0 -59
- package/lib/ret-task.js +0 -71
- package/lib/sprintf.js +0 -18
- package/lib/status.js +0 -14
- package/lib/task.js +0 -251
- package/lib/track-tasks.js +0 -74
- package/lib/validate.js +0 -159
- package/lib/vcon.js +0 -113
- package/lib/when-task.js +0 -84
- package/src/dist.build.requirejs +0 -20
- package/test/ast.mocha.js +0 -136
- package/test/cb-task.mocha.js +0 -220
- package/test/core-deferred.mocha.js +0 -143
- package/test/core-when.mocha.js +0 -96
- package/test/core.mocha.js +0 -589
- package/test/dsl.mocha.js +0 -352
- package/test/event-manager.mocha.js +0 -119
- package/test/exec-options.mocha.js +0 -48
- package/test/finalcb-task.mocha.js +0 -58
- package/test/input-parser.mocha.js +0 -86
- package/test/log-events.mocha.js +0 -88
- package/test/mocha.opts +0 -2
- package/test/module-use.mocha.js +0 -164
- package/test/promise-auto-resolve.mocha.js +0 -68
- package/test/ret-task.mocha.js +0 -220
- package/test/task.mocha.js +0 -42
- package/test/validate-cb-task.mocha.js +0 -100
- package/test/validate-ret-task.mocha.js +0 -110
- package/test/validate.mocha.js +0 -324
- package/test/vcon.mocha.js +0 -193
- package/vendor/chai/chai.js +0 -4251
- package/vendor/jquery/jquery-1.7.1.js +0 -9266
- package/vendor/jquery/jquery-1.7.1.min.js +0 -4
- package/vendor/node/util.js +0 -531
- package/vendor/requirejs/require.js +0 -2045
- package/vendor/requirejs/require.min.js +0 -36
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @providesModule ReactTransitionGroup
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var React = require("./React");
|
|
22
|
+
var ReactTransitionableChild = require("./ReactTransitionableChild");
|
|
23
|
+
var ReactTransitionKeySet = require("./ReactTransitionKeySet");
|
|
24
|
+
|
|
25
|
+
var ReactTransitionGroup = React.createClass({
|
|
26
|
+
|
|
27
|
+
propTypes: {
|
|
28
|
+
transitionName: React.PropTypes.string.isRequired,
|
|
29
|
+
transitionEnter: React.PropTypes.bool,
|
|
30
|
+
transitionLeave: React.PropTypes.bool,
|
|
31
|
+
onTransition: React.PropTypes.func,
|
|
32
|
+
component: React.PropTypes.func
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
getDefaultProps: function() {
|
|
36
|
+
return {
|
|
37
|
+
transitionEnter: true,
|
|
38
|
+
transitionLeave: true,
|
|
39
|
+
component: React.DOM.span
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
componentWillMount: function() {
|
|
44
|
+
// _transitionGroupCurrentKeys stores the union of previous *and* next keys.
|
|
45
|
+
// If this were a component we'd store it as state, however, since this must
|
|
46
|
+
// be a mixin, we need to keep the result of the union of keys in each
|
|
47
|
+
// call to animateChildren() which happens in render(), so we can't
|
|
48
|
+
// call setState() in there.
|
|
49
|
+
this._transitionGroupCurrentKeys = {};
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
componentDidUpdate: function() {
|
|
53
|
+
if (this.props.onTransition) {
|
|
54
|
+
this.props.onTransition();
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Render some children in a transitionable way.
|
|
60
|
+
*/
|
|
61
|
+
renderTransitionableChildren: function(sourceChildren) {
|
|
62
|
+
var children = {};
|
|
63
|
+
var childMapping = ReactTransitionKeySet.getChildMapping(sourceChildren);
|
|
64
|
+
|
|
65
|
+
var currentKeys = ReactTransitionKeySet.mergeKeySets(
|
|
66
|
+
this._transitionGroupCurrentKeys,
|
|
67
|
+
ReactTransitionKeySet.getKeySet(sourceChildren)
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
for (var key in currentKeys) {
|
|
71
|
+
// Here is how we keep the nodes in the DOM. ReactTransitionableChild
|
|
72
|
+
// knows how to hold onto its child if it changes to undefined. Here, we
|
|
73
|
+
// may look up an old key in the new children, and it may switch to
|
|
74
|
+
// undefined. React's reconciler will keep the ReactTransitionableChild
|
|
75
|
+
// instance alive such that we can animate it.
|
|
76
|
+
if (childMapping[key] || this.props.transitionLeave) {
|
|
77
|
+
children[key] = ReactTransitionableChild({
|
|
78
|
+
name: this.props.transitionName,
|
|
79
|
+
enter: this.props.transitionEnter,
|
|
80
|
+
onDoneLeaving: this._handleDoneLeaving.bind(this, key)
|
|
81
|
+
}, childMapping[key]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this._transitionGroupCurrentKeys = currentKeys;
|
|
86
|
+
|
|
87
|
+
return children;
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
_handleDoneLeaving: function(key) {
|
|
91
|
+
// When the leave animation finishes, we should blow away the actual DOM
|
|
92
|
+
// node.
|
|
93
|
+
delete this._transitionGroupCurrentKeys[key];
|
|
94
|
+
this.forceUpdate();
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
render: function() {
|
|
98
|
+
return this.transferPropsTo(
|
|
99
|
+
this.props.component(
|
|
100
|
+
{
|
|
101
|
+
transitionName: null,
|
|
102
|
+
transitionEnter: null,
|
|
103
|
+
transitionLeave: null,
|
|
104
|
+
component: null
|
|
105
|
+
},
|
|
106
|
+
this.renderTransitionableChildren(this.props.children)
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
module.exports = ReactTransitionGroup;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @typechecks static-only
|
|
17
|
+
* @providesModule ReactTransitionKeySet
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
"use strict";
|
|
21
|
+
|
|
22
|
+
var ReactChildren = require("./ReactChildren");
|
|
23
|
+
|
|
24
|
+
var MERGE_KEY_SETS_TAIL_SENTINEL = {};
|
|
25
|
+
|
|
26
|
+
var ReactTransitionKeySet = {
|
|
27
|
+
/**
|
|
28
|
+
* Given `this.props.children`, return an object mapping key to child. Just
|
|
29
|
+
* simple syntactic sugar around ReactChildren.map().
|
|
30
|
+
*
|
|
31
|
+
* @param {*} children `this.props.children`
|
|
32
|
+
* @return {object} Mapping of key to child
|
|
33
|
+
*/
|
|
34
|
+
getChildMapping: function(children) {
|
|
35
|
+
return ReactChildren.map(children, function(child) {
|
|
36
|
+
return child;
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Simple syntactic sugar to get an object with keys of all of `children`.
|
|
42
|
+
* Does not have references to the children themselves.
|
|
43
|
+
*
|
|
44
|
+
* @param {*} children `this.props.children`
|
|
45
|
+
* @return {object} Mapping of key to the value "true"
|
|
46
|
+
*/
|
|
47
|
+
getKeySet: function(children) {
|
|
48
|
+
return ReactChildren.map(children, function() {
|
|
49
|
+
return true;
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* When you're adding or removing children some may be added or removed in the
|
|
55
|
+
* same render pass. We want ot show *both* since we want to simultaneously
|
|
56
|
+
* animate elements in and out. This function takes a previous set of keys
|
|
57
|
+
* and a new set of keys and merges them with its best guess of the correct
|
|
58
|
+
* ordering. In the future we may expose some of the utilities in
|
|
59
|
+
* ReactMultiChild to make this easy, but for now React itself does not
|
|
60
|
+
* directly have this concept of the union of prevChildren and nextChildren
|
|
61
|
+
* so we implement it here.
|
|
62
|
+
*
|
|
63
|
+
* @param {object} prev prev child keys as returned from
|
|
64
|
+
* `ReactTransitionKeySet.getKeySet()`.
|
|
65
|
+
* @param {object} next next child keys as returned from
|
|
66
|
+
* `ReactTransitionKeySet.getKeySet()`.
|
|
67
|
+
* @return {object} a key set that contains all keys in `prev` and all keys
|
|
68
|
+
* in `next` in a reasonable order.
|
|
69
|
+
*/
|
|
70
|
+
mergeKeySets: function(prev, next) {
|
|
71
|
+
prev = prev || {};
|
|
72
|
+
next = next || {};
|
|
73
|
+
|
|
74
|
+
var keySet = {};
|
|
75
|
+
var prevKeys = Object.keys(prev).concat([MERGE_KEY_SETS_TAIL_SENTINEL]);
|
|
76
|
+
var nextKeys = Object.keys(next).concat([MERGE_KEY_SETS_TAIL_SENTINEL]);
|
|
77
|
+
var i;
|
|
78
|
+
for (i = 0; i < prevKeys.length - 1; i++) {
|
|
79
|
+
var prevKey = prevKeys[i];
|
|
80
|
+
if (next[prevKey]) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// This key is not in the new set. Place it in our
|
|
85
|
+
// best guess where it should go. We do this by searching
|
|
86
|
+
// for a key after the current one in prevKeys that is
|
|
87
|
+
// still in nextKeys, and inserting right before it.
|
|
88
|
+
// I know this is O(n^2), but this is not a particularly
|
|
89
|
+
// hot code path.
|
|
90
|
+
var insertPos = -1;
|
|
91
|
+
|
|
92
|
+
for (var j = i + 1; j < prevKeys.length; j++) {
|
|
93
|
+
insertPos = nextKeys.indexOf(prevKeys[j]);
|
|
94
|
+
if (insertPos >= 0) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Insert before insertPos
|
|
100
|
+
nextKeys.splice(insertPos, 0, prevKey);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (i = 0; i < nextKeys.length - 1; i++) {
|
|
104
|
+
keySet[nextKeys[i]] = true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return keySet;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
module.exports = ReactTransitionKeySet;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @providesModule ReactTransitionableChild
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var React = require("./React");
|
|
22
|
+
var CSSCore = require("./CSSCore");
|
|
23
|
+
var ReactTransitionEvents = require("./ReactTransitionEvents");
|
|
24
|
+
|
|
25
|
+
// We don't remove the element from the DOM until we receive an animationend or
|
|
26
|
+
// transitionend event. If the user screws up and forgets to add an animation
|
|
27
|
+
// their node will be stuck in the DOM forever, so we detect if an animation
|
|
28
|
+
// does not start and if it doesn't, we just call the end listener immediately.
|
|
29
|
+
var TICK = 17;
|
|
30
|
+
var NO_EVENT_TIMEOUT = 5000;
|
|
31
|
+
|
|
32
|
+
var noEventListener = null;
|
|
33
|
+
|
|
34
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
35
|
+
noEventListener = function() {
|
|
36
|
+
console.warn(
|
|
37
|
+
'transition(): tried to perform an animation without ' +
|
|
38
|
+
'an animationend or transitionend event after timeout (' +
|
|
39
|
+
NO_EVENT_TIMEOUT + 'ms). You should either disable this ' +
|
|
40
|
+
'transition in JS or add a CSS animation/transition.'
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* This component is simply responsible for watching when its single child
|
|
47
|
+
* changes to undefined and animating the old child out. It does this by
|
|
48
|
+
* recording its old child in savedChildren when it detects this event is about
|
|
49
|
+
* to occur.
|
|
50
|
+
*/
|
|
51
|
+
var ReactTransitionableChild = React.createClass({
|
|
52
|
+
/**
|
|
53
|
+
* Perform an actual DOM transition. This takes care of a few things:
|
|
54
|
+
* - Adding the second CSS class to trigger the transition
|
|
55
|
+
* - Listening for the finish event
|
|
56
|
+
* - Cleaning up the css (unless noReset is true)
|
|
57
|
+
*/
|
|
58
|
+
transition: function(animationType, noReset, finishCallback) {
|
|
59
|
+
var node = this.getDOMNode();
|
|
60
|
+
var className = this.props.name + '-' + animationType;
|
|
61
|
+
var activeClassName = className + '-active';
|
|
62
|
+
var noEventTimeout = null;
|
|
63
|
+
|
|
64
|
+
var endListener = function() {
|
|
65
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
66
|
+
clearTimeout(noEventTimeout);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// If this gets invoked after the component is unmounted it's OK.
|
|
70
|
+
if (!noReset) {
|
|
71
|
+
// Usually this means you're about to remove the node if you want to
|
|
72
|
+
// leave it in its animated state.
|
|
73
|
+
CSSCore.removeClass(node, className);
|
|
74
|
+
CSSCore.removeClass(node, activeClassName);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ReactTransitionEvents.removeEndEventListener(node, endListener);
|
|
78
|
+
|
|
79
|
+
// Usually this optional callback is used for informing an owner of
|
|
80
|
+
// a leave animation and telling it to remove the child.
|
|
81
|
+
finishCallback && finishCallback();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
ReactTransitionEvents.addEndEventListener(node, endListener);
|
|
85
|
+
|
|
86
|
+
CSSCore.addClass(node, className);
|
|
87
|
+
|
|
88
|
+
// Need to do this to actually trigger a transition.
|
|
89
|
+
this.queueClass(activeClassName);
|
|
90
|
+
|
|
91
|
+
if ("production" !== process.env.NODE_ENV) {
|
|
92
|
+
noEventTimeout = setTimeout(noEventListener, NO_EVENT_TIMEOUT);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
queueClass: function(className) {
|
|
97
|
+
this.classNameQueue.push(className);
|
|
98
|
+
|
|
99
|
+
if (this.props.runNextTick) {
|
|
100
|
+
this.props.runNextTick(this.flushClassNameQueue);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!this.timeout) {
|
|
105
|
+
this.timeout = setTimeout(this.flushClassNameQueue, TICK);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
flushClassNameQueue: function() {
|
|
110
|
+
if (this.isMounted()) {
|
|
111
|
+
this.classNameQueue.forEach(
|
|
112
|
+
CSSCore.addClass.bind(CSSCore, this.getDOMNode())
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
this.classNameQueue.length = 0;
|
|
116
|
+
this.timeout = null;
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
componentWillMount: function() {
|
|
120
|
+
this.classNameQueue = [];
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
componentWillUnmount: function() {
|
|
124
|
+
if (this.timeout) {
|
|
125
|
+
clearTimeout(this.timeout);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
componentWillReceiveProps: function(nextProps) {
|
|
130
|
+
if (!nextProps.children && this.props.children) {
|
|
131
|
+
this.savedChildren = this.props.children;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
componentDidMount: function(node) {
|
|
136
|
+
if (this.props.enter) {
|
|
137
|
+
this.transition('enter');
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
componentDidUpdate: function(prevProps, prevState, node) {
|
|
142
|
+
if (prevProps.children && !this.props.children) {
|
|
143
|
+
this.transition('leave', true, this.props.onDoneLeaving);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
render: function() {
|
|
148
|
+
return this.props.children || this.savedChildren;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
module.exports = ReactTransitionableChild;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013 Facebook, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @providesModule ReactUpdates
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
var invariant = require("./invariant");
|
|
22
|
+
|
|
23
|
+
var dirtyComponents = [];
|
|
24
|
+
|
|
25
|
+
var batchingStrategy = null;
|
|
26
|
+
|
|
27
|
+
function ensureBatchingStrategy() {
|
|
28
|
+
("production" !== process.env.NODE_ENV ? invariant(batchingStrategy, 'ReactUpdates: must inject a batching strategy') : invariant(batchingStrategy));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function batchedUpdates(callback, param) {
|
|
32
|
+
ensureBatchingStrategy();
|
|
33
|
+
batchingStrategy.batchedUpdates(callback, param);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Array comparator for ReactComponents by owner depth
|
|
38
|
+
*
|
|
39
|
+
* @param {ReactComponent} c1 first component you're comparing
|
|
40
|
+
* @param {ReactComponent} c2 second component you're comparing
|
|
41
|
+
* @return {number} Return value usable by Array.prototype.sort().
|
|
42
|
+
*/
|
|
43
|
+
function mountDepthComparator(c1, c2) {
|
|
44
|
+
return c1._mountDepth - c2._mountDepth;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function runBatchedUpdates() {
|
|
48
|
+
// Since reconciling a component higher in the owner hierarchy usually (not
|
|
49
|
+
// always -- see shouldComponentUpdate()) will reconcile children, reconcile
|
|
50
|
+
// them before their children by sorting the array.
|
|
51
|
+
|
|
52
|
+
dirtyComponents.sort(mountDepthComparator);
|
|
53
|
+
|
|
54
|
+
for (var i = 0; i < dirtyComponents.length; i++) {
|
|
55
|
+
// If a component is unmounted before pending changes apply, ignore them
|
|
56
|
+
// TODO: Queue unmounts in the same list to avoid this happening at all
|
|
57
|
+
var component = dirtyComponents[i];
|
|
58
|
+
if (component.isMounted()) {
|
|
59
|
+
// If performUpdateIfNecessary happens to enqueue any new updates, we
|
|
60
|
+
// shouldn't execute the callbacks until the next render happens, so
|
|
61
|
+
// stash the callbacks first
|
|
62
|
+
var callbacks = component._pendingCallbacks;
|
|
63
|
+
component._pendingCallbacks = null;
|
|
64
|
+
component.performUpdateIfNecessary();
|
|
65
|
+
if (callbacks) {
|
|
66
|
+
for (var j = 0; j < callbacks.length; j++) {
|
|
67
|
+
callbacks[j].call(component);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function clearDirtyComponents() {
|
|
75
|
+
dirtyComponents.length = 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function flushBatchedUpdates() {
|
|
79
|
+
// Run these in separate functions so the JIT can optimize
|
|
80
|
+
try {
|
|
81
|
+
runBatchedUpdates();
|
|
82
|
+
} catch (e) {
|
|
83
|
+
// IE 8 requires catch to use finally.
|
|
84
|
+
throw e;
|
|
85
|
+
} finally {
|
|
86
|
+
clearDirtyComponents();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Mark a component as needing a rerender, adding an optional callback to a
|
|
92
|
+
* list of functions which will be executed once the rerender occurs.
|
|
93
|
+
*/
|
|
94
|
+
function enqueueUpdate(component, callback) {
|
|
95
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
96
|
+
!callback || typeof callback === "function",
|
|
97
|
+
'enqueueUpdate(...): You called `setProps`, `replaceProps`, ' +
|
|
98
|
+
'`setState`, `replaceState`, or `forceUpdate` with a callback that ' +
|
|
99
|
+
'isn\'t callable.'
|
|
100
|
+
) : invariant(!callback || typeof callback === "function"));
|
|
101
|
+
ensureBatchingStrategy();
|
|
102
|
+
|
|
103
|
+
if (!batchingStrategy.isBatchingUpdates) {
|
|
104
|
+
component.performUpdateIfNecessary();
|
|
105
|
+
callback && callback();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
dirtyComponents.push(component);
|
|
110
|
+
|
|
111
|
+
if (callback) {
|
|
112
|
+
if (component._pendingCallbacks) {
|
|
113
|
+
component._pendingCallbacks.push(callback);
|
|
114
|
+
} else {
|
|
115
|
+
component._pendingCallbacks = [callback];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var ReactUpdatesInjection = {
|
|
121
|
+
injectBatchingStrategy: function(_batchingStrategy) {
|
|
122
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
123
|
+
_batchingStrategy,
|
|
124
|
+
'ReactUpdates: must provide a batching strategy'
|
|
125
|
+
) : invariant(_batchingStrategy));
|
|
126
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
127
|
+
typeof _batchingStrategy.batchedUpdates === 'function',
|
|
128
|
+
'ReactUpdates: must provide a batchedUpdates() function'
|
|
129
|
+
) : invariant(typeof _batchingStrategy.batchedUpdates === 'function'));
|
|
130
|
+
("production" !== process.env.NODE_ENV ? invariant(
|
|
131
|
+
typeof _batchingStrategy.isBatchingUpdates === 'boolean',
|
|
132
|
+
'ReactUpdates: must provide an isBatchingUpdates boolean attribute'
|
|
133
|
+
) : invariant(typeof _batchingStrategy.isBatchingUpdates === 'boolean'));
|
|
134
|
+
batchingStrategy = _batchingStrategy;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
var ReactUpdates = {
|
|
139
|
+
batchedUpdates: batchedUpdates,
|
|
140
|
+
enqueueUpdate: enqueueUpdate,
|
|
141
|
+
flushBatchedUpdates: flushBatchedUpdates,
|
|
142
|
+
injection: ReactUpdatesInjection
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
module.exports = ReactUpdates;
|