react 0.7.0 → 0.9.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.
Files changed (217) hide show
  1. package/README.md +10 -231
  2. package/addons.js +1 -0
  3. package/lib/AutoFocusMixin.js +30 -0
  4. package/lib/CSSCore.js +115 -0
  5. package/lib/CSSProperty.js +121 -0
  6. package/lib/CSSPropertyOperations.js +97 -0
  7. package/lib/ChangeEventPlugin.js +387 -0
  8. package/lib/ClientReactRootIndex.js +30 -0
  9. package/lib/CompositionEventPlugin.js +260 -0
  10. package/lib/DOMChildrenOperations.js +165 -0
  11. package/lib/DOMProperty.js +268 -0
  12. package/lib/DOMPropertyOperations.js +181 -0
  13. package/lib/Danger.js +187 -0
  14. package/lib/DefaultDOMPropertyConfig.js +203 -0
  15. package/lib/DefaultEventPluginOrder.js +44 -0
  16. package/lib/EnterLeaveEventPlugin.js +145 -0
  17. package/lib/EventConstants.js +76 -0
  18. package/lib/EventListener.js +69 -0
  19. package/lib/EventPluginHub.js +293 -0
  20. package/lib/EventPluginRegistry.js +281 -0
  21. package/lib/EventPluginUtils.js +214 -0
  22. package/lib/EventPropagators.js +143 -0
  23. package/lib/ExecutionEnvironment.js +44 -0
  24. package/lib/LinkedStateMixin.js +46 -0
  25. package/lib/LinkedValueUtils.js +161 -0
  26. package/lib/MobileSafariClickEventPlugin.js +63 -0
  27. package/lib/PooledClass.js +119 -0
  28. package/lib/React.js +95 -0
  29. package/lib/ReactCSSTransitionGroup.js +65 -0
  30. package/lib/ReactCSSTransitionGroupChild.js +138 -0
  31. package/lib/ReactChildren.js +132 -0
  32. package/lib/ReactComponent.js +550 -0
  33. package/lib/ReactComponentBrowserEnvironment.js +158 -0
  34. package/lib/ReactComponentEnvironment.js +26 -0
  35. package/lib/ReactCompositeComponent.js +1455 -0
  36. package/lib/ReactContext.js +67 -0
  37. package/lib/ReactCurrentOwner.js +39 -0
  38. package/lib/ReactDOM.js +207 -0
  39. package/lib/ReactDOMButton.js +68 -0
  40. package/lib/ReactDOMComponent.js +399 -0
  41. package/lib/ReactDOMForm.js +59 -0
  42. package/lib/ReactDOMIDOperations.js +218 -0
  43. package/lib/ReactDOMImg.js +58 -0
  44. package/lib/ReactDOMInput.js +181 -0
  45. package/lib/ReactDOMOption.js +51 -0
  46. package/lib/ReactDOMSelect.js +179 -0
  47. package/lib/ReactDOMSelection.js +189 -0
  48. package/lib/ReactDOMTextarea.js +140 -0
  49. package/lib/ReactDefaultBatchingStrategy.js +75 -0
  50. package/lib/ReactDefaultInjection.js +115 -0
  51. package/lib/ReactDefaultPerf.js +244 -0
  52. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  53. package/lib/ReactErrorUtils.js +37 -0
  54. package/lib/ReactEventEmitter.js +339 -0
  55. package/lib/ReactEventEmitterMixin.js +57 -0
  56. package/lib/ReactEventTopLevelCallback.js +149 -0
  57. package/lib/ReactInjection.js +39 -0
  58. package/lib/ReactInputSelection.js +140 -0
  59. package/lib/ReactInstanceHandles.js +338 -0
  60. package/lib/ReactLink.js +54 -0
  61. package/lib/ReactMarkupChecksum.js +53 -0
  62. package/lib/ReactMount.js +641 -0
  63. package/lib/ReactMountReady.js +95 -0
  64. package/lib/ReactMultiChild.js +425 -0
  65. package/lib/ReactMultiChildUpdateTypes.js +38 -0
  66. package/lib/ReactOwner.js +154 -0
  67. package/lib/ReactPerf.js +85 -0
  68. package/lib/ReactPropTransferer.js +147 -0
  69. package/lib/ReactPropTypeLocationNames.js +31 -0
  70. package/lib/ReactPropTypeLocations.js +29 -0
  71. package/lib/ReactPropTypes.js +359 -0
  72. package/lib/ReactPutListenerQueue.js +61 -0
  73. package/lib/ReactReconcileTransaction.js +181 -0
  74. package/lib/ReactRootIndex.js +36 -0
  75. package/lib/ReactServerRendering.js +59 -0
  76. package/lib/ReactStateSetters.js +111 -0
  77. package/lib/ReactTestUtils.js +394 -0
  78. package/lib/ReactTextComponent.js +99 -0
  79. package/lib/ReactTransitionChildMapping.js +106 -0
  80. package/lib/ReactTransitionEvents.js +97 -0
  81. package/lib/ReactTransitionGroup.js +187 -0
  82. package/lib/ReactUpdates.js +148 -0
  83. package/lib/ReactWithAddons.js +51 -0
  84. package/lib/SelectEventPlugin.js +200 -0
  85. package/lib/ServerReactRootIndex.js +36 -0
  86. package/lib/SimpleEventPlugin.js +413 -0
  87. package/lib/SyntheticClipboardEvent.js +51 -0
  88. package/lib/SyntheticCompositionEvent.js +51 -0
  89. package/lib/SyntheticDragEvent.js +44 -0
  90. package/lib/SyntheticEvent.js +164 -0
  91. package/lib/SyntheticFocusEvent.js +44 -0
  92. package/lib/SyntheticKeyboardEvent.js +58 -0
  93. package/lib/SyntheticMouseEvent.js +85 -0
  94. package/lib/SyntheticTouchEvent.js +50 -0
  95. package/lib/SyntheticUIEvent.js +45 -0
  96. package/lib/SyntheticWheelEvent.js +66 -0
  97. package/lib/Transaction.js +276 -0
  98. package/lib/ViewportMetrics.js +37 -0
  99. package/lib/accumulate.js +54 -0
  100. package/lib/adler32.js +39 -0
  101. package/lib/cloneWithProps.js +59 -0
  102. package/lib/containsNode.js +49 -0
  103. package/lib/copyProperties.js +54 -0
  104. package/lib/createArrayFrom.js +91 -0
  105. package/lib/createFullPageComponent.js +63 -0
  106. package/lib/createNodesFromMarkup.js +93 -0
  107. package/lib/createObjectFrom.js +61 -0
  108. package/lib/cx.js +44 -0
  109. package/lib/dangerousStyleValue.js +57 -0
  110. package/lib/emptyFunction.js +43 -0
  111. package/lib/escapeTextForBrowser.js +47 -0
  112. package/lib/flattenChildren.js +57 -0
  113. package/lib/forEachAccumulated.js +36 -0
  114. package/lib/getActiveElement.js +34 -0
  115. package/lib/getEventKey.js +85 -0
  116. package/lib/getEventTarget.js +36 -0
  117. package/lib/getMarkupWrap.js +118 -0
  118. package/lib/getNodeForCharacterOffset.js +80 -0
  119. package/lib/getReactRootElementInContainer.js +40 -0
  120. package/lib/getTextContentAccessor.js +42 -0
  121. package/lib/getUnboundedScrollPosition.js +45 -0
  122. package/lib/hyphenate.js +35 -0
  123. package/lib/invariant.js +62 -0
  124. package/lib/isEventSupported.js +70 -0
  125. package/lib/isNode.js +33 -0
  126. package/lib/isTextInputElement.js +49 -0
  127. package/lib/isTextNode.js +30 -0
  128. package/lib/joinClasses.js +44 -0
  129. package/lib/keyMirror.js +58 -0
  130. package/lib/keyOf.js +41 -0
  131. package/lib/memoizeStringOnly.js +39 -0
  132. package/lib/merge.js +37 -0
  133. package/lib/mergeHelpers.js +136 -0
  134. package/lib/mergeInto.js +45 -0
  135. package/lib/mixInto.js +34 -0
  136. package/lib/objMap.js +47 -0
  137. package/lib/objMapKeyVal.js +47 -0
  138. package/lib/onlyChild.js +43 -0
  139. package/lib/performanceNow.js +42 -0
  140. package/lib/shallowEqual.js +49 -0
  141. package/lib/shouldUpdateReactComponent.js +58 -0
  142. package/lib/toArray.js +75 -0
  143. package/lib/traverseAllChildren.js +189 -0
  144. package/lib/warning.js +48 -0
  145. package/package.json +33 -21
  146. package/react.js +1 -0
  147. package/.npmignore +0 -7
  148. package/.travis.yml +0 -7
  149. package/Jakefile.js +0 -39
  150. package/LICENSE +0 -19
  151. package/browser-test/dist.html +0 -90
  152. package/browser-test/index.html +0 -86
  153. package/browser-test/min.html +0 -90
  154. package/dist/react.js +0 -3141
  155. package/dist/react.min.js +0 -22
  156. package/doc/advanced.md +0 -174
  157. package/doc/color-def.graffle +0 -938
  158. package/doc/color-def.png +0 -0
  159. package/doc/simple.dot +0 -25
  160. package/doc/simple.png +0 -0
  161. package/examples/longer-example.js +0 -41
  162. package/examples/simple.js +0 -45
  163. package/examples/using-ast-directly.js +0 -30
  164. package/examples/using-events1.js +0 -79
  165. package/examples/using-log-events.js +0 -43
  166. package/lib/base-task.js +0 -120
  167. package/lib/cb-task.js +0 -84
  168. package/lib/core.js +0 -138
  169. package/lib/dsl.js +0 -138
  170. package/lib/error.js +0 -55
  171. package/lib/event-collector.js +0 -81
  172. package/lib/event-manager.js +0 -89
  173. package/lib/eventemitter.js +0 -20
  174. package/lib/finalcb-first-task.js +0 -68
  175. package/lib/finalcb-task.js +0 -65
  176. package/lib/id.js +0 -22
  177. package/lib/input-parser.js +0 -56
  178. package/lib/log-events.js +0 -101
  179. package/lib/parse.js +0 -41
  180. package/lib/promise-resolve.js +0 -50
  181. package/lib/promise-task.js +0 -93
  182. package/lib/react.js +0 -59
  183. package/lib/ret-task.js +0 -71
  184. package/lib/sprintf.js +0 -18
  185. package/lib/status.js +0 -14
  186. package/lib/task.js +0 -251
  187. package/lib/track-tasks.js +0 -74
  188. package/lib/validate.js +0 -159
  189. package/lib/vcon.js +0 -113
  190. package/lib/when-task.js +0 -84
  191. package/src/dist.build.requirejs +0 -20
  192. package/test/ast.mocha.js +0 -136
  193. package/test/cb-task.mocha.js +0 -220
  194. package/test/core-deferred.mocha.js +0 -143
  195. package/test/core-when.mocha.js +0 -96
  196. package/test/core.mocha.js +0 -589
  197. package/test/dsl.mocha.js +0 -352
  198. package/test/event-manager.mocha.js +0 -119
  199. package/test/exec-options.mocha.js +0 -48
  200. package/test/finalcb-task.mocha.js +0 -58
  201. package/test/input-parser.mocha.js +0 -86
  202. package/test/log-events.mocha.js +0 -88
  203. package/test/mocha.opts +0 -2
  204. package/test/module-use.mocha.js +0 -164
  205. package/test/promise-auto-resolve.mocha.js +0 -68
  206. package/test/ret-task.mocha.js +0 -220
  207. package/test/task.mocha.js +0 -42
  208. package/test/validate-cb-task.mocha.js +0 -100
  209. package/test/validate-ret-task.mocha.js +0 -110
  210. package/test/validate.mocha.js +0 -324
  211. package/test/vcon.mocha.js +0 -193
  212. package/vendor/chai/chai.js +0 -4251
  213. package/vendor/jquery/jquery-1.7.1.js +0 -9266
  214. package/vendor/jquery/jquery-1.7.1.min.js +0 -4
  215. package/vendor/node/util.js +0 -531
  216. package/vendor/requirejs/require.js +0 -2045
  217. package/vendor/requirejs/require.min.js +0 -36
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Copyright 2013-2014 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 ReactTextComponent
17
+ * @typechecks static-only
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var DOMPropertyOperations = require("./DOMPropertyOperations");
23
+ var ReactComponent = require("./ReactComponent");
24
+
25
+ var escapeTextForBrowser = require("./escapeTextForBrowser");
26
+ var mixInto = require("./mixInto");
27
+
28
+ /**
29
+ * Text nodes violate a couple assumptions that React makes about components:
30
+ *
31
+ * - When mounting text into the DOM, adjacent text nodes are merged.
32
+ * - Text nodes cannot be assigned a React root ID.
33
+ *
34
+ * This component is used to wrap strings in elements so that they can undergo
35
+ * the same reconciliation that is applied to elements.
36
+ *
37
+ * TODO: Investigate representing React components in the DOM with text nodes.
38
+ *
39
+ * @class ReactTextComponent
40
+ * @extends ReactComponent
41
+ * @internal
42
+ */
43
+ var ReactTextComponent = function(initialText) {
44
+ this.construct({text: initialText});
45
+ };
46
+
47
+ mixInto(ReactTextComponent, ReactComponent.Mixin);
48
+ mixInto(ReactTextComponent, {
49
+
50
+ /**
51
+ * Creates the markup for this text node. This node is not intended to have
52
+ * any features besides containing text content.
53
+ *
54
+ * @param {string} rootID DOM ID of the root node.
55
+ * @param {ReactReconcileTransaction} transaction
56
+ * @param {number} mountDepth number of components in the owner hierarchy
57
+ * @return {string} Markup for this text node.
58
+ * @internal
59
+ */
60
+ mountComponent: function(rootID, transaction, mountDepth) {
61
+ ReactComponent.Mixin.mountComponent.call(
62
+ this,
63
+ rootID,
64
+ transaction,
65
+ mountDepth
66
+ );
67
+ return (
68
+ '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' +
69
+ escapeTextForBrowser(this.props.text) +
70
+ '</span>'
71
+ );
72
+ },
73
+
74
+ /**
75
+ * Updates this component by updating the text content.
76
+ *
77
+ * @param {object} nextComponent Contains the next text content.
78
+ * @param {ReactReconcileTransaction} transaction
79
+ * @internal
80
+ */
81
+ receiveComponent: function(nextComponent, transaction) {
82
+ var nextProps = nextComponent.props;
83
+ if (nextProps.text !== this.props.text) {
84
+ this.props.text = nextProps.text;
85
+ ReactComponent.BackendIDOperations.updateTextContentByID(
86
+ this._rootNodeID,
87
+ nextProps.text
88
+ );
89
+ }
90
+ }
91
+
92
+ });
93
+
94
+ // Expose the constructor on itself and the prototype for consistency with other
95
+ // descriptors.
96
+ ReactTextComponent.type = ReactTextComponent;
97
+ ReactTextComponent.prototype.type = ReactTextComponent;
98
+
99
+ module.exports = ReactTextComponent;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Copyright 2013-2014 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 ReactTransitionChildMapping
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var ReactChildren = require("./ReactChildren");
23
+
24
+ var ReactTransitionChildMapping = {
25
+ /**
26
+ * Given `this.props.children`, return an object mapping key to child. Just
27
+ * simple syntactic sugar around ReactChildren.map().
28
+ *
29
+ * @param {*} children `this.props.children`
30
+ * @return {object} Mapping of key to child
31
+ */
32
+ getChildMapping: function(children) {
33
+ return ReactChildren.map(children, function(child) {
34
+ return child;
35
+ });
36
+ },
37
+
38
+ /**
39
+ * When you're adding or removing children some may be added or removed in the
40
+ * same render pass. We want ot show *both* since we want to simultaneously
41
+ * animate elements in and out. This function takes a previous set of keys
42
+ * and a new set of keys and merges them with its best guess of the correct
43
+ * ordering. In the future we may expose some of the utilities in
44
+ * ReactMultiChild to make this easy, but for now React itself does not
45
+ * directly have this concept of the union of prevChildren and nextChildren
46
+ * so we implement it here.
47
+ *
48
+ * @param {object} prev prev children as returned from
49
+ * `ReactTransitionChildMapping.getChildMapping()`.
50
+ * @param {object} next next children as returned from
51
+ * `ReactTransitionChildMapping.getChildMapping()`.
52
+ * @return {object} a key set that contains all keys in `prev` and all keys
53
+ * in `next` in a reasonable order.
54
+ */
55
+ mergeChildMappings: function(prev, next) {
56
+ prev = prev || {};
57
+ next = next || {};
58
+
59
+ function getValueForKey(key) {
60
+ if (next.hasOwnProperty(key)) {
61
+ return next[key];
62
+ } else {
63
+ return prev[key];
64
+ }
65
+ }
66
+
67
+ // For each key of `next`, the list of keys to insert before that key in
68
+ // the combined list
69
+ var nextKeysPending = {};
70
+
71
+ var pendingKeys = [];
72
+ for (var prevKey in prev) {
73
+ if (next[prevKey]) {
74
+ if (pendingKeys.length) {
75
+ nextKeysPending[prevKey] = pendingKeys;
76
+ pendingKeys = [];
77
+ }
78
+ } else {
79
+ pendingKeys.push(prevKey);
80
+ }
81
+ }
82
+
83
+ var i;
84
+ var childMapping = {};
85
+ for (var nextKey in next) {
86
+ if (nextKeysPending[nextKey]) {
87
+ for (i = 0; i < nextKeysPending[nextKey].length; i++) {
88
+ var pendingNextKey = nextKeysPending[nextKey][i];
89
+ childMapping[nextKeysPending[nextKey][i]] = getValueForKey(
90
+ pendingNextKey
91
+ );
92
+ }
93
+ }
94
+ childMapping[nextKey] = getValueForKey(nextKey);
95
+ }
96
+
97
+ // Finally, add the keys which didn't appear before any key in `next`
98
+ for (i = 0; i < pendingKeys.length; i++) {
99
+ childMapping[pendingKeys[i]] = getValueForKey(pendingKeys[i]);
100
+ }
101
+
102
+ return childMapping;
103
+ }
104
+ };
105
+
106
+ module.exports = ReactTransitionChildMapping;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright 2013-2014 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 ReactTransitionEvents
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
22
+
23
+ var EVENT_NAME_MAP = {
24
+ transitionend: {
25
+ 'transition': 'transitionend',
26
+ 'WebkitTransition': 'webkitTransitionEnd',
27
+ 'MozTransition': 'mozTransitionEnd',
28
+ 'OTransition': 'oTransitionEnd',
29
+ 'msTransition': 'MSTransitionEnd'
30
+ },
31
+
32
+ animationend: {
33
+ 'animation': 'animationend',
34
+ 'WebkitAnimation': 'webkitAnimationEnd',
35
+ 'MozAnimation': 'mozAnimationEnd',
36
+ 'OAnimation': 'oAnimationEnd',
37
+ 'msAnimation': 'MSAnimationEnd'
38
+ }
39
+ };
40
+
41
+ var endEvents = [];
42
+
43
+ function detectEvents() {
44
+ var testEl = document.createElement('div');
45
+ var style = testEl.style;
46
+ for (var baseEventName in EVENT_NAME_MAP) {
47
+ var baseEvents = EVENT_NAME_MAP[baseEventName];
48
+ for (var styleName in baseEvents) {
49
+ if (styleName in style) {
50
+ endEvents.push(baseEvents[styleName]);
51
+ break;
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ if (ExecutionEnvironment.canUseDOM) {
58
+ detectEvents();
59
+ }
60
+
61
+ // We use the raw {add|remove}EventListener() call because EventListener
62
+ // does not know how to remove event listeners and we really should
63
+ // clean up. Also, these events are not triggered in older browsers
64
+ // so we should be A-OK here.
65
+
66
+ function addEventListener(node, eventName, eventListener) {
67
+ node.addEventListener(eventName, eventListener, false);
68
+ }
69
+
70
+ function removeEventListener(node, eventName, eventListener) {
71
+ node.removeEventListener(eventName, eventListener, false);
72
+ }
73
+
74
+ var ReactTransitionEvents = {
75
+ addEndEventListener: function(node, eventListener) {
76
+ if (endEvents.length === 0) {
77
+ // If CSS transitions are not supported, trigger an "end animation"
78
+ // event immediately.
79
+ window.setTimeout(eventListener, 0);
80
+ return;
81
+ }
82
+ endEvents.forEach(function(endEvent) {
83
+ addEventListener(node, endEvent, eventListener);
84
+ });
85
+ },
86
+
87
+ removeEndEventListener: function(node, eventListener) {
88
+ if (endEvents.length === 0) {
89
+ return;
90
+ }
91
+ endEvents.forEach(function(endEvent) {
92
+ removeEventListener(node, endEvent, eventListener);
93
+ });
94
+ }
95
+ };
96
+
97
+ module.exports = ReactTransitionEvents;
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Copyright 2013-2014 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 ReactTransitionChildMapping = require("./ReactTransitionChildMapping");
23
+
24
+ var cloneWithProps = require("./cloneWithProps");
25
+ var emptyFunction = require("./emptyFunction");
26
+ var merge = require("./merge");
27
+
28
+ var ReactTransitionGroup = React.createClass({
29
+
30
+ propTypes: {
31
+ component: React.PropTypes.func,
32
+ childFactory: React.PropTypes.func
33
+ },
34
+
35
+ getDefaultProps: function() {
36
+ return {
37
+ component: React.DOM.span,
38
+ childFactory: emptyFunction.thatReturnsArgument
39
+ };
40
+ },
41
+
42
+ getInitialState: function() {
43
+ return {
44
+ children: ReactTransitionChildMapping.getChildMapping(this.props.children)
45
+ };
46
+ },
47
+
48
+ componentWillReceiveProps: function(nextProps) {
49
+ var nextChildMapping = ReactTransitionChildMapping.getChildMapping(
50
+ nextProps.children
51
+ );
52
+ var prevChildMapping = this.state.children;
53
+
54
+ this.setState({
55
+ children: ReactTransitionChildMapping.mergeChildMappings(
56
+ prevChildMapping,
57
+ nextChildMapping
58
+ )
59
+ });
60
+
61
+ var key;
62
+
63
+ for (key in nextChildMapping) {
64
+ if (!prevChildMapping.hasOwnProperty(key) &&
65
+ !this.currentlyTransitioningKeys[key]) {
66
+ this.keysToEnter.push(key);
67
+ }
68
+ }
69
+
70
+ for (key in prevChildMapping) {
71
+ if (!nextChildMapping.hasOwnProperty(key) &&
72
+ !this.currentlyTransitioningKeys[key]) {
73
+ this.keysToLeave.push(key);
74
+ }
75
+ }
76
+
77
+ // If we want to someday check for reordering, we could do it here.
78
+ },
79
+
80
+ componentWillMount: function() {
81
+ this.currentlyTransitioningKeys = {};
82
+ this.keysToEnter = [];
83
+ this.keysToLeave = [];
84
+ },
85
+
86
+ componentDidUpdate: function() {
87
+ var keysToEnter = this.keysToEnter;
88
+ this.keysToEnter = [];
89
+ keysToEnter.forEach(this.performEnter);
90
+
91
+ var keysToLeave = this.keysToLeave;
92
+ this.keysToLeave = [];
93
+ keysToLeave.forEach(this.performLeave);
94
+ },
95
+
96
+ performEnter: function(key) {
97
+ this.currentlyTransitioningKeys[key] = true;
98
+
99
+ var component = this.refs[key];
100
+
101
+ if (component.componentWillEnter) {
102
+ component.componentWillEnter(
103
+ this._handleDoneEntering.bind(this, key)
104
+ );
105
+ } else {
106
+ this._handleDoneEntering(key);
107
+ }
108
+ },
109
+
110
+ _handleDoneEntering: function(key) {
111
+ var component = this.refs[key];
112
+ if (component.componentDidEnter) {
113
+ component.componentDidEnter();
114
+ }
115
+
116
+ delete this.currentlyTransitioningKeys[key];
117
+
118
+ var currentChildMapping = ReactTransitionChildMapping.getChildMapping(
119
+ this.props.children
120
+ );
121
+
122
+ if (!currentChildMapping.hasOwnProperty(key)) {
123
+ // This was removed before it had fully entered. Remove it.
124
+ this.performLeave(key);
125
+ }
126
+ },
127
+
128
+ performLeave: function(key) {
129
+ this.currentlyTransitioningKeys[key] = true;
130
+
131
+ var component = this.refs[key];
132
+ if (component.componentWillLeave) {
133
+ component.componentWillLeave(this._handleDoneLeaving.bind(this, key));
134
+ } else {
135
+ // Note that this is somewhat dangerous b/c it calls setState()
136
+ // again, effectively mutating the component before all the work
137
+ // is done.
138
+ this._handleDoneLeaving(key);
139
+ }
140
+ },
141
+
142
+ _handleDoneLeaving: function(key) {
143
+ var component = this.refs[key];
144
+
145
+ if (component.componentDidLeave) {
146
+ component.componentDidLeave();
147
+ }
148
+
149
+ delete this.currentlyTransitioningKeys[key];
150
+
151
+ var currentChildMapping = ReactTransitionChildMapping.getChildMapping(
152
+ this.props.children
153
+ );
154
+
155
+ if (currentChildMapping.hasOwnProperty(key)) {
156
+ // This entered again before it fully left. Add it again.
157
+ this.performEnter(key);
158
+ } else {
159
+ var newChildren = merge(this.state.children);
160
+ delete newChildren[key];
161
+ this.setState({children: newChildren});
162
+ }
163
+ },
164
+
165
+ render: function() {
166
+ // TODO: we could get rid of the need for the wrapper node
167
+ // by cloning a single child
168
+ var childrenToRender = {};
169
+ for (var key in this.state.children) {
170
+ var child = this.state.children[key];
171
+ if (child) {
172
+ // You may need to apply reactive updates to a child as it is leaving.
173
+ // The normal React way to do it won't work since the child will have
174
+ // already been removed. In case you need this behavior you can provide
175
+ // a childFactory function to wrap every child, even the ones that are
176
+ // leaving.
177
+ childrenToRender[key] = cloneWithProps(
178
+ this.props.childFactory(child),
179
+ {ref: key}
180
+ );
181
+ }
182
+ }
183
+ return this.transferPropsTo(this.props.component(null, childrenToRender));
184
+ }
185
+ });
186
+
187
+ module.exports = ReactTransitionGroup;