react 0.8.0 → 0.9.0-rc1

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 (107) hide show
  1. package/README.md +0 -8
  2. package/addons.js +0 -3
  3. package/lib/AutoFocusMixin.js +30 -0
  4. package/lib/CSSCore.js +22 -21
  5. package/lib/CSSProperty.js +31 -0
  6. package/lib/ChangeEventPlugin.js +26 -4
  7. package/lib/ClientReactRootIndex.js +30 -0
  8. package/lib/CompositionEventPlugin.js +57 -9
  9. package/lib/DOMChildrenOperations.js +32 -2
  10. package/lib/DOMProperty.js +2 -0
  11. package/lib/DOMPropertyOperations.js +14 -1
  12. package/lib/Danger.js +8 -7
  13. package/lib/DefaultDOMPropertyConfig.js +12 -2
  14. package/lib/EnterLeaveEventPlugin.js +37 -4
  15. package/lib/EventConstants.js +3 -0
  16. package/lib/EventListener.js +42 -34
  17. package/lib/EventPluginHub.js +113 -12
  18. package/lib/EventPluginRegistry.js +39 -16
  19. package/lib/EventPluginUtils.js +32 -3
  20. package/lib/EventPropagators.js +6 -42
  21. package/lib/ExecutionEnvironment.js +3 -0
  22. package/lib/LinkedValueUtils.js +161 -0
  23. package/lib/PooledClass.js +6 -0
  24. package/lib/React.js +27 -3
  25. package/lib/ReactCSSTransitionGroup.js +65 -0
  26. package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +21 -35
  27. package/lib/ReactComponent.js +87 -52
  28. package/lib/ReactComponentBrowserEnvironment.js +67 -49
  29. package/lib/ReactComponentEnvironment.js +2 -0
  30. package/lib/ReactCompositeComponent.js +547 -112
  31. package/lib/ReactContext.js +67 -0
  32. package/lib/ReactDOM.js +13 -0
  33. package/lib/ReactDOMButton.js +4 -0
  34. package/lib/ReactDOMComponent.js +46 -21
  35. package/lib/ReactDOMForm.js +9 -2
  36. package/lib/ReactDOMIDOperations.js +105 -60
  37. package/lib/ReactDOMImg.js +58 -0
  38. package/lib/ReactDOMInput.js +26 -14
  39. package/lib/ReactDOMOption.js +1 -0
  40. package/lib/ReactDOMSelect.js +36 -17
  41. package/lib/ReactDOMTextarea.js +12 -8
  42. package/lib/ReactDefaultInjection.js +50 -26
  43. package/lib/ReactDefaultPerf.js +207 -370
  44. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  45. package/lib/ReactErrorUtils.js +5 -14
  46. package/lib/ReactEventEmitter.js +141 -145
  47. package/lib/ReactEventEmitterMixin.js +0 -32
  48. package/lib/ReactEventTopLevelCallback.js +32 -12
  49. package/lib/ReactInjection.js +39 -0
  50. package/lib/ReactInstanceHandles.js +35 -19
  51. package/lib/ReactLink.js +1 -1
  52. package/lib/ReactMount.js +127 -103
  53. package/lib/ReactMountReady.js +1 -1
  54. package/lib/ReactMultiChild.js +30 -46
  55. package/lib/ReactMultiChildUpdateTypes.js +2 -0
  56. package/lib/ReactOwner.js +10 -2
  57. package/lib/ReactPerf.js +5 -8
  58. package/lib/ReactPropTransferer.js +40 -21
  59. package/lib/ReactPropTypeLocationNames.js +31 -0
  60. package/lib/ReactPropTypeLocations.js +29 -0
  61. package/lib/ReactPropTypes.js +248 -47
  62. package/lib/ReactPutListenerQueue.js +61 -0
  63. package/lib/ReactReconcileTransaction.js +20 -0
  64. package/lib/ReactRootIndex.js +36 -0
  65. package/lib/ReactServerRendering.js +8 -11
  66. package/lib/ReactTextComponent.js +8 -3
  67. package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +42 -47
  68. package/lib/ReactTransitionGroup.js +132 -57
  69. package/lib/ReactUpdates.js +14 -11
  70. package/lib/ReactWithAddons.js +7 -2
  71. package/lib/SelectEventPlugin.js +22 -39
  72. package/lib/ServerReactRootIndex.js +36 -0
  73. package/lib/SimpleEventPlugin.js +54 -6
  74. package/lib/SyntheticClipboardEvent.js +7 -1
  75. package/lib/SyntheticDragEvent.js +44 -0
  76. package/lib/SyntheticEvent.js +2 -1
  77. package/lib/SyntheticKeyboardEvent.js +4 -2
  78. package/lib/SyntheticWheelEvent.js +10 -7
  79. package/lib/Transaction.js +61 -36
  80. package/lib/cloneWithProps.js +59 -0
  81. package/lib/createArrayFrom.js +10 -13
  82. package/lib/createFullPageComponent.js +63 -0
  83. package/lib/cx.js +2 -2
  84. package/lib/flattenChildren.js +5 -2
  85. package/lib/getActiveElement.js +4 -3
  86. package/lib/getEventKey.js +85 -0
  87. package/lib/getMarkupWrap.js +10 -0
  88. package/lib/getTextContentAccessor.js +5 -3
  89. package/lib/getUnboundedScrollPosition.js +2 -2
  90. package/lib/invariant.js +12 -4
  91. package/lib/isEventSupported.js +7 -11
  92. package/lib/mergeHelpers.js +5 -6
  93. package/lib/onlyChild.js +43 -0
  94. package/lib/shouldUpdateReactComponent.js +58 -0
  95. package/lib/toArray.js +75 -0
  96. package/lib/traverseAllChildren.js +69 -7
  97. package/lib/warning.js +40 -0
  98. package/package.json +2 -3
  99. package/react.js +0 -3
  100. package/ReactJSErrors.js +0 -40
  101. package/lib/$.js +0 -46
  102. package/lib/CallbackRegistry.js +0 -91
  103. package/lib/LinkedValueMixin.js +0 -68
  104. package/lib/ex.js +0 -49
  105. package/lib/filterAttributes.js +0 -45
  106. package/lib/ge.js +0 -76
  107. package/lib/mutateHTMLNodeWithMarkup.js +0 -100
@@ -27,7 +27,6 @@ var SyntheticMouseEvent = require("./SyntheticMouseEvent");
27
27
  */
28
28
  var WheelEventInterface = {
29
29
  deltaX: function(event) {
30
- // NOTE: IE<9 does not support x-axis delta.
31
30
  return (
32
31
  'deltaX' in event ? event.deltaX :
33
32
  // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
@@ -36,15 +35,19 @@ var WheelEventInterface = {
36
35
  },
37
36
  deltaY: function(event) {
38
37
  return (
39
- // Normalize (up is positive).
40
- 'deltaY' in event ? -event.deltaY :
41
- // Fallback to `wheelDeltaY` for Webkit.
42
- 'wheelDeltaY' in event ? event.wheelDeltaY :
43
- // Fallback to `wheelDelta` for IE<9.
44
- 'wheelDelta' in event ? event.wheelDelta : 0
38
+ 'deltaY' in event ? event.deltaY :
39
+ // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
40
+ 'wheelDeltaY' in event ? -event.wheelDeltaY :
41
+ // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
42
+ 'wheelDelta' in event ? -event.wheelDelta : 0
45
43
  );
46
44
  },
47
45
  deltaZ: null,
46
+
47
+ // Browsers without "deltaMode" is reporting in raw wheel delta where one
48
+ // notch on the scroll is always +/- 120, roughly equivalent to pixels.
49
+ // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
50
+ // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
48
51
  deltaMode: null
49
52
  };
50
53
 
@@ -27,7 +27,7 @@ var invariant = require("./invariant");
27
27
  * instantiates a transaction can provide enforcers of the invariants at
28
28
  * creation time. The `Transaction` class itself will supply one additional
29
29
  * automatic invariant for you - the invariant that any transaction instance
30
- * should not be ran while it is already being ran. You would typically create a
30
+ * should not be run while it is already being run. You would typically create a
31
31
  * single instance of a `Transaction` for reuse multiple times, that potentially
32
32
  * is used to wrap several different methods. Wrappers are extremely simple -
33
33
  * they only require implementing two methods.
@@ -67,7 +67,7 @@ var invariant = require("./invariant");
67
67
  * while guaranteeing that afterwards, the event system is reactivated.
68
68
  * - Flushing a queue of collected DOM mutations to the main UI thread after a
69
69
  * reconciliation takes place in a worker thread.
70
- * - Invoking any collected `componentDidRender` callbacks after rendering new
70
+ * - Invoking any collected `componentDidUpdate` callbacks after rendering new
71
71
  * content.
72
72
  * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue
73
73
  * to preserve the `scrollTop` (an automatic scroll aware DOM).
@@ -146,56 +146,72 @@ var Mixin = {
146
146
  'is already an outstanding transaction.'
147
147
  ) : invariant(!this.isInTransaction()));
148
148
  var memberStart = Date.now();
149
- var errorToThrow = null;
149
+ var errorThrown;
150
150
  var ret;
151
151
  try {
152
- this.initializeAll();
152
+ this._isInTransaction = true;
153
+ // Catching errors makes debugging more difficult, so we start with
154
+ // errorThrown set to true before setting it to false after calling
155
+ // close -- if it's still set to true in the finally block, it means
156
+ // one of these calls threw.
157
+ errorThrown = true;
158
+ this.initializeAll(0);
153
159
  ret = method.call(scope, a, b, c, d, e, f);
154
- } catch (error) {
155
- // IE8 requires `catch` in order to use `finally`.
156
- errorToThrow = error;
160
+ errorThrown = false;
157
161
  } finally {
158
162
  var memberEnd = Date.now();
159
163
  this.methodInvocationTime += (memberEnd - memberStart);
160
164
  try {
161
- this.closeAll();
162
- } catch (closeError) {
163
- // If `method` throws, prefer to show that stack trace over any thrown
164
- // by invoking `closeAll`.
165
- errorToThrow = errorToThrow || closeError;
165
+ if (errorThrown) {
166
+ // If `method` throws, prefer to show that stack trace over any thrown
167
+ // by invoking `closeAll`.
168
+ try {
169
+ this.closeAll(0);
170
+ } catch (err) {
171
+ }
172
+ } else {
173
+ // Since `method` didn't throw, we don't want to silence the exception
174
+ // here.
175
+ this.closeAll(0);
176
+ }
177
+ } finally {
178
+ this._isInTransaction = false;
166
179
  }
167
180
  }
168
- if (errorToThrow) {
169
- throw errorToThrow;
170
- }
171
181
  return ret;
172
182
  },
173
183
 
174
- initializeAll: function() {
175
- this._isInTransaction = true;
184
+ initializeAll: function(startIndex) {
176
185
  var transactionWrappers = this.transactionWrappers;
177
186
  var wrapperInitTimes = this.timingMetrics.wrapperInitTimes;
178
- var errorToThrow = null;
179
- for (var i = 0; i < transactionWrappers.length; i++) {
187
+ for (var i = startIndex; i < transactionWrappers.length; i++) {
180
188
  var initStart = Date.now();
181
189
  var wrapper = transactionWrappers[i];
182
190
  try {
191
+ // Catching errors makes debugging more difficult, so we start with the
192
+ // OBSERVED_ERROR state before overwriting it with the real return value
193
+ // of initialize -- if it's still set to OBSERVED_ERROR in the finally
194
+ // block, it means wrapper.initialize threw.
195
+ this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;
183
196
  this.wrapperInitData[i] = wrapper.initialize ?
184
197
  wrapper.initialize.call(this) :
185
198
  null;
186
- } catch (initError) {
187
- // Prefer to show the stack trace of the first error.
188
- errorToThrow = errorToThrow || initError;
189
- this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;
190
199
  } finally {
191
200
  var curInitTime = wrapperInitTimes[i];
192
201
  var initEnd = Date.now();
193
202
  wrapperInitTimes[i] = (curInitTime || 0) + (initEnd - initStart);
203
+
204
+ if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {
205
+ // The initializer for wrapper i threw an error; initialize the
206
+ // remaining wrappers but silence any exceptions from them to ensure
207
+ // that the first error is the one to bubble up.
208
+ try {
209
+ this.initializeAll(i + 1);
210
+ } catch (err) {
211
+ }
212
+ }
194
213
  }
195
214
  }
196
- if (errorToThrow) {
197
- throw errorToThrow;
198
- }
199
215
  },
200
216
 
201
217
  /**
@@ -204,36 +220,45 @@ var Mixin = {
204
220
  * (`close`rs that correspond to initializers that failed will not be
205
221
  * invoked).
206
222
  */
207
- closeAll: function() {
223
+ closeAll: function(startIndex) {
208
224
  ("production" !== process.env.NODE_ENV ? invariant(
209
225
  this.isInTransaction(),
210
226
  'Transaction.closeAll(): Cannot close transaction when none are open.'
211
227
  ) : invariant(this.isInTransaction()));
212
228
  var transactionWrappers = this.transactionWrappers;
213
229
  var wrapperCloseTimes = this.timingMetrics.wrapperCloseTimes;
214
- var errorToThrow = null;
215
- for (var i = 0; i < transactionWrappers.length; i++) {
230
+ for (var i = startIndex; i < transactionWrappers.length; i++) {
216
231
  var wrapper = transactionWrappers[i];
217
232
  var closeStart = Date.now();
218
233
  var initData = this.wrapperInitData[i];
234
+ var errorThrown;
219
235
  try {
236
+ // Catching errors makes debugging more difficult, so we start with
237
+ // errorThrown set to true before setting it to false after calling
238
+ // close -- if it's still set to true in the finally block, it means
239
+ // wrapper.close threw.
240
+ errorThrown = true;
220
241
  if (initData !== Transaction.OBSERVED_ERROR) {
221
242
  wrapper.close && wrapper.close.call(this, initData);
222
243
  }
223
- } catch (closeError) {
224
- // Prefer to show the stack trace of the first error.
225
- errorToThrow = errorToThrow || closeError;
244
+ errorThrown = false;
226
245
  } finally {
227
246
  var closeEnd = Date.now();
228
247
  var curCloseTime = wrapperCloseTimes[i];
229
248
  wrapperCloseTimes[i] = (curCloseTime || 0) + (closeEnd - closeStart);
249
+
250
+ if (errorThrown) {
251
+ // The closer for wrapper i threw an error; close the remaining
252
+ // wrappers but silence any exceptions from them to ensure that the
253
+ // first error is the one to bubble up.
254
+ try {
255
+ this.closeAll(i + 1);
256
+ } catch (e) {
257
+ }
258
+ }
230
259
  }
231
260
  }
232
261
  this.wrapperInitData.length = 0;
233
- this._isInTransaction = false;
234
- if (errorToThrow) {
235
- throw errorToThrow;
236
- }
237
262
  }
238
263
  };
239
264
 
@@ -0,0 +1,59 @@
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
17
+ * @providesModule cloneWithProps
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var ReactPropTransferer = require("./ReactPropTransferer");
23
+
24
+ var keyOf = require("./keyOf");
25
+
26
+ var CHILDREN_PROP = keyOf({children: null});
27
+
28
+ /**
29
+ * Sometimes you want to change the props of a child passed to you. Usually
30
+ * this is to add a CSS class.
31
+ *
32
+ * @param {object} child child component you'd like to clone
33
+ * @param {object} props props you'd like to modify. They will be merged
34
+ * as if you used `transferPropsTo()`.
35
+ * @return {object} a clone of child with props merged in.
36
+ */
37
+ function cloneWithProps(child, props) {
38
+ if ("production" !== process.env.NODE_ENV) {
39
+ if (child.props.ref) {
40
+ console.warn(
41
+ 'You are calling cloneWithProps() on a child with a ref. This is ' +
42
+ 'dangerous because you\'re creating a new child which will not be ' +
43
+ 'added as a ref to its parent.'
44
+ );
45
+ }
46
+ }
47
+
48
+ var newProps = ReactPropTransferer.mergeProps(props, child.props);
49
+
50
+ // Use `child.props.children` if it is provided.
51
+ if (!newProps.hasOwnProperty(CHILDREN_PROP) &&
52
+ child.props.hasOwnProperty(CHILDREN_PROP)) {
53
+ newProps.children = child.props.children;
54
+ }
55
+
56
+ return child.constructor.ConvenienceConstructor(newProps);
57
+ }
58
+
59
+ module.exports = cloneWithProps;
@@ -17,11 +17,9 @@
17
17
  * @typechecks
18
18
  */
19
19
 
20
+ var toArray = require("./toArray");
21
+
20
22
  /**
21
- * NOTE: if you are a previous user of this function, it has been considered
22
- * unsafe because it's inconsistent across browsers for some inputs.
23
- * Instead use `Array.isArray()`.
24
- *
25
23
  * Perform a heuristic test to determine if an object is "array-like".
26
24
  *
27
25
  * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?"
@@ -31,6 +29,8 @@
31
29
  * true if the argument is an actual array, an `arguments' object, or an
32
30
  * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).
33
31
  *
32
+ * It will return false for other array-like objects like Filelist.
33
+ *
34
34
  * @param {*} obj
35
35
  * @return {boolean}
36
36
  */
@@ -72,8 +72,8 @@ function hasArrayNature(obj) {
72
72
  *
73
73
  * This allows you to treat `things' as an array, but accept scalars in the API.
74
74
  *
75
- * This is also good for converting certain pseudo-arrays, like `arguments` or
76
- * HTMLCollections, into arrays.
75
+ * If you need to convert an array-like object, like `arguments`, into an array
76
+ * use toArray instead.
77
77
  *
78
78
  * @param {*} obj
79
79
  * @return {array}
@@ -81,14 +81,11 @@ function hasArrayNature(obj) {
81
81
  function createArrayFrom(obj) {
82
82
  if (!hasArrayNature(obj)) {
83
83
  return [obj];
84
+ } else if (Array.isArray(obj)) {
85
+ return obj.slice();
86
+ } else {
87
+ return toArray(obj);
84
88
  }
85
- if (obj.item) {
86
- // IE does not support Array#slice on HTMLCollections
87
- var l = obj.length, ret = new Array(l);
88
- while (l--) { ret[l] = obj[l]; }
89
- return ret;
90
- }
91
- return Array.prototype.slice.call(obj);
92
89
  }
93
90
 
94
91
  module.exports = createArrayFrom;
@@ -0,0 +1,63 @@
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 createFullPageComponent
17
+ * @typechecks
18
+ */
19
+
20
+ "use strict";
21
+
22
+ // Defeat circular references by requiring this directly.
23
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
24
+
25
+ var invariant = require("./invariant");
26
+
27
+ /**
28
+ * Create a component that will throw an exception when unmounted.
29
+ *
30
+ * Components like <html> <head> and <body> can't be removed or added
31
+ * easily in a cross-browser way, however it's valuable to be able to
32
+ * take advantage of React's reconciliation for styling and <title>
33
+ * management. So we just document it and throw in dangerous cases.
34
+ *
35
+ * @param {function} componentClass convenience constructor to wrap
36
+ * @return {function} convenience constructor of new component
37
+ */
38
+ function createFullPageComponent(componentClass) {
39
+ var FullPageComponent = ReactCompositeComponent.createClass({
40
+ displayName: 'ReactFullPageComponent' + (
41
+ componentClass.componentConstructor.displayName || ''
42
+ ),
43
+
44
+ componentWillUnmount: function() {
45
+ ("production" !== process.env.NODE_ENV ? invariant(
46
+ false,
47
+ '%s tried to unmount. Because of cross-browser quirks it is ' +
48
+ 'impossible to unmount some top-level components (eg <html>, <head>, ' +
49
+ 'and <body>) reliably and efficiently. To fix this, have a single ' +
50
+ 'top-level component that never unmounts render these elements.',
51
+ this.constructor.displayName
52
+ ) : invariant(false));
53
+ },
54
+
55
+ render: function() {
56
+ return this.transferPropsTo(componentClass(null, this.props.children));
57
+ }
58
+ });
59
+
60
+ return FullPageComponent;
61
+ }
62
+
63
+ module.exports = createFullPageComponent;
package/lib/cx.js CHANGED
@@ -33,8 +33,8 @@
33
33
  */
34
34
  function cx(classNames) {
35
35
  if (typeof classNames == 'object') {
36
- return Object.keys(classNames).map(function(className) {
37
- return classNames[className] ? className : '';
36
+ return Object.keys(classNames).filter(function(className) {
37
+ return classNames[className];
38
38
  }).join(' ');
39
39
  } else {
40
40
  return Array.prototype.join.call(arguments, ' ');
@@ -35,11 +35,14 @@ function flattenSingleChildIntoContext(traverseContext, child, name) {
35
35
  'Children keys must be unique.',
36
36
  name
37
37
  ) : invariant(!result.hasOwnProperty(name)));
38
- result[name] = child;
38
+ if (child != null) {
39
+ result[name] = child;
40
+ }
39
41
  }
40
42
 
41
43
  /**
42
- * Flattens children that are typically specified as `props.children`.
44
+ * Flattens children that are typically specified as `props.children`. Any null
45
+ * children will not be included in the resulting object.
43
46
  * @return {!object} flattened children keyed by name.
44
47
  */
45
48
  function flattenChildren(children) {
@@ -20,14 +20,15 @@
20
20
  /**
21
21
  * Same as document.activeElement but wraps in a try-catch block. In IE it is
22
22
  * not safe to call document.activeElement if there is nothing focused.
23
+ *
24
+ * The activeElement will be null only if the document body is not yet defined.
23
25
  */
24
26
  function getActiveElement() /*?DOMElement*/ {
25
27
  try {
26
- return document.activeElement;
28
+ return document.activeElement || document.body;
27
29
  } catch (e) {
28
- return null;
30
+ return document.body;
29
31
  }
30
32
  }
31
33
 
32
34
  module.exports = getActiveElement;
33
-
@@ -0,0 +1,85 @@
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 getEventKey
17
+ * @typechecks static-only
18
+ */
19
+
20
+ "use strict";
21
+
22
+ /**
23
+ * Normalization of deprecated HTML5 "key" values
24
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
25
+ */
26
+ var normalizeKey = {
27
+ 'Esc': 'Escape',
28
+ 'Spacebar': ' ',
29
+ 'Left': 'ArrowLeft',
30
+ 'Up': 'ArrowUp',
31
+ 'Right': 'ArrowRight',
32
+ 'Down': 'ArrowDown',
33
+ 'Del': 'Delete',
34
+ 'Win': 'OS',
35
+ 'Menu': 'ContextMenu',
36
+ 'Apps': 'ContextMenu',
37
+ 'Scroll': 'ScrollLock',
38
+ 'MozPrintableKey': 'Unidentified'
39
+ };
40
+
41
+ /**
42
+ * Translation from legacy "which/keyCode" to HTML5 "key"
43
+ * Only special keys supported, all others depend on keyboard layout or browser
44
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
45
+ */
46
+ var translateToKey = {
47
+ 8: 'Backspace',
48
+ 9: 'Tab',
49
+ 12: 'Clear',
50
+ 13: 'Enter',
51
+ 16: 'Shift',
52
+ 17: 'Control',
53
+ 18: 'Alt',
54
+ 19: 'Pause',
55
+ 20: 'CapsLock',
56
+ 27: 'Escape',
57
+ 32: ' ',
58
+ 33: 'PageUp',
59
+ 34: 'PageDown',
60
+ 35: 'End',
61
+ 36: 'Home',
62
+ 37: 'ArrowLeft',
63
+ 38: 'ArrowUp',
64
+ 39: 'ArrowRight',
65
+ 40: 'ArrowDown',
66
+ 45: 'Insert',
67
+ 46: 'Delete',
68
+ 112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',
69
+ 118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12',
70
+ 144: 'NumLock',
71
+ 145: 'ScrollLock',
72
+ 224: 'Meta'
73
+ };
74
+
75
+ /**
76
+ * @param {object} nativeEvent Native browser event.
77
+ * @return {string} Normalized `key` property.
78
+ */
79
+ function getEventKey(nativeEvent) {
80
+ return 'key' in nativeEvent ?
81
+ normalizeKey[nativeEvent.key] || nativeEvent.key :
82
+ translateToKey[nativeEvent.which || nativeEvent.keyCode] || 'Unidentified';
83
+ }
84
+
85
+ module.exports = getEventKey;