This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,71 @@
"use strict";
exports.__esModule = true;
exports.isStartish = isStartish;
exports.isMoveish = isMoveish;
exports.isEndish = isEndish;
exports.isCancelish = isCancelish;
exports.isScroll = isScroll;
exports.isSelectionChange = isSelectionChange;
exports.SELECTION_CHANGE = exports.SELECT = exports.SCROLL = exports.TOUCH_CANCEL = exports.TOUCH_END = exports.TOUCH_MOVE = exports.TOUCH_START = exports.MOUSE_CANCEL = exports.MOUSE_UP = exports.MOUSE_MOVE = exports.MOUSE_DOWN = exports.FOCUS_OUT = exports.CONTEXT_MENU = exports.BLUR = void 0;
/**
* Copyright (c) Nicolas Gallagher
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
var BLUR = 'blur';
exports.BLUR = BLUR;
var CONTEXT_MENU = 'contextmenu';
exports.CONTEXT_MENU = CONTEXT_MENU;
var FOCUS_OUT = 'focusout';
exports.FOCUS_OUT = FOCUS_OUT;
var MOUSE_DOWN = 'mousedown';
exports.MOUSE_DOWN = MOUSE_DOWN;
var MOUSE_MOVE = 'mousemove';
exports.MOUSE_MOVE = MOUSE_MOVE;
var MOUSE_UP = 'mouseup';
exports.MOUSE_UP = MOUSE_UP;
var MOUSE_CANCEL = 'dragstart';
exports.MOUSE_CANCEL = MOUSE_CANCEL;
var TOUCH_START = 'touchstart';
exports.TOUCH_START = TOUCH_START;
var TOUCH_MOVE = 'touchmove';
exports.TOUCH_MOVE = TOUCH_MOVE;
var TOUCH_END = 'touchend';
exports.TOUCH_END = TOUCH_END;
var TOUCH_CANCEL = 'touchcancel';
exports.TOUCH_CANCEL = TOUCH_CANCEL;
var SCROLL = 'scroll';
exports.SCROLL = SCROLL;
var SELECT = 'select';
exports.SELECT = SELECT;
var SELECTION_CHANGE = 'selectionchange';
exports.SELECTION_CHANGE = SELECTION_CHANGE;
function isStartish(eventType) {
return eventType === TOUCH_START || eventType === MOUSE_DOWN;
}
function isMoveish(eventType) {
return eventType === TOUCH_MOVE || eventType === MOUSE_MOVE;
}
function isEndish(eventType) {
return eventType === TOUCH_END || eventType === MOUSE_UP || isCancelish(eventType);
}
function isCancelish(eventType) {
return eventType === TOUCH_CANCEL || eventType === MOUSE_CANCEL;
}
function isScroll(eventType) {
return eventType === SCROLL;
}
function isSelectionChange(eventType) {
return eventType === SELECT || eventType === SELECTION_CHANGE;
}

View File

@ -0,0 +1,603 @@
"use strict";
exports.__esModule = true;
exports.attachListeners = attachListeners;
exports.addNode = addNode;
exports.removeNode = removeNode;
exports.terminateResponder = terminateResponder;
exports.getResponderNode = getResponderNode;
var _ExecutionEnvironment = require("fbjs/lib/ExecutionEnvironment");
var _createResponderEvent = _interopRequireDefault(require("./createResponderEvent"));
var _ResponderEventTypes = require("./ResponderEventTypes");
var _utils = require("./utils");
var _ResponderTouchHistoryStore = _interopRequireDefault(require("./ResponderTouchHistoryStore"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright (c) Nicolas Gallagher
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
/**
* RESPONDER EVENT SYSTEM
*
* A single, global "interaction lock" on views. For a view to be the "responder" means
* that pointer interactions are exclusive to that view and none other. The "interaction
* lock" can be transferred (only) to ancestors of the current "responder" as long as
* pointers continue to be active.
*
* Responder being granted:
*
* A view can become the "responder" after the following events:
* * "pointerdown" (implemented using "touchstart", "mousedown")
* * "pointermove" (implemented using "touchmove", "mousemove")
* * "scroll" (while a pointer is down)
* * "selectionchange" (while a pointer is down)
*
* If nothing is already the "responder", the event propagates to (capture) and from
* (bubble) the event target until a view returns `true` for
* `on*ShouldSetResponder(Capture)`.
*
* If something is already the responder, the event propagates to (capture) and from
* (bubble) the lowest common ancestor of the event target and the current "responder".
* Then negotiation happens between the current "responder" and a view that wants to
* become the "responder": see the timing diagram below.
*
* (NOTE: Scrolled views either automatically become the "responder" or release the
* "interaction lock". A native scroll view that isn't built on top of the responder
* system must result in the current "responder" being notified that it no longer has
* the "interaction lock" - the native system has taken over.
*
* Responder being released:
*
* As soon as there are no more active pointers that *started* inside descendants
* of the *current* "responder", an `onResponderRelease` event is dispatched to the
* current "responder", and the responder lock is released.
*
* Typical sequence of events:
* * startShouldSetResponder
* * responderGrant/Reject
* * responderStart
* * responderMove
* * responderEnd
* * responderRelease
*/
/* Negotiation Performed
+-----------------------+
/ \
Process low level events to + Current Responder + wantsResponderID
determine who to perform negot-| (if any exists at all) |
iation/transition | Otherwise just pass through|
-------------------------------+----------------------------+------------------+
Bubble to find first ID | |
to return true:wantsResponderID| |
| |
+--------------+ | |
| onTouchStart | | |
+------+-------+ none | |
| return| |
+-----------v-------------+true| +------------------------+ |
|onStartShouldSetResponder|----->| onResponderStart (cur) |<-----------+
+-----------+-------------+ | +------------------------+ | |
| | | +--------+-------+
| returned true for| false:REJECT +-------->|onResponderReject
| wantsResponderID | | | +----------------+
| (now attempt | +------------------+-----+ |
| handoff) | | onResponder | |
+------------------->| TerminationRequest | |
| +------------------+-----+ |
| | | +----------------+
| true:GRANT +-------->|onResponderGrant|
| | +--------+-------+
| +------------------------+ | |
| | onResponderTerminate |<-----------+
| +------------------+-----+ |
| | | +----------------+
| +-------->|onResponderStart|
| | +----------------+
Bubble to find first ID | |
to return true:wantsResponderID| |
| |
+-------------+ | |
| onTouchMove | | |
+------+------+ none | |
| return| |
+-----------v-------------+true| +------------------------+ |
|onMoveShouldSetResponder |----->| onResponderMove (cur) |<-----------+
+-----------+-------------+ | +------------------------+ | |
| | | +--------+-------+
| returned true for| false:REJECT +-------->|onResponderReject
| wantsResponderID | | | +----------------+
| (now attempt | +------------------+-----+ |
| handoff) | | onResponder | |
+------------------->| TerminationRequest| |
| +------------------+-----+ |
| | | +----------------+
| true:GRANT +-------->|onResponderGrant|
| | +--------+-------+
| +------------------------+ | |
| | onResponderTerminate |<-----------+
| +------------------+-----+ |
| | | +----------------+
| +-------->|onResponderMove |
| | +----------------+
| |
| |
Some active touch started| |
inside current responder | +------------------------+ |
+------------------------->| onResponderEnd | |
| | +------------------------+ |
+---+---------+ | |
| onTouchEnd | | |
+---+---------+ | |
| | +------------------------+ |
+------------------------->| onResponderEnd | |
No active touches started| +-----------+------------+ |
inside current responder | | |
| v |
| +------------------------+ |
| | onResponderRelease | |
| +------------------------+ |
| |
+ + */
var emptyObject = {};
/* ------------ IMPLEMENTATION ------------ */
var startRegistration = ['onStartShouldSetResponderCapture', 'onStartShouldSetResponder', {
bubbles: true
}];
var moveRegistration = ['onMoveShouldSetResponderCapture', 'onMoveShouldSetResponder', {
bubbles: true
}];
var scrollRegistration = ['onScrollShouldSetResponderCapture', 'onScrollShouldSetResponder', {
bubbles: false
}];
var shouldSetResponderEvents = {
touchstart: startRegistration,
mousedown: startRegistration,
touchmove: moveRegistration,
mousemove: moveRegistration,
scroll: scrollRegistration
};
var emptyResponder = {
id: null,
idPath: null,
node: null
};
var responderListenersMap = new Map();
var isEmulatingMouseEvents = false;
var trackedTouchCount = 0;
var currentResponder = {
id: null,
node: null,
idPath: null
};
function changeCurrentResponder(responder) {
currentResponder = responder;
}
function getResponderConfig(id) {
var config = responderListenersMap.get(id);
return config != null ? config : emptyObject;
}
/**
* Process native events
*
* A single event listener is used to manage the responder system.
* All pointers are tracked in the ResponderTouchHistoryStore. Native events
* are interpreted in terms of the Responder System and checked to see if
* the responder should be transferred. Each host node that is attached to
* the Responder System has an ID, which is used to look up its associated
* callbacks.
*/
function eventListener(domEvent) {
var eventType = domEvent.type;
var eventTarget = domEvent.target;
/**
* Manage emulated events and early bailout.
* Since PointerEvent is not used yet (lack of support in older Safari), it's
* necessary to manually manage the mess of browser touch/mouse events.
* And bailout early for termination events when there is no active responder.
*/
// Flag when browser may produce emulated events
if (eventType === 'touchstart') {
isEmulatingMouseEvents = true;
} // Remove flag when browser will not produce emulated events
if (eventType === 'touchmove' || trackedTouchCount > 1) {
isEmulatingMouseEvents = false;
} // Ignore various events in particular circumstances
if ( // Ignore browser emulated mouse events
eventType === 'mousedown' && isEmulatingMouseEvents || eventType === 'mousemove' && isEmulatingMouseEvents || // Ignore mousemove if a mousedown didn't occur first
eventType === 'mousemove' && trackedTouchCount < 1) {
return;
} // Remove flag after emulated events are finished
if (isEmulatingMouseEvents && eventType === 'mouseup') {
if (trackedTouchCount === 0) {
isEmulatingMouseEvents = false;
}
return;
}
var isStartEvent = (0, _ResponderEventTypes.isStartish)(eventType) && (0, _utils.isPrimaryPointerDown)(domEvent);
var isMoveEvent = (0, _ResponderEventTypes.isMoveish)(eventType);
var isEndEvent = (0, _ResponderEventTypes.isEndish)(eventType);
var isScrollEvent = (0, _ResponderEventTypes.isScroll)(eventType);
var isSelectionChangeEvent = (0, _ResponderEventTypes.isSelectionChange)(eventType);
var responderEvent = (0, _createResponderEvent.default)(domEvent);
/**
* Record the state of active pointers
*/
if (isStartEvent || isMoveEvent || isEndEvent) {
if (domEvent.touches) {
trackedTouchCount = domEvent.touches.length;
} else {
if (isStartEvent) {
trackedTouchCount = 1;
} else if (isEndEvent) {
trackedTouchCount = 0;
}
}
_ResponderTouchHistoryStore.default.recordTouchTrack(eventType, responderEvent.nativeEvent);
}
/**
* Responder System logic
*/
var eventPaths = (0, _utils.getResponderPaths)(domEvent);
var wasNegotiated = false;
var wantsResponder; // If an event occured that might change the current responder...
if (isStartEvent || isMoveEvent || isScrollEvent && trackedTouchCount > 0) {
// If there is already a responder, prune the event paths to the lowest common ancestor
// of the existing responder and deepest target of the event.
var currentResponderIdPath = currentResponder.idPath;
var eventIdPath = eventPaths.idPath;
if (currentResponderIdPath != null && eventIdPath != null) {
var lowestCommonAncestor = (0, _utils.getLowestCommonAncestor)(currentResponderIdPath, eventIdPath);
if (lowestCommonAncestor != null) {
var indexOfLowestCommonAncestor = eventIdPath.indexOf(lowestCommonAncestor); // Skip the current responder so it doesn't receive unexpected "shouldSet" events.
var index = indexOfLowestCommonAncestor + (lowestCommonAncestor === currentResponder.id ? 1 : 0);
eventPaths = {
idPath: eventIdPath.slice(index),
nodePath: eventPaths.nodePath.slice(index)
};
} else {
eventPaths = null;
}
}
if (eventPaths != null) {
// If a node wants to become the responder, attempt to transfer.
wantsResponder = findWantsResponder(eventPaths, domEvent, responderEvent);
if (wantsResponder != null) {
// Sets responder if none exists, or negotates with existing responder.
attemptTransfer(responderEvent, wantsResponder);
wasNegotiated = true;
}
}
} // If there is now a responder, invoke its callbacks for the lifecycle of the gesture.
if (currentResponder.id != null && currentResponder.node != null) {
var _currentResponder = currentResponder,
id = _currentResponder.id,
node = _currentResponder.node;
var _getResponderConfig = getResponderConfig(id),
onResponderStart = _getResponderConfig.onResponderStart,
onResponderMove = _getResponderConfig.onResponderMove,
onResponderEnd = _getResponderConfig.onResponderEnd,
onResponderRelease = _getResponderConfig.onResponderRelease,
onResponderTerminate = _getResponderConfig.onResponderTerminate,
onResponderTerminationRequest = _getResponderConfig.onResponderTerminationRequest;
responderEvent.bubbles = false;
responderEvent.cancelable = false;
responderEvent.currentTarget = node; // Start
if (isStartEvent) {
if (onResponderStart != null) {
onResponderStart(responderEvent);
}
} // Move
else if (isMoveEvent) {
if (onResponderMove != null) {
onResponderMove(responderEvent);
}
} else {
var isTerminateEvent = (0, _ResponderEventTypes.isCancelish)(eventType) || // native context menu
eventType === 'contextmenu' || // window blur
eventType === 'blur' && eventTarget === window || // responder (or ancestors) blur
eventType === 'blur' && eventTarget.contains(node) && domEvent.relatedTarget !== node || // native scroll without using a pointer
isScrollEvent && trackedTouchCount === 0 || // native scroll on node that is parent of the responder (allow siblings to scroll)
isScrollEvent && eventTarget.contains(node) && eventTarget !== node || // native select/selectionchange on node
isSelectionChangeEvent && (0, _utils.hasValidSelection)(domEvent);
var isReleaseEvent = isEndEvent && !isTerminateEvent && !(0, _utils.hasTargetTouches)(node, domEvent.touches); // End
if (isEndEvent) {
if (onResponderEnd != null) {
onResponderEnd(responderEvent);
}
} // Release
if (isReleaseEvent) {
if (onResponderRelease != null) {
onResponderRelease(responderEvent);
}
changeCurrentResponder(emptyResponder);
} // Terminate
if (isTerminateEvent) {
var shouldTerminate = true; // Responders can still avoid termination but only for these events.
if (eventType === 'contextmenu' || eventType === 'scroll' || eventType === 'selectionchange') {
if (wasNegotiated || // Only call this function is it wasn't already called during negotiation.
onResponderTerminationRequest != null && onResponderTerminationRequest(responderEvent) === false) {
shouldTerminate = false;
}
}
if (shouldTerminate) {
if (onResponderTerminate != null) {
onResponderTerminate(responderEvent);
}
changeCurrentResponder(emptyResponder);
isEmulatingMouseEvents = false;
trackedTouchCount = 0;
}
}
}
}
}
/**
* Walk the event path to/from the target node. At each node, stop and call the
* relevant "shouldSet" functions for the given event type. If any of those functions
* call "stopPropagation" on the event, stop searching for a responder.
*/
function findWantsResponder(eventPaths, domEvent, responderEvent) {
var shouldSetCallbacks = shouldSetResponderEvents[domEvent.type]; // for Flow
if (shouldSetCallbacks != null) {
var idPath = eventPaths.idPath,
nodePath = eventPaths.nodePath;
var shouldSetCallbackCaptureName = shouldSetCallbacks[0];
var shouldSetCallbackBubbleName = shouldSetCallbacks[1];
var bubbles = shouldSetCallbacks[2].bubbles;
var check = function check(id, node, callbackName) {
var config = getResponderConfig(id);
var shouldSetCallback = config[callbackName];
if (shouldSetCallback != null) {
if (shouldSetCallback(responderEvent) === true) {
return {
id: id,
node: node,
idPath: idPath
};
}
}
}; // capture
for (var i = idPath.length - 1; i >= 0; i--) {
var id = idPath[i];
var node = nodePath[i];
var result = check(id, node, shouldSetCallbackCaptureName);
if (result != null) {
return result;
}
if (responderEvent.isPropagationStopped() === true) {
return;
}
} // bubble
if (bubbles) {
for (var _i = 0; _i < idPath.length; _i++) {
var _id = idPath[_i];
var _node = nodePath[_i];
var _result = check(_id, _node, shouldSetCallbackBubbleName);
if (_result != null) {
return _result;
}
if (responderEvent.isPropagationStopped() === true) {
return;
}
}
} else {
var _id2 = idPath[0];
var _node2 = nodePath[0];
var target = domEvent.target;
if (target === _node2) {
return check(_id2, _node2, shouldSetCallbackBubbleName);
}
}
}
}
/**
* Attempt to transfer the responder.
*/
function attemptTransfer(responderEvent, wantsResponder) {
var _currentResponder2 = currentResponder,
currentId = _currentResponder2.id,
currentNode = _currentResponder2.node;
var id = wantsResponder.id,
node = wantsResponder.node;
var _getResponderConfig2 = getResponderConfig(id),
onResponderGrant = _getResponderConfig2.onResponderGrant,
onResponderReject = _getResponderConfig2.onResponderReject;
responderEvent.bubbles = false;
responderEvent.cancelable = false;
responderEvent.currentTarget = node; // Set responder
if (currentId == null) {
if (onResponderGrant != null) {
responderEvent.currentTarget = node;
responderEvent.dispatchConfig.registrationName = 'onResponderGrant';
onResponderGrant(responderEvent);
}
changeCurrentResponder(wantsResponder);
} // Negotiate with current responder
else {
var _getResponderConfig3 = getResponderConfig(currentId),
onResponderTerminate = _getResponderConfig3.onResponderTerminate,
onResponderTerminationRequest = _getResponderConfig3.onResponderTerminationRequest;
var allowTransfer = onResponderTerminationRequest != null && onResponderTerminationRequest(responderEvent);
if (allowTransfer) {
// Terminate existing responder
if (onResponderTerminate != null) {
responderEvent.currentTarget = currentNode;
onResponderTerminate(responderEvent);
} // Grant next responder
if (onResponderGrant != null) {
onResponderGrant(responderEvent);
}
changeCurrentResponder(wantsResponder);
} else {
// Reject responder request
if (onResponderReject != null) {
onResponderReject(responderEvent);
}
}
}
}
/* ------------ PUBLIC API ------------ */
/**
* Attach Listeners
*
* Use native events as ReactDOM doesn't have a non-plugin API to implement
* this system.
*/
var documentEventsCapturePhase = ['blur', 'scroll'];
var documentEventsBubblePhase = [// mouse
'mousedown', 'mousemove', 'mouseup', 'dragstart', // touch
'touchstart', 'touchmove', 'touchend', 'touchcancel', // other
'contextmenu', 'select', 'selectionchange'];
function attachListeners() {
if (_ExecutionEnvironment.canUseDOM && window.__reactResponderSystemActive == null) {
window.addEventListener('blur', eventListener);
documentEventsBubblePhase.forEach(function (eventType) {
document.addEventListener(eventType, eventListener);
});
documentEventsCapturePhase.forEach(function (eventType) {
document.addEventListener(eventType, eventListener, true);
});
window.__reactResponderSystemActive = true;
}
}
/**
* Register a node with the ResponderSystem.
*/
function addNode(id, node, config) {
(0, _utils.setResponderId)(node, id);
responderListenersMap.set(id, config);
}
/**
* Unregister a node with the ResponderSystem.
*/
function removeNode(id) {
if (currentResponder.id === id) {
terminateResponder();
}
if (responderListenersMap.has(id)) {
responderListenersMap.delete(id);
}
}
/**
* Allow the current responder to be terminated from within components to support
* more complex requirements, such as use with other React libraries for working
* with scroll views, input views, etc.
*/
function terminateResponder() {
var _currentResponder3 = currentResponder,
id = _currentResponder3.id,
node = _currentResponder3.node;
if (id != null && node != null) {
var _getResponderConfig4 = getResponderConfig(id),
onResponderTerminate = _getResponderConfig4.onResponderTerminate;
if (onResponderTerminate != null) {
var event = (0, _createResponderEvent.default)({});
event.currentTarget = node;
onResponderTerminate(event);
}
changeCurrentResponder(emptyResponder);
}
isEmulatingMouseEvents = false;
trackedTouchCount = 0;
}
/**
* Allow unit tests to inspect the current responder in the system.
* FOR TESTING ONLY.
*/
function getResponderNode() {
return currentResponder.node;
}

View File

@ -0,0 +1,196 @@
"use strict";
exports.__esModule = true;
exports.default = void 0;
var _ResponderEventTypes = require("./ResponderEventTypes");
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
/**
* Tracks the position and time of each active touch by `touch.identifier`. We
* should typically only see IDs in the range of 1-20 because IDs get recycled
* when touches end and start again.
*/
var __DEV__ = process.env.NODE_ENV !== 'production';
var MAX_TOUCH_BANK = 20;
var touchBank = [];
var touchHistory = {
touchBank: touchBank,
numberActiveTouches: 0,
// If there is only one active touch, we remember its location. This prevents
// us having to loop through all of the touches all the time in the most
// common case.
indexOfSingleActiveTouch: -1,
mostRecentTimeStamp: 0
};
function timestampForTouch(touch) {
// The legacy internal implementation provides "timeStamp", which has been
// renamed to "timestamp".
return touch.timeStamp || touch.timestamp;
}
/**
* TODO: Instead of making gestures recompute filtered velocity, we could
* include a built in velocity computation that can be reused globally.
*/
function createTouchRecord(touch) {
return {
touchActive: true,
startPageX: touch.pageX,
startPageY: touch.pageY,
startTimeStamp: timestampForTouch(touch),
currentPageX: touch.pageX,
currentPageY: touch.pageY,
currentTimeStamp: timestampForTouch(touch),
previousPageX: touch.pageX,
previousPageY: touch.pageY,
previousTimeStamp: timestampForTouch(touch)
};
}
function resetTouchRecord(touchRecord, touch) {
touchRecord.touchActive = true;
touchRecord.startPageX = touch.pageX;
touchRecord.startPageY = touch.pageY;
touchRecord.startTimeStamp = timestampForTouch(touch);
touchRecord.currentPageX = touch.pageX;
touchRecord.currentPageY = touch.pageY;
touchRecord.currentTimeStamp = timestampForTouch(touch);
touchRecord.previousPageX = touch.pageX;
touchRecord.previousPageY = touch.pageY;
touchRecord.previousTimeStamp = timestampForTouch(touch);
}
function getTouchIdentifier(_ref) {
var identifier = _ref.identifier;
if (identifier == null) {
console.error('Touch object is missing identifier.');
}
if (__DEV__) {
if (identifier > MAX_TOUCH_BANK) {
console.error('Touch identifier %s is greater than maximum supported %s which causes ' + 'performance issues backfilling array locations for all of the indices.', identifier, MAX_TOUCH_BANK);
}
}
return identifier;
}
function recordTouchStart(touch) {
var identifier = getTouchIdentifier(touch);
var touchRecord = touchBank[identifier];
if (touchRecord) {
resetTouchRecord(touchRecord, touch);
} else {
touchBank[identifier] = createTouchRecord(touch);
}
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
}
function recordTouchMove(touch) {
var touchRecord = touchBank[getTouchIdentifier(touch)];
if (touchRecord) {
touchRecord.touchActive = true;
touchRecord.previousPageX = touchRecord.currentPageX;
touchRecord.previousPageY = touchRecord.currentPageY;
touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
touchRecord.currentPageX = touch.pageX;
touchRecord.currentPageY = touch.pageY;
touchRecord.currentTimeStamp = timestampForTouch(touch);
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
} else {
console.warn('Cannot record touch move without a touch start.\n', "Touch Move: " + printTouch(touch) + "\n", "Touch Bank: " + printTouchBank());
}
}
function recordTouchEnd(touch) {
var touchRecord = touchBank[getTouchIdentifier(touch)];
if (touchRecord) {
touchRecord.touchActive = false;
touchRecord.previousPageX = touchRecord.currentPageX;
touchRecord.previousPageY = touchRecord.currentPageY;
touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
touchRecord.currentPageX = touch.pageX;
touchRecord.currentPageY = touch.pageY;
touchRecord.currentTimeStamp = timestampForTouch(touch);
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
} else {
console.warn('Cannot record touch end without a touch start.\n', "Touch End: " + printTouch(touch) + "\n", "Touch Bank: " + printTouchBank());
}
}
function printTouch(touch) {
return JSON.stringify({
identifier: touch.identifier,
pageX: touch.pageX,
pageY: touch.pageY,
timestamp: timestampForTouch(touch)
});
}
function printTouchBank() {
var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));
if (touchBank.length > MAX_TOUCH_BANK) {
printed += ' (original size: ' + touchBank.length + ')';
}
return printed;
}
var ResponderTouchHistoryStore = {
recordTouchTrack: function recordTouchTrack(topLevelType, nativeEvent) {
if ((0, _ResponderEventTypes.isMoveish)(topLevelType)) {
nativeEvent.changedTouches.forEach(recordTouchMove);
} else if ((0, _ResponderEventTypes.isStartish)(topLevelType)) {
nativeEvent.changedTouches.forEach(recordTouchStart);
touchHistory.numberActiveTouches = nativeEvent.touches.length;
if (touchHistory.numberActiveTouches === 1) {
touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier;
}
} else if ((0, _ResponderEventTypes.isEndish)(topLevelType)) {
nativeEvent.changedTouches.forEach(recordTouchEnd);
touchHistory.numberActiveTouches = nativeEvent.touches.length;
if (touchHistory.numberActiveTouches === 1) {
for (var i = 0; i < touchBank.length; i++) {
var touchTrackToCheck = touchBank[i];
if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
touchHistory.indexOfSingleActiveTouch = i;
break;
}
}
if (__DEV__) {
var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch];
if (!(activeRecord != null && activeRecord.touchActive)) {
console.error('Cannot find single active touch.');
}
}
}
}
},
touchHistory: touchHistory
};
var _default = ResponderTouchHistoryStore;
exports.default = _default;
module.exports = exports.default;

View File

@ -0,0 +1,174 @@
"use strict";
exports.__esModule = true;
exports.default = createResponderEvent;
var _getBoundingClientRect = _interopRequireDefault(require("../../modules/getBoundingClientRect"));
var _ResponderTouchHistoryStore = _interopRequireDefault(require("./ResponderTouchHistoryStore"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright (c) Nicolas Gallagher
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
var emptyFunction = function emptyFunction() {};
var emptyObject = {};
var emptyArray = [];
/**
* Safari produces very large identifiers that would cause the `touchBank` array
* length to be so large as to crash the browser, if not normalized like this.
* In the future the `touchBank` should use an object/map instead.
*/
function normalizeIdentifier(identifier) {
return identifier > 20 ? identifier % 20 : identifier;
}
/**
* Converts a native DOM event to a ResponderEvent.
* Mouse events are transformed into fake touch events.
*/
function createResponderEvent(domEvent) {
var rect;
var propagationWasStopped = false;
var changedTouches;
var touches;
var domEventChangedTouches = domEvent.changedTouches;
var domEventType = domEvent.type;
var metaKey = domEvent.metaKey === true;
var shiftKey = domEvent.shiftKey === true;
var force = domEventChangedTouches && domEventChangedTouches[0].force || 0;
var identifier = normalizeIdentifier(domEventChangedTouches && domEventChangedTouches[0].identifier || 0);
var clientX = domEventChangedTouches && domEventChangedTouches[0].clientX || domEvent.clientX;
var clientY = domEventChangedTouches && domEventChangedTouches[0].clientY || domEvent.clientY;
var pageX = domEventChangedTouches && domEventChangedTouches[0].pageX || domEvent.pageX;
var pageY = domEventChangedTouches && domEventChangedTouches[0].pageY || domEvent.pageY;
var preventDefault = typeof domEvent.preventDefault === 'function' ? domEvent.preventDefault.bind(domEvent) : emptyFunction;
var timestamp = domEvent.timeStamp;
function normalizeTouches(touches) {
return Array.prototype.slice.call(touches).map(function (touch) {
return {
force: touch.force,
identifier: normalizeIdentifier(touch.identifier),
get locationX() {
return locationX(touch.clientX);
},
get locationY() {
return locationY(touch.clientY);
},
pageX: touch.pageX,
pageY: touch.pageY,
target: touch.target,
timestamp: timestamp
};
});
}
if (domEventChangedTouches != null) {
changedTouches = normalizeTouches(domEventChangedTouches);
touches = normalizeTouches(domEvent.touches);
} else {
var emulatedTouches = [{
force: force,
identifier: identifier,
get locationX() {
return locationX(clientX);
},
get locationY() {
return locationY(clientY);
},
pageX: pageX,
pageY: pageY,
target: domEvent.target,
timestamp: timestamp
}];
changedTouches = emulatedTouches;
touches = domEventType === 'mouseup' || domEventType === 'dragstart' ? emptyArray : emulatedTouches;
}
var responderEvent = {
bubbles: true,
cancelable: true,
// `currentTarget` is set before dispatch
currentTarget: null,
defaultPrevented: domEvent.defaultPrevented,
dispatchConfig: emptyObject,
eventPhase: domEvent.eventPhase,
isDefaultPrevented: function isDefaultPrevented() {
return domEvent.defaultPrevented;
},
isPropagationStopped: function isPropagationStopped() {
return propagationWasStopped;
},
isTrusted: domEvent.isTrusted,
nativeEvent: {
altKey: false,
ctrlKey: false,
metaKey: metaKey,
shiftKey: shiftKey,
changedTouches: changedTouches,
force: force,
identifier: identifier,
get locationX() {
return locationX(clientX);
},
get locationY() {
return locationY(clientY);
},
pageX: pageX,
pageY: pageY,
target: domEvent.target,
timestamp: timestamp,
touches: touches,
type: domEventType
},
persist: emptyFunction,
preventDefault: preventDefault,
stopPropagation: function stopPropagation() {
propagationWasStopped = true;
},
target: domEvent.target,
timeStamp: timestamp,
touchHistory: _ResponderTouchHistoryStore.default.touchHistory
}; // Using getters and functions serves two purposes:
// 1) The value of `currentTarget` is not initially available.
// 2) Measuring the clientRect may cause layout jank and should only be done on-demand.
function locationX(x) {
rect = rect || (0, _getBoundingClientRect.default)(responderEvent.currentTarget);
if (rect) {
return x - rect.left;
}
}
function locationY(y) {
rect = rect || (0, _getBoundingClientRect.default)(responderEvent.currentTarget);
if (rect) {
return y - rect.top;
}
}
return responderEvent;
}
module.exports = exports.default;

View File

@ -0,0 +1,91 @@
"use strict";
exports.__esModule = true;
exports.default = useResponderEvents;
var React = _interopRequireWildcard(require("react"));
var ResponderSystem = _interopRequireWildcard(require("./ResponderSystem"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* Copyright (c) Nicolas Gallagher
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
/**
* Hook for integrating the Responder System into React
*
* function SomeComponent({ onStartShouldSetResponder }) {
* const ref = useRef(null);
* useResponderEvents(ref, { onStartShouldSetResponder });
* return <div ref={ref} />
* }
*/
var emptyObject = {};
var idCounter = 0;
function useStable(getInitialValue) {
var ref = React.useRef(null);
if (ref.current == null) {
ref.current = getInitialValue();
}
return ref.current;
}
function useResponderEvents(hostRef, config) {
if (config === void 0) {
config = emptyObject;
}
var id = useStable(function () {
return idCounter++;
});
var isAttachedRef = React.useRef(false); // This is a separate effects so it doesn't run when the config changes.
// On initial mount, attach global listeners if needed.
// On unmount, remove node potentially attached to the Responder System.
React.useEffect(function () {
ResponderSystem.attachListeners();
return function () {
ResponderSystem.removeNode(id);
};
}, [id]); // Register and unregister with the Responder System as necessary
React.useEffect(function () {
var _config = config,
onMoveShouldSetResponder = _config.onMoveShouldSetResponder,
onMoveShouldSetResponderCapture = _config.onMoveShouldSetResponderCapture,
onScrollShouldSetResponder = _config.onScrollShouldSetResponder,
onScrollShouldSetResponderCapture = _config.onScrollShouldSetResponderCapture,
onSelectionChangeShouldSetResponder = _config.onSelectionChangeShouldSetResponder,
onSelectionChangeShouldSetResponderCapture = _config.onSelectionChangeShouldSetResponderCapture,
onStartShouldSetResponder = _config.onStartShouldSetResponder,
onStartShouldSetResponderCapture = _config.onStartShouldSetResponderCapture;
var requiresResponderSystem = onMoveShouldSetResponder != null || onMoveShouldSetResponderCapture != null || onScrollShouldSetResponder != null || onScrollShouldSetResponderCapture != null || onSelectionChangeShouldSetResponder != null || onSelectionChangeShouldSetResponderCapture != null || onStartShouldSetResponder != null || onStartShouldSetResponderCapture != null;
var node = hostRef.current;
if (requiresResponderSystem) {
ResponderSystem.addNode(id, node, config);
isAttachedRef.current = true;
} else if (isAttachedRef.current) {
ResponderSystem.removeNode(id);
isAttachedRef.current = false;
}
}, [config, hostRef, id]);
React.useDebugValue({
isResponder: hostRef.current === ResponderSystem.getResponderNode()
});
React.useDebugValue(config);
}
module.exports = exports.default;

View File

@ -0,0 +1,200 @@
"use strict";
exports.__esModule = true;
exports.setResponderId = setResponderId;
exports.getResponderPaths = getResponderPaths;
exports.getLowestCommonAncestor = getLowestCommonAncestor;
exports.hasTargetTouches = hasTargetTouches;
exports.hasValidSelection = hasValidSelection;
exports.isPrimaryPointerDown = isPrimaryPointerDown;
var _isSelectionValid = _interopRequireDefault(require("../../modules/isSelectionValid"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright (c) Nicolas Gallagher
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
var keyName = '__reactResponderId';
function getEventPath(domEvent) {
// The 'selectionchange' event always has the 'document' as the target.
// Use the anchor node as the initial target to reconstruct a path.
// (We actually only need the first "responder" node in practice.)
if (domEvent.type === 'selectionchange') {
var target = window.getSelection().anchorNode;
return composedPathFallback(target);
} else {
var path = domEvent.composedPath != null ? domEvent.composedPath() : composedPathFallback(domEvent.target);
return path;
}
}
function composedPathFallback(target) {
var path = [];
while (target != null && target !== document.body) {
path.push(target);
target = target.parentNode;
}
return path;
}
/**
* Retrieve the responderId from a host node
*/
function getResponderId(node) {
if (node != null) {
return node[keyName];
}
return null;
}
/**
* Store the responderId on a host node
*/
function setResponderId(node, id) {
if (node != null) {
node[keyName] = id;
}
}
/**
* Filter the event path to contain only the nodes attached to the responder system
*/
function getResponderPaths(domEvent) {
var idPath = [];
var nodePath = [];
var eventPath = getEventPath(domEvent);
for (var i = 0; i < eventPath.length; i++) {
var node = eventPath[i];
var id = getResponderId(node);
if (id != null) {
idPath.push(id);
nodePath.push(node);
}
}
return {
idPath: idPath,
nodePath: nodePath
};
}
/**
* Walk the paths and find the first common ancestor
*/
function getLowestCommonAncestor(pathA, pathB) {
var pathALength = pathA.length;
var pathBLength = pathB.length;
if ( // If either path is empty
pathALength === 0 || pathBLength === 0 || // If the last elements aren't the same there can't be a common ancestor
// that is connected to the responder system
pathA[pathALength - 1] !== pathB[pathBLength - 1]) {
return null;
}
var itemA = pathA[0];
var indexA = 0;
var itemB = pathB[0];
var indexB = 0; // If A is deeper, skip indices that can't match.
if (pathALength - pathBLength > 0) {
indexA = pathALength - pathBLength;
itemA = pathA[indexA];
pathALength = pathBLength;
} // If B is deeper, skip indices that can't match
if (pathBLength - pathALength > 0) {
indexB = pathBLength - pathALength;
itemB = pathB[indexB];
pathBLength = pathALength;
} // Walk in lockstep until a match is found
var depth = pathALength;
while (depth--) {
if (itemA === itemB) {
return itemA;
}
itemA = pathA[indexA++];
itemB = pathB[indexB++];
}
return null;
}
/**
* Determine whether any of the active touches are within the current responder.
* This cannot rely on W3C `targetTouches`, as neither IE11 nor Safari implement it.
*/
function hasTargetTouches(target, touches) {
if (!touches || touches.length === 0) {
return false;
}
for (var i = 0; i < touches.length; i++) {
var node = touches[i].target;
if (node != null) {
if (target.contains(node)) {
return true;
}
}
}
return false;
}
/**
* Ignore 'selectionchange' events that don't correspond with a person's intent to
* select text.
*/
function hasValidSelection(domEvent) {
if (domEvent.type === 'selectionchange') {
return (0, _isSelectionValid.default)();
}
return domEvent.type === 'select';
}
/**
* Events are only valid if the primary button was used without specific modifier keys.
*/
function isPrimaryPointerDown(domEvent) {
var altKey = domEvent.altKey,
button = domEvent.button,
buttons = domEvent.buttons,
ctrlKey = domEvent.ctrlKey,
type = domEvent.type;
var isTouch = type === 'touchstart' || type === 'touchmove';
var isPrimaryMouseDown = type === 'mousedown' && (button === 0 || buttons === 1);
var isPrimaryMouseMove = type === 'mousemove' && buttons === 1;
var noModifiers = altKey === false && ctrlKey === false;
if (isTouch || isPrimaryMouseDown && noModifiers || isPrimaryMouseMove && noModifiers) {
return true;
}
return false;
}