react 0.14.0-alpha2 → 0.14.0-beta3
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 +5 -2
- package/addons.js +6 -3
- package/dist/JSXTransformer.js +634 -274
- package/dist/react-with-addons.js +5350 -4954
- package/dist/react-with-addons.min.js +6 -6
- package/dist/react.js +4777 -4408
- package/dist/react.min.js +6 -5
- package/lib/{AutoFocusMixin.js → AutoFocusUtils.js} +15 -5
- package/lib/BeforeInputEventPlugin.js +13 -13
- package/lib/CSSProperty.js +3 -0
- package/lib/CSSPropertyOperations.js +13 -13
- package/lib/CallbackQueue.js +4 -4
- package/lib/ChangeEventPlugin.js +16 -14
- package/lib/DOMChildrenOperations.js +10 -6
- package/lib/DOMProperty.js +82 -117
- package/lib/DOMPropertyOperations.js +78 -33
- package/lib/Danger.js +14 -14
- package/lib/DefaultEventPluginOrder.js +2 -2
- package/lib/EnterLeaveEventPlugin.js +8 -8
- package/lib/EventConstants.js +23 -1
- package/lib/EventPluginHub.js +13 -13
- package/lib/EventPluginRegistry.js +8 -8
- package/lib/EventPluginUtils.js +17 -17
- package/lib/EventPropagators.js +7 -7
- package/lib/FallbackCompositionState.js +3 -3
- package/lib/HTMLDOMPropertyConfig.js +13 -3
- package/lib/LinkedStateMixin.js +2 -2
- package/lib/LinkedValueUtils.js +50 -38
- package/lib/MetaMatchers.js +118 -0
- package/lib/OrderedMap.js +453 -0
- package/lib/PooledClass.js +14 -2
- package/lib/React.js +6 -6
- package/lib/ReactBrowserComponentMixin.js +4 -4
- package/lib/ReactBrowserEventEmitter.js +30 -7
- package/lib/ReactCSSTransitionGroup.js +16 -5
- package/lib/ReactCSSTransitionGroupChild.js +20 -11
- package/lib/ReactChildReconciler.js +25 -18
- package/lib/ReactChildren.js +9 -9
- package/lib/ReactClass.js +65 -83
- package/lib/ReactComponent.js +22 -17
- package/lib/ReactComponentBrowserEnvironment.js +2 -2
- package/lib/ReactComponentEnvironment.js +2 -2
- package/lib/ReactComponentWithPureRenderMixin.js +3 -3
- package/lib/ReactCompositeComponent.js +80 -111
- package/lib/ReactDOM.js +72 -158
- package/lib/ReactDOMButton.js +15 -26
- package/lib/ReactDOMComponent.js +378 -56
- package/lib/ReactDOMFactories.js +177 -0
- package/lib/ReactDOMIDOperations.js +23 -23
- package/lib/ReactDOMInput.js +83 -99
- package/lib/ReactDOMOption.js +25 -45
- package/lib/ReactDOMSelect.js +88 -98
- package/lib/ReactDOMSelection.js +3 -3
- package/lib/ReactDOMServer.js +2 -2
- package/lib/ReactDOMTextComponent.js +11 -11
- package/lib/ReactDOMTextarea.js +48 -61
- package/lib/ReactDefaultBatchingStrategy.js +4 -4
- package/lib/ReactDefaultInjection.js +24 -71
- package/lib/ReactDefaultPerf.js +7 -7
- package/lib/ReactDefaultPerfAnalysis.js +6 -9
- package/lib/ReactElement.js +22 -83
- package/lib/ReactElementValidator.js +48 -117
- package/lib/ReactEmptyComponent.js +4 -4
- package/lib/ReactErrorUtils.js +1 -1
- package/lib/ReactEventEmitterMixin.js +3 -4
- package/lib/ReactEventListener.js +57 -12
- package/lib/ReactFragment.js +22 -17
- package/lib/ReactInjection.js +11 -11
- package/lib/ReactInputSelection.js +8 -7
- package/lib/ReactInstanceHandles.js +12 -12
- package/lib/ReactIsomorphic.js +11 -11
- package/lib/ReactLink.js +1 -1
- package/lib/ReactMarkupChecksum.js +6 -2
- package/lib/ReactMount.js +88 -88
- package/lib/ReactMultiChild.js +83 -22
- package/lib/ReactMultiChildUpdateTypes.js +2 -1
- package/lib/ReactNativeComponent.js +3 -8
- package/lib/ReactNoopUpdateQueue.js +118 -0
- package/lib/ReactOwner.js +3 -3
- package/lib/ReactPerf.js +2 -2
- package/lib/ReactPropTransferer.js +3 -3
- package/lib/ReactPropTypeLocationNames.js +1 -1
- package/lib/ReactPropTypeLocations.js +1 -1
- package/lib/ReactPropTypes.js +49 -11
- package/lib/ReactReconcileTransaction.js +8 -8
- package/lib/ReactReconciler.js +18 -20
- package/lib/ReactRef.js +1 -1
- package/lib/ReactServerBatchingStrategy.js +23 -0
- package/lib/ReactServerRendering.js +22 -9
- package/lib/ReactServerRenderingTransaction.js +7 -7
- package/lib/ReactTestUtils.js +80 -58
- package/lib/ReactTransitionChildMapping.js +2 -2
- package/lib/ReactTransitionEvents.js +1 -1
- package/lib/ReactTransitionGroup.js +5 -6
- package/lib/ReactUpdateQueue.js +61 -36
- package/lib/ReactUpdates.js +14 -17
- package/lib/ReactWithAddons.js +14 -16
- package/lib/ResponderEventPlugin.js +514 -0
- package/lib/ResponderSyntheticEvent.js +40 -0
- package/lib/ResponderTouchHistoryStore.js +180 -0
- package/lib/SVGDOMPropertyConfig.js +1 -1
- package/lib/SelectEventPlugin.js +14 -15
- package/lib/SimpleEventPlugin.js +205 -29
- package/lib/SyntheticClipboardEvent.js +3 -3
- package/lib/SyntheticCompositionEvent.js +3 -3
- package/lib/SyntheticDragEvent.js +3 -3
- package/lib/SyntheticEvent.js +9 -8
- package/lib/SyntheticFocusEvent.js +3 -3
- package/lib/SyntheticInputEvent.js +3 -3
- package/lib/SyntheticKeyboardEvent.js +6 -6
- package/lib/SyntheticMouseEvent.js +5 -5
- package/lib/SyntheticTouchEvent.js +4 -4
- package/lib/SyntheticUIEvent.js +4 -4
- package/lib/SyntheticWheelEvent.js +3 -3
- package/lib/TapEventPlugin.js +119 -0
- package/lib/Transaction.js +16 -10
- package/lib/accumulate.js +44 -0
- package/lib/accumulateInto.js +2 -2
- package/lib/adler32.js +19 -7
- package/lib/cloneWithProps.js +12 -7
- package/lib/createHierarchyRenderer.js +85 -0
- package/lib/dangerousStyleValue.js +1 -1
- package/lib/deprecated.js +47 -0
- package/lib/findDOMNode.js +11 -12
- package/lib/flattenChildren.js +4 -4
- package/lib/forEachAccumulated.js +1 -1
- package/lib/getEventCharCode.js +1 -1
- package/lib/getEventKey.js +1 -1
- package/lib/getEventModifierState.js +0 -1
- package/lib/getTestDocument.js +28 -0
- package/lib/getTextContentAccessor.js +1 -1
- package/lib/instantiateReactComponent.js +24 -20
- package/lib/isEventSupported.js +1 -1
- package/lib/isTextInputElement.js +2 -1
- package/lib/joinClasses.js +1 -1
- package/lib/onlyChild.js +3 -3
- package/lib/quoteAttributeValueForBrowser.js +1 -1
- package/lib/reactComponentExpect.js +210 -0
- package/lib/renderSubtreeIntoContainer.js +1 -1
- package/lib/setInnerHTML.js +2 -2
- package/lib/setTextContent.js +3 -3
- package/lib/shallowCompare.js +1 -1
- package/lib/sliceChildren.js +51 -0
- package/lib/traverseAllChildren.js +15 -14
- package/lib/update.js +13 -13
- package/lib/validateDOMNesting.js +14 -6
- package/lib/webcomponents.js +6379 -0
- package/package.json +4 -6
- package/react.js +53 -1
- package/addons/CSSTransitionGroup.js +0 -1
- package/addons/LinkedStateMixin.js +0 -1
- package/addons/Perf.js +0 -1
- package/addons/PureRenderMixin.js +0 -1
- package/addons/TestUtils.js +0 -1
- package/addons/TransitionGroup.js +0 -1
- package/addons/batchedUpdates.js +0 -1
- package/addons/cloneWithProps.js +0 -1
- package/addons/createFragment.js +0 -1
- package/addons/renderSubtreeIntoContainer.js +0 -1
- package/addons/shallowCompare.js +0 -1
- package/addons/update.js +0 -1
- package/lib/CSSCore.js +0 -97
- package/lib/EventListener.js +0 -84
- package/lib/ExecutionEnvironment.js +0 -38
- package/lib/LocalEventTrapMixin.js +0 -46
- package/lib/ReactContext.js +0 -32
- package/lib/ReactDOMClient.js +0 -85
- package/lib/ReactDOMForm.js +0 -47
- package/lib/ReactDOMIframe.js +0 -43
- package/lib/ReactDOMImg.js +0 -44
- package/lib/ReactLifeCycle.js +0 -35
- package/lib/camelize.js +0 -32
- package/lib/camelizeStyleName.js +0 -40
- package/lib/containsNode.js +0 -55
- package/lib/createArrayFromMixed.js +0 -85
- package/lib/createFullPageComponent.js +0 -51
- package/lib/createNodesFromMarkup.js +0 -84
- package/lib/emptyFunction.js +0 -38
- package/lib/emptyObject.js +0 -20
- package/lib/focusNode.js +0 -26
- package/lib/getActiveElement.js +0 -29
- package/lib/getMarkupWrap.js +0 -115
- package/lib/getUnboundedScrollPosition.js +0 -38
- package/lib/hyphenate.js +0 -33
- package/lib/hyphenateStyleName.js +0 -39
- package/lib/invariant.js +0 -49
- package/lib/isNode.js +0 -23
- package/lib/isTextNode.js +0 -25
- package/lib/keyMirror.js +0 -48
- package/lib/keyOf.js +0 -35
- package/lib/mapObject.js +0 -51
- package/lib/performance.js +0 -23
- package/lib/performanceNow.js +0 -28
- package/lib/shallowEqual.js +0 -48
- package/lib/toArray.js +0 -57
- package/lib/warning.js +0 -61
package/lib/ReactUpdateQueue.js
CHANGED
|
@@ -11,44 +11,35 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var ReactUpdates = require("./ReactUpdates");
|
|
14
|
+
var ReactCurrentOwner = require('./ReactCurrentOwner');
|
|
15
|
+
var ReactElement = require('./ReactElement');
|
|
16
|
+
var ReactInstanceMap = require('./ReactInstanceMap');
|
|
17
|
+
var ReactUpdates = require('./ReactUpdates');
|
|
19
18
|
|
|
20
|
-
var assign = require(
|
|
21
|
-
var invariant = require(
|
|
22
|
-
var warning = require(
|
|
19
|
+
var assign = require('./Object.assign');
|
|
20
|
+
var invariant = require('fbjs/lib/invariant');
|
|
21
|
+
var warning = require('fbjs/lib/warning');
|
|
23
22
|
|
|
24
23
|
function enqueueUpdate(internalInstance) {
|
|
25
|
-
|
|
26
|
-
// If we're in a componentWillMount handler, don't enqueue a rerender
|
|
27
|
-
// because ReactUpdates assumes we're in a browser context (which is
|
|
28
|
-
// wrong for server rendering) and we're about to do a render anyway.
|
|
29
|
-
// See bug in #1740.
|
|
30
|
-
ReactUpdates.enqueueUpdate(internalInstance);
|
|
31
|
-
}
|
|
24
|
+
ReactUpdates.enqueueUpdate(internalInstance);
|
|
32
25
|
}
|
|
33
26
|
|
|
34
27
|
function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
|
|
35
|
-
|
|
28
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
29
|
+
process.env.NODE_ENV !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition ' + '(such as within `render`). Render methods should be a pure function ' + 'of props and state.', callerName) : undefined;
|
|
30
|
+
}
|
|
36
31
|
|
|
37
32
|
var internalInstance = ReactInstanceMap.get(publicInstance);
|
|
38
33
|
if (!internalInstance) {
|
|
39
|
-
if (
|
|
34
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
40
35
|
// Only warn when we have a callerName. Otherwise we should be silent.
|
|
41
36
|
// We're probably calling from enqueueCallback. We don't want to warn
|
|
42
37
|
// there because we already warned for the corresponding lifecycle method.
|
|
43
|
-
|
|
38
|
+
process.env.NODE_ENV !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : undefined;
|
|
44
39
|
}
|
|
45
40
|
return null;
|
|
46
41
|
}
|
|
47
42
|
|
|
48
|
-
if (internalInstance === ReactLifeCycle.currentlyUnmountingInstance) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
43
|
return internalInstance;
|
|
53
44
|
}
|
|
54
45
|
|
|
@@ -58,6 +49,32 @@ function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
|
|
|
58
49
|
*/
|
|
59
50
|
var ReactUpdateQueue = {
|
|
60
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Checks whether or not this composite component is mounted.
|
|
54
|
+
* @param {ReactClass} publicInstance The instance we want to test.
|
|
55
|
+
* @return {boolean} True if mounted, false otherwise.
|
|
56
|
+
* @protected
|
|
57
|
+
* @final
|
|
58
|
+
*/
|
|
59
|
+
isMounted: function (publicInstance) {
|
|
60
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
61
|
+
var owner = ReactCurrentOwner.current;
|
|
62
|
+
if (owner !== null) {
|
|
63
|
+
process.env.NODE_ENV !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : undefined;
|
|
64
|
+
owner._warnedAboutRefsInRender = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
var internalInstance = ReactInstanceMap.get(publicInstance);
|
|
68
|
+
if (internalInstance) {
|
|
69
|
+
// During componentWillMount and render this will still be null but after
|
|
70
|
+
// that will always render to something. At least for now. So we can use
|
|
71
|
+
// this hack.
|
|
72
|
+
return !!internalInstance._renderedComponent;
|
|
73
|
+
} else {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
61
78
|
/**
|
|
62
79
|
* Enqueue a callback that will be executed after all the pending updates
|
|
63
80
|
* have processed.
|
|
@@ -67,7 +84,7 @@ var ReactUpdateQueue = {
|
|
|
67
84
|
* @internal
|
|
68
85
|
*/
|
|
69
86
|
enqueueCallback: function (publicInstance, callback) {
|
|
70
|
-
'
|
|
87
|
+
!(typeof callback === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' + '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + 'isn\'t callable.') : invariant(false) : undefined;
|
|
71
88
|
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
|
|
72
89
|
|
|
73
90
|
// Previously we would throw an error if we didn't have an internal
|
|
@@ -75,7 +92,7 @@ var ReactUpdateQueue = {
|
|
|
75
92
|
// behavior we have in other enqueue* methods.
|
|
76
93
|
// We also need to ignore callbacks in componentWillMount. See
|
|
77
94
|
// enqueueUpdates.
|
|
78
|
-
if (!internalInstance
|
|
95
|
+
if (!internalInstance) {
|
|
79
96
|
return null;
|
|
80
97
|
}
|
|
81
98
|
|
|
@@ -92,7 +109,7 @@ var ReactUpdateQueue = {
|
|
|
92
109
|
},
|
|
93
110
|
|
|
94
111
|
enqueueCallbackInternal: function (internalInstance, callback) {
|
|
95
|
-
'
|
|
112
|
+
!(typeof callback === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' + '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + 'isn\'t callable.') : invariant(false) : undefined;
|
|
96
113
|
if (internalInstance._pendingCallbacks) {
|
|
97
114
|
internalInstance._pendingCallbacks.push(callback);
|
|
98
115
|
} else {
|
|
@@ -108,7 +125,7 @@ var ReactUpdateQueue = {
|
|
|
108
125
|
* You may want to call this when you know that some deeper aspect of the
|
|
109
126
|
* component's state has changed but `setState` was not called.
|
|
110
127
|
*
|
|
111
|
-
* This will not invoke `
|
|
128
|
+
* This will not invoke `shouldComponentUpdate`, but it will invoke
|
|
112
129
|
* `componentWillUpdate` and `componentDidUpdate`.
|
|
113
130
|
*
|
|
114
131
|
* @param {ReactClass} publicInstance The instance that should rerender.
|
|
@@ -182,20 +199,24 @@ var ReactUpdateQueue = {
|
|
|
182
199
|
*/
|
|
183
200
|
enqueueSetProps: function (publicInstance, partialProps) {
|
|
184
201
|
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setProps');
|
|
185
|
-
|
|
186
202
|
if (!internalInstance) {
|
|
187
203
|
return;
|
|
188
204
|
}
|
|
205
|
+
ReactUpdateQueue.enqueueSetPropsInternal(internalInstance, partialProps);
|
|
206
|
+
},
|
|
189
207
|
|
|
190
|
-
|
|
208
|
+
enqueueSetPropsInternal: function (internalInstance, partialProps) {
|
|
209
|
+
var topLevelWrapper = internalInstance._topLevelWrapper;
|
|
210
|
+
!topLevelWrapper ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setProps(...): You called `setProps` on a ' + 'component with a parent. This is an anti-pattern since props will ' + 'get reactively updated when rendered. Instead, change the owner\'s ' + '`render` method to pass the correct value as props to the component ' + 'where it is created.') : invariant(false) : undefined;
|
|
191
211
|
|
|
192
212
|
// Merge with the pending element if it exists, otherwise with existing
|
|
193
213
|
// element props.
|
|
194
|
-
var
|
|
214
|
+
var wrapElement = topLevelWrapper._pendingElement || topLevelWrapper._currentElement;
|
|
215
|
+
var element = wrapElement.props;
|
|
195
216
|
var props = assign({}, element.props, partialProps);
|
|
196
|
-
|
|
217
|
+
topLevelWrapper._pendingElement = ReactElement.cloneAndReplaceProps(wrapElement, ReactElement.cloneAndReplaceProps(element, props));
|
|
197
218
|
|
|
198
|
-
enqueueUpdate(
|
|
219
|
+
enqueueUpdate(topLevelWrapper);
|
|
199
220
|
},
|
|
200
221
|
|
|
201
222
|
/**
|
|
@@ -207,19 +228,23 @@ var ReactUpdateQueue = {
|
|
|
207
228
|
*/
|
|
208
229
|
enqueueReplaceProps: function (publicInstance, props) {
|
|
209
230
|
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceProps');
|
|
210
|
-
|
|
211
231
|
if (!internalInstance) {
|
|
212
232
|
return;
|
|
213
233
|
}
|
|
234
|
+
ReactUpdateQueue.enqueueReplacePropsInternal(internalInstance, props);
|
|
235
|
+
},
|
|
214
236
|
|
|
215
|
-
|
|
237
|
+
enqueueReplacePropsInternal: function (internalInstance, props) {
|
|
238
|
+
var topLevelWrapper = internalInstance._topLevelWrapper;
|
|
239
|
+
!topLevelWrapper ? process.env.NODE_ENV !== 'production' ? invariant(false, 'replaceProps(...): You called `replaceProps` on a ' + 'component with a parent. This is an anti-pattern since props will ' + 'get reactively updated when rendered. Instead, change the owner\'s ' + '`render` method to pass the correct value as props to the component ' + 'where it is created.') : invariant(false) : undefined;
|
|
216
240
|
|
|
217
241
|
// Merge with the pending element if it exists, otherwise with existing
|
|
218
242
|
// element props.
|
|
219
|
-
var
|
|
220
|
-
|
|
243
|
+
var wrapElement = topLevelWrapper._pendingElement || topLevelWrapper._currentElement;
|
|
244
|
+
var element = wrapElement.props;
|
|
245
|
+
topLevelWrapper._pendingElement = ReactElement.cloneAndReplaceProps(wrapElement, ReactElement.cloneAndReplaceProps(element, props));
|
|
221
246
|
|
|
222
|
-
enqueueUpdate(
|
|
247
|
+
enqueueUpdate(topLevelWrapper);
|
|
223
248
|
},
|
|
224
249
|
|
|
225
250
|
enqueueElementInternal: function (internalInstance, newElement) {
|
package/lib/ReactUpdates.js
CHANGED
|
@@ -11,16 +11,14 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var CallbackQueue = require(
|
|
15
|
-
var PooledClass = require(
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var
|
|
19
|
-
var Transaction = require("./Transaction");
|
|
14
|
+
var CallbackQueue = require('./CallbackQueue');
|
|
15
|
+
var PooledClass = require('./PooledClass');
|
|
16
|
+
var ReactPerf = require('./ReactPerf');
|
|
17
|
+
var ReactReconciler = require('./ReactReconciler');
|
|
18
|
+
var Transaction = require('./Transaction');
|
|
20
19
|
|
|
21
|
-
var assign = require(
|
|
22
|
-
var invariant = require(
|
|
23
|
-
var warning = require("./warning");
|
|
20
|
+
var assign = require('./Object.assign');
|
|
21
|
+
var invariant = require('fbjs/lib/invariant');
|
|
24
22
|
|
|
25
23
|
var dirtyComponents = [];
|
|
26
24
|
var asapCallbackQueue = CallbackQueue.getPooled();
|
|
@@ -29,7 +27,7 @@ var asapEnqueued = false;
|
|
|
29
27
|
var batchingStrategy = null;
|
|
30
28
|
|
|
31
29
|
function ensureInjected() {
|
|
32
|
-
|
|
30
|
+
!(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching ' + 'strategy') : invariant(false) : undefined;
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
var NESTED_UPDATES = {
|
|
@@ -109,7 +107,7 @@ function mountOrderComparator(c1, c2) {
|
|
|
109
107
|
|
|
110
108
|
function runBatchedUpdates(transaction) {
|
|
111
109
|
var len = transaction.dirtyComponentsLength;
|
|
112
|
-
|
|
110
|
+
!(len === dirtyComponents.length) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected flush transaction\'s stored dirty-components length (%s) to ' + 'match dirty-components array length (%s).', len, dirtyComponents.length) : invariant(false) : undefined;
|
|
113
111
|
|
|
114
112
|
// Since reconciling a component higher in the owner hierarchy usually (not
|
|
115
113
|
// always -- see shouldComponentUpdate()) will reconcile children, reconcile
|
|
@@ -173,7 +171,6 @@ function enqueueUpdate(component) {
|
|
|
173
171
|
// verify that that's the case. (This is called by each top-level update
|
|
174
172
|
// function, like setProps, setState, forceUpdate, etc.; creation and
|
|
175
173
|
// destruction of top-level components is guarded in ReactMount.)
|
|
176
|
-
'production' !== process.env.NODE_ENV ? warning(ReactCurrentOwner.current == null, 'enqueueUpdate(): Render methods should be a pure function of props ' + 'and state; triggering nested component updates from render is not ' + 'allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate.') : null;
|
|
177
174
|
|
|
178
175
|
if (!batchingStrategy.isBatchingUpdates) {
|
|
179
176
|
batchingStrategy.batchedUpdates(enqueueUpdate, component);
|
|
@@ -188,21 +185,21 @@ function enqueueUpdate(component) {
|
|
|
188
185
|
* if no updates are currently being performed.
|
|
189
186
|
*/
|
|
190
187
|
function asap(callback, context) {
|
|
191
|
-
|
|
188
|
+
!batchingStrategy.isBatchingUpdates ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\'t enqueue an asap callback in a context where' + 'updates are not being batched.') : invariant(false) : undefined;
|
|
192
189
|
asapCallbackQueue.enqueue(callback, context);
|
|
193
190
|
asapEnqueued = true;
|
|
194
191
|
}
|
|
195
192
|
|
|
196
193
|
var ReactUpdatesInjection = {
|
|
197
194
|
injectReconcileTransaction: function (ReconcileTransaction) {
|
|
198
|
-
|
|
195
|
+
!ReconcileTransaction ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : invariant(false) : undefined;
|
|
199
196
|
ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
|
|
200
197
|
},
|
|
201
198
|
|
|
202
199
|
injectBatchingStrategy: function (_batchingStrategy) {
|
|
203
|
-
|
|
204
|
-
'
|
|
205
|
-
'
|
|
200
|
+
!_batchingStrategy ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : invariant(false) : undefined;
|
|
201
|
+
!(typeof _batchingStrategy.batchedUpdates === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : invariant(false) : undefined;
|
|
202
|
+
!(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : invariant(false) : undefined;
|
|
206
203
|
batchingStrategy = _batchingStrategy;
|
|
207
204
|
}
|
|
208
205
|
};
|
package/lib/ReactWithAddons.js
CHANGED
|
@@ -18,18 +18,17 @@
|
|
|
18
18
|
|
|
19
19
|
'use strict';
|
|
20
20
|
|
|
21
|
-
var LinkedStateMixin = require(
|
|
22
|
-
var React = require(
|
|
23
|
-
var ReactComponentWithPureRenderMixin = require(
|
|
24
|
-
var ReactCSSTransitionGroup = require(
|
|
25
|
-
var ReactFragment = require(
|
|
26
|
-
var ReactTransitionGroup = require(
|
|
27
|
-
var ReactUpdates = require(
|
|
28
|
-
|
|
29
|
-
var cloneWithProps = require(
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var update = require("./update");
|
|
21
|
+
var LinkedStateMixin = require('./LinkedStateMixin');
|
|
22
|
+
var React = require('./React');
|
|
23
|
+
var ReactComponentWithPureRenderMixin = require('./ReactComponentWithPureRenderMixin');
|
|
24
|
+
var ReactCSSTransitionGroup = require('./ReactCSSTransitionGroup');
|
|
25
|
+
var ReactFragment = require('./ReactFragment');
|
|
26
|
+
var ReactTransitionGroup = require('./ReactTransitionGroup');
|
|
27
|
+
var ReactUpdates = require('./ReactUpdates');
|
|
28
|
+
|
|
29
|
+
var cloneWithProps = require('./cloneWithProps');
|
|
30
|
+
var shallowCompare = require('./shallowCompare');
|
|
31
|
+
var update = require('./update');
|
|
33
32
|
|
|
34
33
|
React.addons = {
|
|
35
34
|
CSSTransitionGroup: ReactCSSTransitionGroup,
|
|
@@ -40,14 +39,13 @@ React.addons = {
|
|
|
40
39
|
batchedUpdates: ReactUpdates.batchedUpdates,
|
|
41
40
|
cloneWithProps: cloneWithProps,
|
|
42
41
|
createFragment: ReactFragment.create,
|
|
43
|
-
renderSubtreeIntoContainer: renderSubtreeIntoContainer,
|
|
44
42
|
shallowCompare: shallowCompare,
|
|
45
43
|
update: update
|
|
46
44
|
};
|
|
47
45
|
|
|
48
|
-
if (
|
|
49
|
-
React.addons.Perf = require(
|
|
50
|
-
React.addons.TestUtils = require(
|
|
46
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
47
|
+
React.addons.Perf = require('./ReactDefaultPerf');
|
|
48
|
+
React.addons.TestUtils = require('./ReactTestUtils');
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
module.exports = React;
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2015, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*
|
|
9
|
+
* @providesModule ResponderEventPlugin
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
var EventConstants = require('./EventConstants');
|
|
15
|
+
var EventPluginUtils = require('./EventPluginUtils');
|
|
16
|
+
var EventPropagators = require('./EventPropagators');
|
|
17
|
+
var ReactInstanceHandles = require('./ReactInstanceHandles');
|
|
18
|
+
var ResponderSyntheticEvent = require('./ResponderSyntheticEvent');
|
|
19
|
+
var ResponderTouchHistoryStore = require('./ResponderTouchHistoryStore');
|
|
20
|
+
|
|
21
|
+
var accumulate = require('./accumulate');
|
|
22
|
+
var invariant = require('fbjs/lib/invariant');
|
|
23
|
+
var keyOf = require('fbjs/lib/keyOf');
|
|
24
|
+
|
|
25
|
+
var isStartish = EventPluginUtils.isStartish;
|
|
26
|
+
var isMoveish = EventPluginUtils.isMoveish;
|
|
27
|
+
var isEndish = EventPluginUtils.isEndish;
|
|
28
|
+
var executeDirectDispatch = EventPluginUtils.executeDirectDispatch;
|
|
29
|
+
var hasDispatches = EventPluginUtils.hasDispatches;
|
|
30
|
+
var executeDispatchesInOrderStopAtTrue = EventPluginUtils.executeDispatchesInOrderStopAtTrue;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* ID of element that should respond to touch/move types of interactions, as
|
|
34
|
+
* indicated explicitly by relevant callbacks.
|
|
35
|
+
*/
|
|
36
|
+
var responderID = null;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Count of current touches. A textInput should become responder iff the
|
|
40
|
+
* the selection changes while there is a touch on the screen.
|
|
41
|
+
*/
|
|
42
|
+
var trackedTouchCount = 0;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Last reported number of active touches.
|
|
46
|
+
*/
|
|
47
|
+
var previousActiveTouches = 0;
|
|
48
|
+
|
|
49
|
+
var changeResponder = function (nextResponderID) {
|
|
50
|
+
var oldResponderID = responderID;
|
|
51
|
+
responderID = nextResponderID;
|
|
52
|
+
if (ResponderEventPlugin.GlobalResponderHandler !== null) {
|
|
53
|
+
ResponderEventPlugin.GlobalResponderHandler.onChange(oldResponderID, nextResponderID);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
var eventTypes = {
|
|
58
|
+
/**
|
|
59
|
+
* On a `touchStart`/`mouseDown`, is it desired that this element become the
|
|
60
|
+
* responder?
|
|
61
|
+
*/
|
|
62
|
+
startShouldSetResponder: {
|
|
63
|
+
phasedRegistrationNames: {
|
|
64
|
+
bubbled: keyOf({ onStartShouldSetResponder: null }),
|
|
65
|
+
captured: keyOf({ onStartShouldSetResponderCapture: null })
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* On a `scroll`, is it desired that this element become the responder? This
|
|
71
|
+
* is usually not needed, but should be used to retroactively infer that a
|
|
72
|
+
* `touchStart` had occured during momentum scroll. During a momentum scroll,
|
|
73
|
+
* a touch start will be immediately followed by a scroll event if the view is
|
|
74
|
+
* currently scrolling.
|
|
75
|
+
*
|
|
76
|
+
* TODO: This shouldn't bubble.
|
|
77
|
+
*/
|
|
78
|
+
scrollShouldSetResponder: {
|
|
79
|
+
phasedRegistrationNames: {
|
|
80
|
+
bubbled: keyOf({ onScrollShouldSetResponder: null }),
|
|
81
|
+
captured: keyOf({ onScrollShouldSetResponderCapture: null })
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* On text selection change, should this element become the responder? This
|
|
87
|
+
* is needed for text inputs or other views with native selection, so the
|
|
88
|
+
* JS view can claim the responder.
|
|
89
|
+
*
|
|
90
|
+
* TODO: This shouldn't bubble.
|
|
91
|
+
*/
|
|
92
|
+
selectionChangeShouldSetResponder: {
|
|
93
|
+
phasedRegistrationNames: {
|
|
94
|
+
bubbled: keyOf({ onSelectionChangeShouldSetResponder: null }),
|
|
95
|
+
captured: keyOf({ onSelectionChangeShouldSetResponderCapture: null })
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* On a `touchMove`/`mouseMove`, is it desired that this element become the
|
|
101
|
+
* responder?
|
|
102
|
+
*/
|
|
103
|
+
moveShouldSetResponder: {
|
|
104
|
+
phasedRegistrationNames: {
|
|
105
|
+
bubbled: keyOf({ onMoveShouldSetResponder: null }),
|
|
106
|
+
captured: keyOf({ onMoveShouldSetResponderCapture: null })
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Direct responder events dispatched directly to responder. Do not bubble.
|
|
112
|
+
*/
|
|
113
|
+
responderStart: { registrationName: keyOf({ onResponderStart: null }) },
|
|
114
|
+
responderMove: { registrationName: keyOf({ onResponderMove: null }) },
|
|
115
|
+
responderEnd: { registrationName: keyOf({ onResponderEnd: null }) },
|
|
116
|
+
responderRelease: { registrationName: keyOf({ onResponderRelease: null }) },
|
|
117
|
+
responderTerminationRequest: {
|
|
118
|
+
registrationName: keyOf({ onResponderTerminationRequest: null })
|
|
119
|
+
},
|
|
120
|
+
responderGrant: { registrationName: keyOf({ onResponderGrant: null }) },
|
|
121
|
+
responderReject: { registrationName: keyOf({ onResponderReject: null }) },
|
|
122
|
+
responderTerminate: { registrationName: keyOf({ onResponderTerminate: null }) }
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
* Responder System:
|
|
128
|
+
* ----------------
|
|
129
|
+
*
|
|
130
|
+
* - A global, solitary "interaction lock" on a view.
|
|
131
|
+
* - If a node becomes the responder, it should convey visual feedback
|
|
132
|
+
* immediately to indicate so, either by highlighting or moving accordingly.
|
|
133
|
+
* - To be the responder means, that touches are exclusively important to that
|
|
134
|
+
* responder view, and no other view.
|
|
135
|
+
* - While touches are still occuring, the responder lock can be transfered to
|
|
136
|
+
* a new view, but only to increasingly "higher" views (meaning ancestors of
|
|
137
|
+
* the current responder).
|
|
138
|
+
*
|
|
139
|
+
* Responder being granted:
|
|
140
|
+
* ------------------------
|
|
141
|
+
*
|
|
142
|
+
* - Touch starts, moves, and scrolls can cause an ID to become the responder.
|
|
143
|
+
* - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to
|
|
144
|
+
* the "appropriate place".
|
|
145
|
+
* - If nothing is currently the responder, the "appropriate place" is the
|
|
146
|
+
* initiating event's `targetID`.
|
|
147
|
+
* - If something *is* already the responder, the "appropriate place" is the
|
|
148
|
+
* first common ancestor of the event target and the current `responderID`.
|
|
149
|
+
* - Some negotiation happens: See the timing diagram below.
|
|
150
|
+
* - Scrolled views automatically become responder. The reasoning is that a
|
|
151
|
+
* platform scroll view that isn't built on top of the responder system has
|
|
152
|
+
* began scrolling, and the active responder must now be notified that the
|
|
153
|
+
* interaction is no longer locked to it - the system has taken over.
|
|
154
|
+
*
|
|
155
|
+
* - Responder being released:
|
|
156
|
+
* As soon as no more touches that *started* inside of descendents of the
|
|
157
|
+
* *current* responderID, an `onResponderRelease` event is dispatched to the
|
|
158
|
+
* current responder, and the responder lock is released.
|
|
159
|
+
*
|
|
160
|
+
* TODO:
|
|
161
|
+
* - on "end", a callback hook for `onResponderEndShouldRemainResponder` that
|
|
162
|
+
* determines if the responder lock should remain.
|
|
163
|
+
* - If a view shouldn't "remain" the responder, any active touches should by
|
|
164
|
+
* default be considered "dead" and do not influence future negotiations or
|
|
165
|
+
* bubble paths. It should be as if those touches do not exist.
|
|
166
|
+
* -- For multitouch: Usually a translate-z will choose to "remain" responder
|
|
167
|
+
* after one out of many touches ended. For translate-y, usually the view
|
|
168
|
+
* doesn't wish to "remain" responder after one of many touches end.
|
|
169
|
+
* - Consider building this on top of a `stopPropagation` model similar to
|
|
170
|
+
* `W3C` events.
|
|
171
|
+
* - Ensure that `onResponderTerminate` is called on touch cancels, whether or
|
|
172
|
+
* not `onResponderTerminationRequest` returns `true` or `false`.
|
|
173
|
+
*
|
|
174
|
+
*/
|
|
175
|
+
|
|
176
|
+
/* Negotiation Performed
|
|
177
|
+
+-----------------------+
|
|
178
|
+
/ \
|
|
179
|
+
Process low level events to + Current Responder + wantsResponderID
|
|
180
|
+
determine who to perform negot-| (if any exists at all) |
|
|
181
|
+
iation/transition | Otherwise just pass through|
|
|
182
|
+
-------------------------------+----------------------------+------------------+
|
|
183
|
+
Bubble to find first ID | |
|
|
184
|
+
to return true:wantsResponderID| |
|
|
185
|
+
| |
|
|
186
|
+
+-------------+ | |
|
|
187
|
+
| onTouchStart| | |
|
|
188
|
+
+------+------+ none | |
|
|
189
|
+
| return| |
|
|
190
|
+
+-----------v-------------+true| +------------------------+ |
|
|
191
|
+
|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+
|
|
192
|
+
+-----------+-------------+ | +------------------------+ | |
|
|
193
|
+
| | | +--------+-------+
|
|
194
|
+
| returned true for| false:REJECT +-------->|onResponderReject
|
|
195
|
+
| wantsResponderID | | | +----------------+
|
|
196
|
+
| (now attempt | +------------------+-----+ |
|
|
197
|
+
| handoff) | | onResponder | |
|
|
198
|
+
+------------------->| TerminationRequest| |
|
|
199
|
+
| +------------------+-----+ |
|
|
200
|
+
| | | +----------------+
|
|
201
|
+
| true:GRANT +-------->|onResponderGrant|
|
|
202
|
+
| | +--------+-------+
|
|
203
|
+
| +------------------------+ | |
|
|
204
|
+
| | onResponderTerminate |<-----------+
|
|
205
|
+
| +------------------+-----+ |
|
|
206
|
+
| | | +----------------+
|
|
207
|
+
| +-------->|onResponderStart|
|
|
208
|
+
| | +----------------+
|
|
209
|
+
Bubble to find first ID | |
|
|
210
|
+
to return true:wantsResponderID| |
|
|
211
|
+
| |
|
|
212
|
+
+-------------+ | |
|
|
213
|
+
| onTouchMove | | |
|
|
214
|
+
+------+------+ none | |
|
|
215
|
+
| return| |
|
|
216
|
+
+-----------v-------------+true| +------------------------+ |
|
|
217
|
+
|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+
|
|
218
|
+
+-----------+-------------+ | +------------------------+ | |
|
|
219
|
+
| | | +--------+-------+
|
|
220
|
+
| returned true for| false:REJECT +-------->|onResponderRejec|
|
|
221
|
+
| wantsResponderID | | | +----------------+
|
|
222
|
+
| (now attempt | +------------------+-----+ |
|
|
223
|
+
| handoff) | | onResponder | |
|
|
224
|
+
+------------------->| TerminationRequest| |
|
|
225
|
+
| +------------------+-----+ |
|
|
226
|
+
| | | +----------------+
|
|
227
|
+
| true:GRANT +-------->|onResponderGrant|
|
|
228
|
+
| | +--------+-------+
|
|
229
|
+
| +------------------------+ | |
|
|
230
|
+
| | onResponderTerminate |<-----------+
|
|
231
|
+
| +------------------+-----+ |
|
|
232
|
+
| | | +----------------+
|
|
233
|
+
| +-------->|onResponderMove |
|
|
234
|
+
| | +----------------+
|
|
235
|
+
| |
|
|
236
|
+
| |
|
|
237
|
+
Some active touch started| |
|
|
238
|
+
inside current responder | +------------------------+ |
|
|
239
|
+
+------------------------->| onResponderEnd | |
|
|
240
|
+
| | +------------------------+ |
|
|
241
|
+
+---+---------+ | |
|
|
242
|
+
| onTouchEnd | | |
|
|
243
|
+
+---+---------+ | |
|
|
244
|
+
| | +------------------------+ |
|
|
245
|
+
+------------------------->| onResponderEnd | |
|
|
246
|
+
No active touches started| +-----------+------------+ |
|
|
247
|
+
inside current responder | | |
|
|
248
|
+
| v |
|
|
249
|
+
| +------------------------+ |
|
|
250
|
+
| | onResponderRelease | |
|
|
251
|
+
| +------------------------+ |
|
|
252
|
+
| |
|
|
253
|
+
+ + */
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* A note about event ordering in the `EventPluginHub`.
|
|
257
|
+
*
|
|
258
|
+
* Suppose plugins are injected in the following order:
|
|
259
|
+
*
|
|
260
|
+
* `[R, S, C]`
|
|
261
|
+
*
|
|
262
|
+
* To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
|
|
263
|
+
* `onClick` etc) and `R` is `ResponderEventPlugin`.
|
|
264
|
+
*
|
|
265
|
+
* "Deferred-Dispatched Events":
|
|
266
|
+
*
|
|
267
|
+
* - The current event plugin system will traverse the list of injected plugins,
|
|
268
|
+
* in order, and extract events by collecting the plugin's return value of
|
|
269
|
+
* `extractEvents()`.
|
|
270
|
+
* - These events that are returned from `extractEvents` are "deferred
|
|
271
|
+
* dispatched events".
|
|
272
|
+
* - When returned from `extractEvents`, deferred-dispatched events contain an
|
|
273
|
+
* "accumulation" of deferred dispatches.
|
|
274
|
+
* - These deferred dispatches are accumulated/collected before they are
|
|
275
|
+
* returned, but processed at a later time by the `EventPluginHub` (hence the
|
|
276
|
+
* name deferred).
|
|
277
|
+
*
|
|
278
|
+
* In the process of returning their deferred-dispatched events, event plugins
|
|
279
|
+
* themselves can dispatch events on-demand without returning them from
|
|
280
|
+
* `extractEvents`. Plugins might want to do this, so that they can use event
|
|
281
|
+
* dispatching as a tool that helps them decide which events should be extracted
|
|
282
|
+
* in the first place.
|
|
283
|
+
*
|
|
284
|
+
* "On-Demand-Dispatched Events":
|
|
285
|
+
*
|
|
286
|
+
* - On-demand-dispatched events are not returned from `extractEvents`.
|
|
287
|
+
* - On-demand-dispatched events are dispatched during the process of returning
|
|
288
|
+
* the deferred-dispatched events.
|
|
289
|
+
* - They should not have side effects.
|
|
290
|
+
* - They should be avoided, and/or eventually be replaced with another
|
|
291
|
+
* abstraction that allows event plugins to perform multiple "rounds" of event
|
|
292
|
+
* extraction.
|
|
293
|
+
*
|
|
294
|
+
* Therefore, the sequence of event dispatches becomes:
|
|
295
|
+
*
|
|
296
|
+
* - `R`s on-demand events (if any) (dispatched by `R` on-demand)
|
|
297
|
+
* - `S`s on-demand events (if any) (dispatched by `S` on-demand)
|
|
298
|
+
* - `C`s on-demand events (if any) (dispatched by `C` on-demand)
|
|
299
|
+
* - `R`s extracted events (if any) (dispatched by `EventPluginHub`)
|
|
300
|
+
* - `S`s extracted events (if any) (dispatched by `EventPluginHub`)
|
|
301
|
+
* - `C`s extracted events (if any) (dispatched by `EventPluginHub`)
|
|
302
|
+
*
|
|
303
|
+
* In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
|
|
304
|
+
* on-demand dispatch returns `true` (and some other details are satisfied) the
|
|
305
|
+
* `onResponderGrant` deferred dispatched event is returned from
|
|
306
|
+
* `extractEvents`. The sequence of dispatch executions in this case
|
|
307
|
+
* will appear as follows:
|
|
308
|
+
*
|
|
309
|
+
* - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
|
|
310
|
+
* - `touchStartCapture` (`EventPluginHub` dispatches as usual)
|
|
311
|
+
* - `touchStart` (`EventPluginHub` dispatches as usual)
|
|
312
|
+
* - `responderGrant/Reject` (`EventPluginHub` dispatches as usual)
|
|
313
|
+
*
|
|
314
|
+
* @param {string} topLevelType Record from `EventConstants`.
|
|
315
|
+
* @param {string} topLevelTargetID ID of deepest React rendered element.
|
|
316
|
+
* @param {object} nativeEvent Native browser event.
|
|
317
|
+
* @return {*} An accumulation of synthetic events.
|
|
318
|
+
*/
|
|
319
|
+
function setResponderAndExtractTransfer(topLevelType, topLevelTargetID, nativeEvent, nativeEventTarget) {
|
|
320
|
+
var shouldSetEventType = isStartish(topLevelType) ? eventTypes.startShouldSetResponder : isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder : topLevelType === EventConstants.topLevelTypes.topSelectionChange ? eventTypes.selectionChangeShouldSetResponder : eventTypes.scrollShouldSetResponder;
|
|
321
|
+
|
|
322
|
+
// TODO: stop one short of the the current responder.
|
|
323
|
+
var bubbleShouldSetFrom = !responderID ? topLevelTargetID : ReactInstanceHandles.getFirstCommonAncestorID(responderID, topLevelTargetID);
|
|
324
|
+
|
|
325
|
+
// When capturing/bubbling the "shouldSet" event, we want to skip the target
|
|
326
|
+
// (deepest ID) if it happens to be the current responder. The reasoning:
|
|
327
|
+
// It's strange to get an `onMoveShouldSetResponder` when you're *already*
|
|
328
|
+
// the responder.
|
|
329
|
+
var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderID;
|
|
330
|
+
var shouldSetEvent = ResponderSyntheticEvent.getPooled(shouldSetEventType, bubbleShouldSetFrom, nativeEvent, nativeEventTarget);
|
|
331
|
+
shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
332
|
+
if (skipOverBubbleShouldSetFrom) {
|
|
333
|
+
EventPropagators.accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
|
|
334
|
+
} else {
|
|
335
|
+
EventPropagators.accumulateTwoPhaseDispatches(shouldSetEvent);
|
|
336
|
+
}
|
|
337
|
+
var wantsResponderID = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
|
|
338
|
+
if (!shouldSetEvent.isPersistent()) {
|
|
339
|
+
shouldSetEvent.constructor.release(shouldSetEvent);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (!wantsResponderID || wantsResponderID === responderID) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
var extracted;
|
|
346
|
+
var grantEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderGrant, wantsResponderID, nativeEvent, nativeEventTarget);
|
|
347
|
+
grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
348
|
+
|
|
349
|
+
EventPropagators.accumulateDirectDispatches(grantEvent);
|
|
350
|
+
if (responderID) {
|
|
351
|
+
|
|
352
|
+
var terminationRequestEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminationRequest, responderID, nativeEvent, nativeEventTarget);
|
|
353
|
+
terminationRequestEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
354
|
+
EventPropagators.accumulateDirectDispatches(terminationRequestEvent);
|
|
355
|
+
var shouldSwitch = !hasDispatches(terminationRequestEvent) || executeDirectDispatch(terminationRequestEvent);
|
|
356
|
+
if (!terminationRequestEvent.isPersistent()) {
|
|
357
|
+
terminationRequestEvent.constructor.release(terminationRequestEvent);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (shouldSwitch) {
|
|
361
|
+
var terminateType = eventTypes.responderTerminate;
|
|
362
|
+
var terminateEvent = ResponderSyntheticEvent.getPooled(terminateType, responderID, nativeEvent, nativeEventTarget);
|
|
363
|
+
terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
364
|
+
EventPropagators.accumulateDirectDispatches(terminateEvent);
|
|
365
|
+
extracted = accumulate(extracted, [grantEvent, terminateEvent]);
|
|
366
|
+
changeResponder(wantsResponderID);
|
|
367
|
+
} else {
|
|
368
|
+
var rejectEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderReject, wantsResponderID, nativeEvent, nativeEventTarget);
|
|
369
|
+
rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
370
|
+
EventPropagators.accumulateDirectDispatches(rejectEvent);
|
|
371
|
+
extracted = accumulate(extracted, rejectEvent);
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
extracted = accumulate(extracted, grantEvent);
|
|
375
|
+
changeResponder(wantsResponderID);
|
|
376
|
+
}
|
|
377
|
+
return extracted;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* A transfer is a negotiation between a currently set responder and the next
|
|
382
|
+
* element to claim responder status. Any start event could trigger a transfer
|
|
383
|
+
* of responderID. Any move event could trigger a transfer.
|
|
384
|
+
*
|
|
385
|
+
* @param {string} topLevelType Record from `EventConstants`.
|
|
386
|
+
* @return {boolean} True if a transfer of responder could possibly occur.
|
|
387
|
+
*/
|
|
388
|
+
function canTriggerTransfer(topLevelType, topLevelTargetID) {
|
|
389
|
+
return topLevelTargetID && (topLevelType === EventConstants.topLevelTypes.topScroll || trackedTouchCount > 0 && topLevelType === EventConstants.topLevelTypes.topSelectionChange || isStartish(topLevelType) || isMoveish(topLevelType));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Returns whether or not this touch end event makes it such that there are no
|
|
394
|
+
* longer any touches that started inside of the current `responderID`.
|
|
395
|
+
*
|
|
396
|
+
* @param {NativeEvent} nativeEvent Native touch end event.
|
|
397
|
+
* @return {boolean} Whether or not this touch end event ends the responder.
|
|
398
|
+
*/
|
|
399
|
+
function noResponderTouches(nativeEvent) {
|
|
400
|
+
var touches = nativeEvent.touches;
|
|
401
|
+
if (!touches || touches.length === 0) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
for (var i = 0; i < touches.length; i++) {
|
|
405
|
+
var activeTouch = touches[i];
|
|
406
|
+
var target = activeTouch.target;
|
|
407
|
+
if (target !== null && target !== undefined && target !== 0) {
|
|
408
|
+
// Is the original touch location inside of the current responder?
|
|
409
|
+
var isAncestor = ReactInstanceHandles.isAncestorIDOf(responderID, EventPluginUtils.getID(target));
|
|
410
|
+
if (isAncestor) {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
var ResponderEventPlugin = {
|
|
419
|
+
|
|
420
|
+
getResponderID: function () {
|
|
421
|
+
return responderID;
|
|
422
|
+
},
|
|
423
|
+
|
|
424
|
+
eventTypes: eventTypes,
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* We must be resilient to `topLevelTargetID` being `undefined` on
|
|
428
|
+
* `touchMove`, or `touchEnd`. On certain platforms, this means that a native
|
|
429
|
+
* scroll has assumed control and the original touch targets are destroyed.
|
|
430
|
+
*
|
|
431
|
+
* @param {string} topLevelType Record from `EventConstants`.
|
|
432
|
+
* @param {DOMEventTarget} topLevelTarget The listening component root node.
|
|
433
|
+
* @param {string} topLevelTargetID ID of `topLevelTarget`.
|
|
434
|
+
* @param {object} nativeEvent Native browser event.
|
|
435
|
+
* @return {*} An accumulation of synthetic events.
|
|
436
|
+
* @see {EventPluginHub.extractEvents}
|
|
437
|
+
*/
|
|
438
|
+
extractEvents: function (topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
|
|
439
|
+
if (isStartish(topLevelType)) {
|
|
440
|
+
trackedTouchCount += 1;
|
|
441
|
+
} else if (isEndish(topLevelType)) {
|
|
442
|
+
trackedTouchCount -= 1;
|
|
443
|
+
!(trackedTouchCount >= 0) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Ended a touch event which was not counted in trackedTouchCount.') : invariant(false) : undefined;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent, nativeEventTarget);
|
|
447
|
+
|
|
448
|
+
var extracted = canTriggerTransfer(topLevelType, topLevelTargetID) ? setResponderAndExtractTransfer(topLevelType, topLevelTargetID, nativeEvent, nativeEventTarget) : null;
|
|
449
|
+
// Responder may or may not have transfered on a new touch start/move.
|
|
450
|
+
// Regardless, whoever is the responder after any potential transfer, we
|
|
451
|
+
// direct all touch start/move/ends to them in the form of
|
|
452
|
+
// `onResponderMove/Start/End`. These will be called for *every* additional
|
|
453
|
+
// finger that move/start/end, dispatched directly to whoever is the
|
|
454
|
+
// current responder at that moment, until the responder is "released".
|
|
455
|
+
//
|
|
456
|
+
// These multiple individual change touch events are are always bookended
|
|
457
|
+
// by `onResponderGrant`, and one of
|
|
458
|
+
// (`onResponderRelease/onResponderTerminate`).
|
|
459
|
+
var isResponderTouchStart = responderID && isStartish(topLevelType);
|
|
460
|
+
var isResponderTouchMove = responderID && isMoveish(topLevelType);
|
|
461
|
+
var isResponderTouchEnd = responderID && isEndish(topLevelType);
|
|
462
|
+
var incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove ? eventTypes.responderMove : isResponderTouchEnd ? eventTypes.responderEnd : null;
|
|
463
|
+
|
|
464
|
+
if (incrementalTouch) {
|
|
465
|
+
var gesture = ResponderSyntheticEvent.getPooled(incrementalTouch, responderID, nativeEvent, nativeEventTarget);
|
|
466
|
+
gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
467
|
+
EventPropagators.accumulateDirectDispatches(gesture);
|
|
468
|
+
extracted = accumulate(extracted, gesture);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
var isResponderTerminate = responderID && topLevelType === EventConstants.topLevelTypes.topTouchCancel;
|
|
472
|
+
var isResponderRelease = responderID && !isResponderTerminate && isEndish(topLevelType) && noResponderTouches(nativeEvent);
|
|
473
|
+
var finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease ? eventTypes.responderRelease : null;
|
|
474
|
+
if (finalTouch) {
|
|
475
|
+
var finalEvent = ResponderSyntheticEvent.getPooled(finalTouch, responderID, nativeEvent, nativeEventTarget);
|
|
476
|
+
finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
477
|
+
EventPropagators.accumulateDirectDispatches(finalEvent);
|
|
478
|
+
extracted = accumulate(extracted, finalEvent);
|
|
479
|
+
changeResponder(null);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
var numberActiveTouches = ResponderTouchHistoryStore.touchHistory.numberActiveTouches;
|
|
483
|
+
if (ResponderEventPlugin.GlobalInteractionHandler && numberActiveTouches !== previousActiveTouches) {
|
|
484
|
+
ResponderEventPlugin.GlobalInteractionHandler.onChange(numberActiveTouches);
|
|
485
|
+
}
|
|
486
|
+
previousActiveTouches = numberActiveTouches;
|
|
487
|
+
|
|
488
|
+
return extracted;
|
|
489
|
+
},
|
|
490
|
+
|
|
491
|
+
GlobalResponderHandler: null,
|
|
492
|
+
GlobalInteractionHandler: null,
|
|
493
|
+
|
|
494
|
+
injection: {
|
|
495
|
+
/**
|
|
496
|
+
* @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler
|
|
497
|
+
* Object that handles any change in responder. Use this to inject
|
|
498
|
+
* integration with an existing touch handling system etc.
|
|
499
|
+
*/
|
|
500
|
+
injectGlobalResponderHandler: function (GlobalResponderHandler) {
|
|
501
|
+
ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler;
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* @param {{onChange: (numberActiveTouches) => void} GlobalInteractionHandler
|
|
506
|
+
* Object that handles any change in the number of active touches.
|
|
507
|
+
*/
|
|
508
|
+
injectGlobalInteractionHandler: function (GlobalInteractionHandler) {
|
|
509
|
+
ResponderEventPlugin.GlobalInteractionHandler = GlobalInteractionHandler;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
module.exports = ResponderEventPlugin;
|