react 0.13.2 → 0.14.0-alpha3

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 (197) hide show
  1. package/README.md +1 -1
  2. package/addons.js +7 -0
  3. package/addons/CSSTransitionGroup.js +1 -0
  4. package/addons/LinkedStateMixin.js +1 -0
  5. package/addons/Perf.js +1 -0
  6. package/addons/PureRenderMixin.js +1 -0
  7. package/addons/TestUtils.js +1 -0
  8. package/addons/TransitionGroup.js +1 -0
  9. package/addons/batchedUpdates.js +1 -0
  10. package/addons/cloneWithProps.js +1 -0
  11. package/addons/createFragment.js +1 -0
  12. package/addons/renderSubtreeIntoContainer.js +1 -0
  13. package/addons/shallowCompare.js +1 -0
  14. package/addons/update.js +1 -0
  15. package/dist/JSXTransformer.js +3355 -1685
  16. package/dist/react-with-addons.js +3320 -5133
  17. package/dist/react-with-addons.min.js +6 -7
  18. package/dist/react.js +2962 -4548
  19. package/dist/react.min.js +5 -5
  20. package/lib/AutoFocusMixin.js +4 -3
  21. package/lib/BeforeInputEventPlugin.js +30 -118
  22. package/lib/CSSCore.js +12 -23
  23. package/lib/CSSProperty.js +4 -3
  24. package/lib/CSSPropertyOperations.js +14 -30
  25. package/lib/CallbackQueue.js +7 -10
  26. package/lib/ChangeEventPlugin.js +24 -88
  27. package/lib/ClientReactRootIndex.js +2 -2
  28. package/lib/DOMChildrenOperations.js +13 -33
  29. package/lib/DOMProperty.js +41 -67
  30. package/lib/DOMPropertyOperations.js +30 -51
  31. package/lib/Danger.js +19 -62
  32. package/lib/DefaultEventPluginOrder.js +2 -12
  33. package/lib/EnterLeaveEventPlugin.js +11 -33
  34. package/lib/EventConstants.js +2 -2
  35. package/lib/EventListener.js +11 -13
  36. package/lib/EventPluginHub.js +44 -47
  37. package/lib/EventPluginRegistry.js +18 -74
  38. package/lib/EventPluginUtils.js +27 -38
  39. package/lib/EventPropagators.js +23 -26
  40. package/lib/ExecutionEnvironment.js +4 -8
  41. package/lib/FallbackCompositionState.js +3 -3
  42. package/lib/HTMLDOMPropertyConfig.js +7 -19
  43. package/lib/LinkedStateMixin.js +3 -6
  44. package/lib/LinkedValueUtils.js +34 -64
  45. package/lib/LocalEventTrapMixin.js +9 -16
  46. package/lib/Object.assign.js +1 -1
  47. package/lib/PooledClass.js +8 -11
  48. package/lib/React.js +9 -129
  49. package/lib/ReactBrowserComponentMixin.js +9 -2
  50. package/lib/ReactBrowserEventEmitter.js +26 -82
  51. package/lib/ReactCSSTransitionGroup.js +13 -24
  52. package/lib/ReactCSSTransitionGroupChild.js +18 -28
  53. package/lib/ReactChildReconciler.js +11 -19
  54. package/lib/ReactChildren.js +21 -28
  55. package/lib/ReactClass.js +81 -234
  56. package/lib/ReactComponent.js +17 -33
  57. package/lib/ReactComponentBrowserEnvironment.js +4 -8
  58. package/lib/ReactComponentEnvironment.js +6 -12
  59. package/lib/ReactComponentWithPureRenderMixin.js +4 -5
  60. package/lib/ReactCompositeComponent.js +87 -311
  61. package/lib/ReactContext.js +2 -44
  62. package/lib/ReactCurrentOwner.js +1 -3
  63. package/lib/ReactDOM.js +4 -2
  64. package/lib/ReactDOMButton.js +3 -4
  65. package/lib/ReactDOMClient.js +85 -0
  66. package/lib/ReactDOMComponent.js +182 -146
  67. package/lib/ReactDOMForm.js +3 -3
  68. package/lib/ReactDOMIDOperations.js +11 -22
  69. package/lib/ReactDOMIframe.js +3 -3
  70. package/lib/ReactDOMImg.js +3 -3
  71. package/lib/ReactDOMInput.js +22 -35
  72. package/lib/ReactDOMOption.js +67 -10
  73. package/lib/ReactDOMSelect.js +50 -28
  74. package/lib/ReactDOMSelection.js +5 -20
  75. package/lib/ReactDOMServer.js +24 -0
  76. package/lib/ReactDOMTextComponent.js +17 -18
  77. package/lib/ReactDOMTextarea.js +15 -27
  78. package/lib/ReactDefaultBatchingStrategy.js +9 -13
  79. package/lib/ReactDefaultInjection.js +31 -40
  80. package/lib/ReactDefaultPerf.js +36 -69
  81. package/lib/ReactDefaultPerfAnalysis.js +8 -14
  82. package/lib/ReactElement.js +24 -57
  83. package/lib/ReactElementValidator.js +38 -105
  84. package/lib/ReactEmptyComponent.js +7 -11
  85. package/lib/ReactErrorUtils.js +2 -2
  86. package/lib/ReactEventEmitterMixin.js +3 -12
  87. package/lib/ReactEventListener.js +16 -38
  88. package/lib/ReactFragment.js +23 -54
  89. package/lib/ReactInjection.js +1 -1
  90. package/lib/ReactInputSelection.js +11 -21
  91. package/lib/ReactInstanceHandles.js +27 -57
  92. package/lib/ReactInstanceMap.js +5 -5
  93. package/lib/ReactIsomorphic.js +70 -0
  94. package/lib/ReactLifeCycle.js +1 -1
  95. package/lib/ReactLink.js +2 -4
  96. package/lib/ReactMarkupChecksum.js +5 -10
  97. package/lib/ReactMount.js +137 -260
  98. package/lib/ReactMultiChild.js +19 -45
  99. package/lib/ReactMultiChildUpdateTypes.js +1 -1
  100. package/lib/ReactNativeComponent.js +7 -11
  101. package/lib/ReactOwner.js +7 -24
  102. package/lib/ReactPerf.js +8 -12
  103. package/lib/ReactPropTransferer.js +4 -4
  104. package/lib/ReactPropTypeLocationNames.js +2 -2
  105. package/lib/ReactPropTypeLocations.js +1 -1
  106. package/lib/ReactPropTypes.js +41 -61
  107. package/lib/ReactReconcileTransaction.js +9 -34
  108. package/lib/ReactReconciler.js +9 -19
  109. package/lib/ReactRef.js +5 -8
  110. package/lib/ReactRootIndex.js +2 -2
  111. package/lib/ReactServerRendering.js +7 -15
  112. package/lib/ReactServerRenderingTransaction.js +7 -32
  113. package/lib/ReactStateSetters.js +6 -6
  114. package/lib/ReactTestUtils.js +93 -165
  115. package/lib/ReactTransitionChildMapping.js +5 -7
  116. package/lib/ReactTransitionEvents.js +5 -5
  117. package/lib/ReactTransitionGroup.js +30 -52
  118. package/lib/ReactUpdateQueue.js +27 -90
  119. package/lib/ReactUpdates.js +27 -79
  120. package/lib/ReactWithAddons.js +7 -6
  121. package/lib/SVGDOMPropertyConfig.js +41 -4
  122. package/lib/SelectEventPlugin.js +28 -29
  123. package/lib/ServerReactRootIndex.js +2 -2
  124. package/lib/SimpleEventPlugin.js +136 -128
  125. package/lib/SyntheticClipboardEvent.js +3 -7
  126. package/lib/SyntheticCompositionEvent.js +3 -9
  127. package/lib/SyntheticDragEvent.js +1 -1
  128. package/lib/SyntheticEvent.js +8 -10
  129. package/lib/SyntheticFocusEvent.js +1 -1
  130. package/lib/SyntheticInputEvent.js +3 -9
  131. package/lib/SyntheticKeyboardEvent.js +4 -4
  132. package/lib/SyntheticMouseEvent.js +8 -14
  133. package/lib/SyntheticTouchEvent.js +1 -1
  134. package/lib/SyntheticUIEvent.js +3 -3
  135. package/lib/SyntheticWheelEvent.js +11 -15
  136. package/lib/Transaction.js +12 -24
  137. package/lib/ViewportMetrics.js +2 -2
  138. package/lib/accumulateInto.js +2 -5
  139. package/lib/adler32.js +2 -4
  140. package/lib/camelize.js +4 -2
  141. package/lib/camelizeStyleName.js +2 -2
  142. package/lib/cloneWithProps.js +5 -11
  143. package/lib/containsNode.js +29 -16
  144. package/lib/createArrayFromMixed.js +17 -16
  145. package/lib/createFullPageComponent.js +4 -11
  146. package/lib/createNodesFromMarkup.js +6 -8
  147. package/lib/dangerousStyleValue.js +2 -3
  148. package/lib/emptyFunction.js +10 -4
  149. package/lib/emptyObject.js +1 -1
  150. package/lib/escapeTextContentForBrowser.js +1 -1
  151. package/lib/findDOMNode.js +5 -24
  152. package/lib/flattenChildren.js +4 -10
  153. package/lib/focusNode.js +2 -3
  154. package/lib/forEachAccumulated.js +2 -2
  155. package/lib/getActiveElement.js +4 -2
  156. package/lib/getEventCharCode.js +1 -1
  157. package/lib/getEventKey.js +1 -1
  158. package/lib/getEventModifierState.js +1 -1
  159. package/lib/getEventTarget.js +1 -1
  160. package/lib/getIteratorFn.js +2 -4
  161. package/lib/getMarkupWrap.js +7 -5
  162. package/lib/getNodeForCharacterOffset.js +1 -1
  163. package/lib/getTextContentAccessor.js +2 -4
  164. package/lib/getUnboundedScrollPosition.js +1 -1
  165. package/lib/hyphenate.js +3 -1
  166. package/lib/hyphenateStyleName.js +2 -2
  167. package/lib/instantiateReactComponent.js +14 -38
  168. package/lib/invariant.js +8 -12
  169. package/lib/isEventSupported.js +7 -10
  170. package/lib/isNode.js +4 -6
  171. package/lib/isTextInputElement.js +2 -4
  172. package/lib/isTextNode.js +3 -1
  173. package/lib/joinClasses.js +2 -2
  174. package/lib/keyMirror.js +3 -6
  175. package/lib/keyOf.js +4 -3
  176. package/lib/mapObject.js +1 -1
  177. package/lib/memoizeStringOnly.js +2 -2
  178. package/lib/onlyChild.js +2 -5
  179. package/lib/performance.js +2 -5
  180. package/lib/performanceNow.js +3 -1
  181. package/lib/quoteAttributeValueForBrowser.js +1 -1
  182. package/lib/renderSubtreeIntoContainer.js +16 -0
  183. package/lib/setInnerHTML.js +11 -8
  184. package/lib/setTextContent.js +3 -3
  185. package/lib/shallowCompare.js +24 -0
  186. package/lib/shallowEqual.js +17 -11
  187. package/lib/shouldUpdateReactComponent.js +3 -64
  188. package/lib/toArray.js +8 -19
  189. package/lib/traverseAllChildren.js +22 -89
  190. package/lib/update.js +25 -85
  191. package/lib/validateDOMNesting.js +363 -0
  192. package/lib/warning.js +17 -15
  193. package/package.json +3 -3
  194. package/lib/MobileSafariClickEventPlugin.js +0 -56
  195. package/lib/ReactPutListenerQueue.js +0 -54
  196. package/lib/cx.js +0 -52
  197. package/lib/getReactRootElementInContainer.js +0 -33
@@ -31,17 +31,17 @@ var ReactDOMForm = ReactClass.createClass({
31
31
 
32
32
  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
33
33
 
34
- render: function() {
34
+ render: function () {
35
35
  // TODO: Instead of using `ReactDOM` directly, we should use JSX. However,
36
36
  // `jshint` fails to parse JSX so in order for linting to work in the open
37
37
  // source repo, we need to just use `ReactDOM.form`.
38
38
  return form(this.props);
39
39
  },
40
40
 
41
- componentDidMount: function() {
41
+ componentDidMount: function () {
42
42
  this.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset');
43
43
  this.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit');
44
44
  }
45
45
  });
46
46
 
47
- module.exports = ReactDOMForm;
47
+ module.exports = ReactDOMForm;
@@ -10,8 +10,6 @@
10
10
  * @typechecks static-only
11
11
  */
12
12
 
13
- /*jslint evil: true */
14
-
15
13
  'use strict';
16
14
 
17
15
  var CSSPropertyOperations = require("./CSSPropertyOperations");
@@ -30,8 +28,7 @@ var setInnerHTML = require("./setInnerHTML");
30
28
  * @private
31
29
  */
32
30
  var INVALID_PROPERTY_ERRORS = {
33
- dangerouslySetInnerHTML:
34
- '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
31
+ dangerouslySetInnerHTML: '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
35
32
  style: '`style` must be set using `updateStylesByID()`.'
36
33
  };
37
34
 
@@ -50,13 +47,9 @@ var ReactDOMIDOperations = {
50
47
  * @param {*} value New value of the property.
51
48
  * @internal
52
49
  */
53
- updatePropertyByID: function(id, name, value) {
50
+ updatePropertyByID: function (id, name, value) {
54
51
  var node = ReactMount.getNode(id);
55
- ("production" !== process.env.NODE_ENV ? invariant(
56
- !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
57
- 'updatePropertyByID(...): %s',
58
- INVALID_PROPERTY_ERRORS[name]
59
- ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
52
+ !!INVALID_PROPERTY_ERRORS.hasOwnProperty(name) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(false) : undefined;
60
53
 
61
54
  // If we're updating to null or undefined, we should remove the property
62
55
  // from the DOM node instead of inadvertantly setting to a string. This
@@ -76,13 +69,9 @@ var ReactDOMIDOperations = {
76
69
  * @param {string} name A property name to remove, see `DOMProperty`.
77
70
  * @internal
78
71
  */
79
- deletePropertyByID: function(id, name, value) {
72
+ deletePropertyByID: function (id, name, value) {
80
73
  var node = ReactMount.getNode(id);
81
- ("production" !== process.env.NODE_ENV ? invariant(
82
- !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
83
- 'updatePropertyByID(...): %s',
84
- INVALID_PROPERTY_ERRORS[name]
85
- ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
74
+ !!INVALID_PROPERTY_ERRORS.hasOwnProperty(name) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(false) : undefined;
86
75
  DOMPropertyOperations.deleteValueForProperty(node, name, value);
87
76
  },
88
77
 
@@ -94,7 +83,7 @@ var ReactDOMIDOperations = {
94
83
  * @param {object} styles Mapping from styles to values.
95
84
  * @internal
96
85
  */
97
- updateStylesByID: function(id, styles) {
86
+ updateStylesByID: function (id, styles) {
98
87
  var node = ReactMount.getNode(id);
99
88
  CSSPropertyOperations.setValueForStyles(node, styles);
100
89
  },
@@ -106,7 +95,7 @@ var ReactDOMIDOperations = {
106
95
  * @param {string} html An HTML string.
107
96
  * @internal
108
97
  */
109
- updateInnerHTMLByID: function(id, html) {
98
+ updateInnerHTMLByID: function (id, html) {
110
99
  var node = ReactMount.getNode(id);
111
100
  setInnerHTML(node, html);
112
101
  },
@@ -118,7 +107,7 @@ var ReactDOMIDOperations = {
118
107
  * @param {string} content Text content.
119
108
  * @internal
120
109
  */
121
- updateTextContentByID: function(id, content) {
110
+ updateTextContentByID: function (id, content) {
122
111
  var node = ReactMount.getNode(id);
123
112
  DOMChildrenOperations.updateTextContent(node, content);
124
113
  },
@@ -131,7 +120,7 @@ var ReactDOMIDOperations = {
131
120
  * @internal
132
121
  * @see {Danger.dangerouslyReplaceNodeWithMarkup}
133
122
  */
134
- dangerouslyReplaceNodeWithMarkupByID: function(id, markup) {
123
+ dangerouslyReplaceNodeWithMarkupByID: function (id, markup) {
135
124
  var node = ReactMount.getNode(id);
136
125
  DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup);
137
126
  },
@@ -143,7 +132,7 @@ var ReactDOMIDOperations = {
143
132
  * @param {array<string>} markup List of markup strings.
144
133
  * @internal
145
134
  */
146
- dangerouslyProcessChildrenUpdates: function(updates, markup) {
135
+ dangerouslyProcessChildrenUpdates: function (updates, markup) {
147
136
  for (var i = 0; i < updates.length; i++) {
148
137
  updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
149
138
  }
@@ -161,4 +150,4 @@ ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
161
150
  dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
162
151
  });
163
152
 
164
- module.exports = ReactDOMIDOperations;
153
+ module.exports = ReactDOMIDOperations;
@@ -31,13 +31,13 @@ var ReactDOMIframe = ReactClass.createClass({
31
31
 
32
32
  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
33
33
 
34
- render: function() {
34
+ render: function () {
35
35
  return iframe(this.props);
36
36
  },
37
37
 
38
- componentDidMount: function() {
38
+ componentDidMount: function () {
39
39
  this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
40
40
  }
41
41
  });
42
42
 
43
- module.exports = ReactDOMIframe;
43
+ module.exports = ReactDOMIframe;
@@ -31,14 +31,14 @@ var ReactDOMImg = ReactClass.createClass({
31
31
 
32
32
  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
33
33
 
34
- render: function() {
34
+ render: function () {
35
35
  return img(this.props);
36
36
  },
37
37
 
38
- componentDidMount: function() {
38
+ componentDidMount: function () {
39
39
  this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
40
40
  this.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error');
41
41
  }
42
42
  });
43
43
 
44
- module.exports = ReactDOMImg;
44
+ module.exports = ReactDOMImg;
@@ -21,6 +21,7 @@ var ReactMount = require("./ReactMount");
21
21
  var ReactUpdates = require("./ReactUpdates");
22
22
 
23
23
  var assign = require("./Object.assign");
24
+ var findDOMNode = require("./findDOMNode");
24
25
  var invariant = require("./invariant");
25
26
 
26
27
  var input = ReactElement.createFactory('input');
@@ -56,7 +57,7 @@ var ReactDOMInput = ReactClass.createClass({
56
57
 
57
58
  mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
58
59
 
59
- getInitialState: function() {
60
+ getInitialState: function () {
60
61
  var defaultValue = this.props.defaultValue;
61
62
  return {
62
63
  initialChecked: this.props.defaultChecked || false,
@@ -64,17 +65,17 @@ var ReactDOMInput = ReactClass.createClass({
64
65
  };
65
66
  },
66
67
 
67
- render: function() {
68
+ render: function () {
68
69
  // Clone `this.props` so we don't mutate the input.
69
70
  var props = assign({}, this.props);
70
71
 
71
72
  props.defaultChecked = null;
72
73
  props.defaultValue = null;
73
74
 
74
- var value = LinkedValueUtils.getValue(this);
75
+ var value = LinkedValueUtils.getValue(this.props);
75
76
  props.value = value != null ? value : this.state.initialValue;
76
77
 
77
- var checked = LinkedValueUtils.getChecked(this);
78
+ var checked = LinkedValueUtils.getChecked(this.props);
78
79
  props.checked = checked != null ? checked : this.state.initialChecked;
79
80
 
80
81
  props.onChange = this._handleChange;
@@ -82,28 +83,24 @@ var ReactDOMInput = ReactClass.createClass({
82
83
  return input(props, this.props.children);
83
84
  },
84
85
 
85
- componentDidMount: function() {
86
- var id = ReactMount.getID(this.getDOMNode());
86
+ componentDidMount: function () {
87
+ var id = ReactMount.getID(findDOMNode(this));
87
88
  instancesByReactID[id] = this;
88
89
  },
89
90
 
90
- componentWillUnmount: function() {
91
- var rootNode = this.getDOMNode();
91
+ componentWillUnmount: function () {
92
+ var rootNode = findDOMNode(this);
92
93
  var id = ReactMount.getID(rootNode);
93
94
  delete instancesByReactID[id];
94
95
  },
95
96
 
96
- componentDidUpdate: function(prevProps, prevState, prevContext) {
97
- var rootNode = this.getDOMNode();
97
+ componentDidUpdate: function (prevProps, prevState, prevContext) {
98
+ var rootNode = findDOMNode(this);
98
99
  if (this.props.checked != null) {
99
- DOMPropertyOperations.setValueForProperty(
100
- rootNode,
101
- 'checked',
102
- this.props.checked || false
103
- );
100
+ DOMPropertyOperations.setValueForProperty(rootNode, 'checked', this.props.checked || false);
104
101
  }
105
102
 
106
- var value = LinkedValueUtils.getValue(this);
103
+ var value = LinkedValueUtils.getValue(this.props);
107
104
  if (value != null) {
108
105
  // Cast `value` to a string to ensure the value is set correctly. While
109
106
  // browsers typically do this as necessary, jsdom doesn't.
@@ -111,9 +108,9 @@ var ReactDOMInput = ReactClass.createClass({
111
108
  }
112
109
  },
113
110
 
114
- _handleChange: function(event) {
111
+ _handleChange: function (event) {
115
112
  var returnValue;
116
- var onChange = LinkedValueUtils.getOnChange(this);
113
+ var onChange = LinkedValueUtils.getOnChange(this.props);
117
114
  if (onChange) {
118
115
  returnValue = onChange.call(this, event);
119
116
  }
@@ -124,7 +121,7 @@ var ReactDOMInput = ReactClass.createClass({
124
121
 
125
122
  var name = this.props.name;
126
123
  if (this.props.type === 'radio' && name != null) {
127
- var rootNode = this.getDOMNode();
124
+ var rootNode = findDOMNode(this);
128
125
  var queryRoot = rootNode;
129
126
 
130
127
  while (queryRoot.parentNode) {
@@ -137,27 +134,17 @@ var ReactDOMInput = ReactClass.createClass({
137
134
  // and won't include inputs that use the HTML5 `form=` attribute. Since
138
135
  // the input might not even be in a form, let's just use the global
139
136
  // `querySelectorAll` to ensure we don't miss anything.
140
- var group = queryRoot.querySelectorAll(
141
- 'input[name=' + JSON.stringify('' + name) + '][type="radio"]');
137
+ var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
142
138
 
143
- for (var i = 0, groupLen = group.length; i < groupLen; i++) {
139
+ for (var i = 0; i < group.length; i++) {
144
140
  var otherNode = group[i];
145
- if (otherNode === rootNode ||
146
- otherNode.form !== rootNode.form) {
141
+ if (otherNode === rootNode || otherNode.form !== rootNode.form) {
147
142
  continue;
148
143
  }
149
144
  var otherID = ReactMount.getID(otherNode);
150
- ("production" !== process.env.NODE_ENV ? invariant(
151
- otherID,
152
- 'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
153
- 'same `name` is not supported.'
154
- ) : invariant(otherID));
145
+ !otherID ? 'production' !== process.env.NODE_ENV ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.') : invariant(false) : undefined;
155
146
  var otherInstance = instancesByReactID[otherID];
156
- ("production" !== process.env.NODE_ENV ? invariant(
157
- otherInstance,
158
- 'ReactDOMInput: Unknown radio button ID %s.',
159
- otherID
160
- ) : invariant(otherInstance));
147
+ !otherInstance ? 'production' !== process.env.NODE_ENV ? invariant(false, 'ReactDOMInput: Unknown radio button ID %s.', otherID) : invariant(false) : undefined;
161
148
  // If this is a controlled radio button group, forcing the input that
162
149
  // was previously checked to update will cause it to be come re-checked
163
150
  // as appropriate.
@@ -170,4 +157,4 @@ var ReactDOMInput = ReactClass.createClass({
170
157
 
171
158
  });
172
159
 
173
- module.exports = ReactDOMInput;
160
+ module.exports = ReactDOMInput;
@@ -12,13 +12,19 @@
12
12
  'use strict';
13
13
 
14
14
  var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
15
+ var ReactChildren = require("./ReactChildren");
15
16
  var ReactClass = require("./ReactClass");
17
+ var ReactDOMSelect = require("./ReactDOMSelect");
16
18
  var ReactElement = require("./ReactElement");
19
+ var ReactPropTypes = require("./ReactPropTypes");
17
20
 
21
+ var assign = require("./Object.assign");
18
22
  var warning = require("./warning");
19
23
 
20
24
  var option = ReactElement.createFactory('option');
21
25
 
26
+ var valueContextKey = ReactDOMSelect.valueContextKey;
27
+
22
28
  /**
23
29
  * Implements an <option> native component that warns when `selected` is set.
24
30
  */
@@ -28,21 +34,72 @@ var ReactDOMOption = ReactClass.createClass({
28
34
 
29
35
  mixins: [ReactBrowserComponentMixin],
30
36
 
31
- componentWillMount: function() {
37
+ getInitialState: function () {
38
+ return { selected: null };
39
+ },
40
+
41
+ contextTypes: (function () {
42
+ var obj = {};
43
+ obj[valueContextKey] = ReactPropTypes.any;
44
+ return obj;
45
+ })(),
46
+
47
+ componentWillMount: function () {
32
48
  // TODO (yungsters): Remove support for `selected` in <option>.
33
- if ("production" !== process.env.NODE_ENV) {
34
- ("production" !== process.env.NODE_ENV ? warning(
35
- this.props.selected == null,
36
- 'Use the `defaultValue` or `value` props on <select> instead of ' +
37
- 'setting `selected` on <option>.'
38
- ) : null);
49
+ if ('production' !== process.env.NODE_ENV) {
50
+ 'production' !== process.env.NODE_ENV ? warning(this.props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : undefined;
51
+ }
52
+
53
+ // Look up whether this option is 'selected' via parent-based context
54
+ var context = this.context;
55
+ var selectValue = context[valueContextKey];
56
+
57
+ // If context key is null (e.g., no specified value or after initial mount)
58
+ // or missing (e.g., for <datalist>) skip props
59
+ if (selectValue != null) {
60
+ var selected = false;
61
+ if (Array.isArray(selectValue)) {
62
+ // multiple
63
+ for (var i = 0; i < selectValue.length; i++) {
64
+ if ('' + selectValue[i] === '' + this.props.value) {
65
+ selected = true;
66
+ break;
67
+ }
68
+ }
69
+ } else {
70
+ selected = '' + selectValue === '' + this.props.value;
71
+ }
72
+ this.setState({ selected: selected });
39
73
  }
40
74
  },
41
75
 
42
- render: function() {
43
- return option(this.props, this.props.children);
76
+ render: function () {
77
+ var props = this.props;
78
+
79
+ // Read state only from initial mount because <select> updates value
80
+ // manually; we need the initial state only for server rendering
81
+ if (this.state.selected != null) {
82
+ props = assign({}, props, { selected: this.state.selected });
83
+ }
84
+
85
+ var content = '';
86
+
87
+ // Flatten children and warn if they aren't strings or numbers;
88
+ // invalid types are ignored.
89
+ ReactChildren.forEach(this.props.children, function (child) {
90
+ if (child == null) {
91
+ return;
92
+ }
93
+ if (typeof child === 'string' || typeof child === 'number') {
94
+ content += child;
95
+ } else {
96
+ 'production' !== process.env.NODE_ENV ? warning(false, 'Only strings and numbers are supported as <option> children.') : undefined;
97
+ }
98
+ });
99
+
100
+ return option(props, content);
44
101
  }
45
102
 
46
103
  });
47
104
 
48
- module.exports = ReactDOMOption;
105
+ module.exports = ReactDOMOption;
@@ -17,16 +17,20 @@ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
17
17
  var ReactClass = require("./ReactClass");
18
18
  var ReactElement = require("./ReactElement");
19
19
  var ReactUpdates = require("./ReactUpdates");
20
+ var ReactPropTypes = require("./ReactPropTypes");
20
21
 
21
22
  var assign = require("./Object.assign");
23
+ var findDOMNode = require("./findDOMNode");
22
24
 
23
25
  var select = ReactElement.createFactory('select');
24
26
 
27
+ var valueContextKey = '__ReactDOMSelect_value$' + Math.random().toString(36).slice(2);
28
+
25
29
  function updateOptionsIfPendingUpdateAndMounted() {
26
30
  /*jshint validthis:true */
27
31
  if (this._pendingUpdate) {
28
32
  this._pendingUpdate = false;
29
- var value = LinkedValueUtils.getValue(this);
33
+ var value = LinkedValueUtils.getValue(this.props);
30
34
  if (value != null && this.isMounted()) {
31
35
  updateOptions(this, value);
32
36
  }
@@ -43,17 +47,11 @@ function selectValueType(props, propName, componentName) {
43
47
  }
44
48
  if (props.multiple) {
45
49
  if (!Array.isArray(props[propName])) {
46
- return new Error(
47
- ("The `" + propName + "` prop supplied to <select> must be an array if ") +
48
- ("`multiple` is true.")
49
- );
50
+ return new Error('The `' + propName + '` prop supplied to <select> must be an array if ' + '`multiple` is true.');
50
51
  }
51
52
  } else {
52
53
  if (Array.isArray(props[propName])) {
53
- return new Error(
54
- ("The `" + propName + "` prop supplied to <select> must be a scalar ") +
55
- ("value if `multiple` is false.")
56
- );
54
+ return new Error('The `' + propName + '` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.');
57
55
  }
58
56
  }
59
57
  }
@@ -64,15 +62,15 @@ function selectValueType(props, propName, componentName) {
64
62
  * @private
65
63
  */
66
64
  function updateOptions(component, propValue) {
67
- var selectedValue, i, l;
68
- var options = component.getDOMNode().options;
65
+ var selectedValue, i;
66
+ var options = findDOMNode(component).options;
69
67
 
70
68
  if (component.props.multiple) {
71
69
  selectedValue = {};
72
- for (i = 0, l = propValue.length; i < l; i++) {
70
+ for (i = 0; i < propValue.length; i++) {
73
71
  selectedValue['' + propValue[i]] = true;
74
72
  }
75
- for (i = 0, l = options.length; i < l; i++) {
73
+ for (i = 0; i < options.length; i++) {
76
74
  var selected = selectedValue.hasOwnProperty(options[i].value);
77
75
  if (options[i].selected !== selected) {
78
76
  options[i].selected = selected;
@@ -82,7 +80,7 @@ function updateOptions(component, propValue) {
82
80
  // Do not set `select.value` as exact behavior isn't consistent across all
83
81
  // browsers for all cases.
84
82
  selectedValue = '' + propValue;
85
- for (i = 0, l = options.length; i < l; i++) {
83
+ for (i = 0; i < options.length; i++) {
86
84
  if (options[i].value === selectedValue) {
87
85
  options[i].selected = true;
88
86
  return;
@@ -115,12 +113,39 @@ var ReactDOMSelect = ReactClass.createClass({
115
113
 
116
114
  mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
117
115
 
116
+ statics: {
117
+ valueContextKey: valueContextKey
118
+ },
119
+
118
120
  propTypes: {
119
121
  defaultValue: selectValueType,
120
122
  value: selectValueType
121
123
  },
122
124
 
123
- render: function() {
125
+ getInitialState: function () {
126
+ // Pass down initial value so initial generated markup has correct
127
+ // `selected` attributes
128
+ var value = LinkedValueUtils.getValue(this.props);
129
+ if (value != null) {
130
+ return { initialValue: value };
131
+ } else {
132
+ return { initialValue: this.props.defaultValue };
133
+ }
134
+ },
135
+
136
+ childContextTypes: (function () {
137
+ var obj = {};
138
+ obj[valueContextKey] = ReactPropTypes.any;
139
+ return obj;
140
+ })(),
141
+
142
+ getChildContext: function () {
143
+ var obj = {};
144
+ obj[valueContextKey] = this.state.initialValue;
145
+ return obj;
146
+ },
147
+
148
+ render: function () {
124
149
  // Clone `this.props` so we don't mutate the input.
125
150
  var props = assign({}, this.props);
126
151
 
@@ -130,21 +155,18 @@ var ReactDOMSelect = ReactClass.createClass({
130
155
  return select(props, this.props.children);
131
156
  },
132
157
 
133
- componentWillMount: function() {
158
+ componentWillMount: function () {
134
159
  this._pendingUpdate = false;
135
160
  },
136
161
 
137
- componentDidMount: function() {
138
- var value = LinkedValueUtils.getValue(this);
139
- if (value != null) {
140
- updateOptions(this, value);
141
- } else if (this.props.defaultValue != null) {
142
- updateOptions(this, this.props.defaultValue);
143
- }
162
+ componentWillReceiveProps: function (nextProps) {
163
+ // After the initial mount, we control selected-ness manually so don't pass
164
+ // the context value down
165
+ this.setState({ initialValue: null });
144
166
  },
145
167
 
146
- componentDidUpdate: function(prevProps) {
147
- var value = LinkedValueUtils.getValue(this);
168
+ componentDidUpdate: function (prevProps) {
169
+ var value = LinkedValueUtils.getValue(this.props);
148
170
  if (value != null) {
149
171
  this._pendingUpdate = false;
150
172
  updateOptions(this, value);
@@ -159,9 +181,9 @@ var ReactDOMSelect = ReactClass.createClass({
159
181
  }
160
182
  },
161
183
 
162
- _handleChange: function(event) {
184
+ _handleChange: function (event) {
163
185
  var returnValue;
164
- var onChange = LinkedValueUtils.getOnChange(this);
186
+ var onChange = LinkedValueUtils.getOnChange(this.props);
165
187
  if (onChange) {
166
188
  returnValue = onChange.call(this, event);
167
189
  }
@@ -173,4 +195,4 @@ var ReactDOMSelect = ReactClass.createClass({
173
195
 
174
196
  });
175
197
 
176
- module.exports = ReactDOMSelect;
198
+ module.exports = ReactDOMSelect;