UNPKG

26.4 kBJavaScriptView Raw
1var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
2
3var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4
5function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
7function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
8
9function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
10
11// inspired by react-native
12import React from 'react';
13import ReactDOM from 'react-dom';
14import PressEvent, { shouldFirePress } from './PressEvent';
15function keyMirror(obj) {
16 Object.keys(obj).forEach(function (k) {
17 return obj[k] = k;
18 });
19 return obj;
20}
21function copy(from, list) {
22 var to = {};
23 list.forEach(function (k) {
24 to[k] = from[k];
25 });
26 return to;
27}
28function extractSingleTouch(_nativeEvent) {
29 var nativeEvent = _nativeEvent;
30 if (nativeEvent.nativeEvent) {
31 nativeEvent = nativeEvent.nativeEvent;
32 }
33 var touches = nativeEvent.touches;
34 var changedTouches = nativeEvent.changedTouches;
35 var hasTouches = touches && touches.length > 0;
36 var hasChangedTouches = changedTouches && changedTouches.length > 0;
37 return !hasTouches && hasChangedTouches ? changedTouches[0] : hasTouches ? touches[0] : nativeEvent;
38}
39/**
40 * Touchable states.
41 */
42var States = keyMirror({
43 NOT_RESPONDER: null,
44 RESPONDER_INACTIVE_PRESS_IN: null,
45 RESPONDER_INACTIVE_PRESS_OUT: null,
46 RESPONDER_ACTIVE_PRESS_IN: null,
47 RESPONDER_ACTIVE_PRESS_OUT: null,
48 RESPONDER_ACTIVE_LONG_PRESS_IN: null,
49 RESPONDER_ACTIVE_LONG_PRESS_OUT: null,
50 ERROR: null
51});
52/**
53 * Quick lookup map for states that are considered to be "active"
54 */
55var IsActive = {
56 RESPONDER_ACTIVE_PRESS_OUT: true,
57 RESPONDER_ACTIVE_PRESS_IN: true
58};
59/**
60 * Quick lookup for states that are considered to be "pressing" and are
61 * therefore eligible to result in a "selection" if the press stops.
62 */
63var IsPressingIn = {
64 RESPONDER_INACTIVE_PRESS_IN: true,
65 RESPONDER_ACTIVE_PRESS_IN: true,
66 RESPONDER_ACTIVE_LONG_PRESS_IN: true
67};
68var IsLongPressingIn = {
69 RESPONDER_ACTIVE_LONG_PRESS_IN: true
70};
71/**
72 * Inputs to the state machine.
73 */
74var Signals = keyMirror({
75 DELAY: null,
76 RESPONDER_GRANT: null,
77 RESPONDER_RELEASE: null,
78 RESPONDER_TERMINATED: null,
79 ENTER_PRESS_RECT: null,
80 LEAVE_PRESS_RECT: null,
81 LONG_PRESS_DETECTED: null
82});
83/**
84 * Mapping from States x Signals => States
85 */
86var Transitions = {
87 NOT_RESPONDER: {
88 DELAY: States.ERROR,
89 RESPONDER_GRANT: States.RESPONDER_INACTIVE_PRESS_IN,
90 RESPONDER_RELEASE: States.ERROR,
91 RESPONDER_TERMINATED: States.ERROR,
92 ENTER_PRESS_RECT: States.ERROR,
93 LEAVE_PRESS_RECT: States.ERROR,
94 LONG_PRESS_DETECTED: States.ERROR
95 },
96 RESPONDER_INACTIVE_PRESS_IN: {
97 DELAY: States.RESPONDER_ACTIVE_PRESS_IN,
98 RESPONDER_GRANT: States.ERROR,
99 RESPONDER_RELEASE: States.NOT_RESPONDER,
100 RESPONDER_TERMINATED: States.NOT_RESPONDER,
101 ENTER_PRESS_RECT: States.RESPONDER_INACTIVE_PRESS_IN,
102 LEAVE_PRESS_RECT: States.RESPONDER_INACTIVE_PRESS_OUT,
103 LONG_PRESS_DETECTED: States.ERROR
104 },
105 RESPONDER_INACTIVE_PRESS_OUT: {
106 DELAY: States.RESPONDER_ACTIVE_PRESS_OUT,
107 RESPONDER_GRANT: States.ERROR,
108 RESPONDER_RELEASE: States.NOT_RESPONDER,
109 RESPONDER_TERMINATED: States.NOT_RESPONDER,
110 ENTER_PRESS_RECT: States.RESPONDER_INACTIVE_PRESS_IN,
111 LEAVE_PRESS_RECT: States.RESPONDER_INACTIVE_PRESS_OUT,
112 LONG_PRESS_DETECTED: States.ERROR
113 },
114 RESPONDER_ACTIVE_PRESS_IN: {
115 DELAY: States.ERROR,
116 RESPONDER_GRANT: States.ERROR,
117 RESPONDER_RELEASE: States.NOT_RESPONDER,
118 RESPONDER_TERMINATED: States.NOT_RESPONDER,
119 ENTER_PRESS_RECT: States.RESPONDER_ACTIVE_PRESS_IN,
120 LEAVE_PRESS_RECT: States.RESPONDER_ACTIVE_PRESS_OUT,
121 LONG_PRESS_DETECTED: States.RESPONDER_ACTIVE_LONG_PRESS_IN
122 },
123 RESPONDER_ACTIVE_PRESS_OUT: {
124 DELAY: States.ERROR,
125 RESPONDER_GRANT: States.ERROR,
126 RESPONDER_RELEASE: States.NOT_RESPONDER,
127 RESPONDER_TERMINATED: States.NOT_RESPONDER,
128 ENTER_PRESS_RECT: States.RESPONDER_ACTIVE_PRESS_IN,
129 LEAVE_PRESS_RECT: States.RESPONDER_ACTIVE_PRESS_OUT,
130 LONG_PRESS_DETECTED: States.ERROR
131 },
132 RESPONDER_ACTIVE_LONG_PRESS_IN: {
133 DELAY: States.ERROR,
134 RESPONDER_GRANT: States.ERROR,
135 RESPONDER_RELEASE: States.NOT_RESPONDER,
136 RESPONDER_TERMINATED: States.NOT_RESPONDER,
137 ENTER_PRESS_RECT: States.RESPONDER_ACTIVE_LONG_PRESS_IN,
138 LEAVE_PRESS_RECT: States.RESPONDER_ACTIVE_LONG_PRESS_OUT,
139 LONG_PRESS_DETECTED: States.RESPONDER_ACTIVE_LONG_PRESS_IN
140 },
141 RESPONDER_ACTIVE_LONG_PRESS_OUT: {
142 DELAY: States.ERROR,
143 RESPONDER_GRANT: States.ERROR,
144 RESPONDER_RELEASE: States.NOT_RESPONDER,
145 RESPONDER_TERMINATED: States.NOT_RESPONDER,
146 ENTER_PRESS_RECT: States.RESPONDER_ACTIVE_LONG_PRESS_IN,
147 LEAVE_PRESS_RECT: States.RESPONDER_ACTIVE_LONG_PRESS_OUT,
148 LONG_PRESS_DETECTED: States.ERROR
149 },
150 error: {
151 DELAY: States.NOT_RESPONDER,
152 RESPONDER_GRANT: States.RESPONDER_INACTIVE_PRESS_IN,
153 RESPONDER_RELEASE: States.NOT_RESPONDER,
154 RESPONDER_TERMINATED: States.NOT_RESPONDER,
155 ENTER_PRESS_RECT: States.NOT_RESPONDER,
156 LEAVE_PRESS_RECT: States.NOT_RESPONDER,
157 LONG_PRESS_DETECTED: States.NOT_RESPONDER
158 }
159};
160// ==== Typical Constants for integrating into UI components ====
161// const HIT_EXPAND_PX = 20;
162// const HIT_VERT_OFFSET_PX = 10;
163var HIGHLIGHT_DELAY_MS = 130;
164var PRESS_EXPAND_PX = 20;
165var LONG_PRESS_THRESHOLD = 500;
166var LONG_PRESS_DELAY_MS = LONG_PRESS_THRESHOLD - HIGHLIGHT_DELAY_MS;
167var LONG_PRESS_ALLOWED_MOVEMENT = 10;
168var lastClickTime = 0;
169var pressDelay = 200;
170function isAllowPress() {
171 // avoid click penetration
172 return Date.now() - lastClickTime >= pressDelay;
173}
174
175var Touchable = function (_React$Component) {
176 _inherits(Touchable, _React$Component);
177
178 function Touchable() {
179 _classCallCheck(this, Touchable);
180
181 var _this = _possibleConstructorReturn(this, (Touchable.__proto__ || Object.getPrototypeOf(Touchable)).apply(this, arguments));
182
183 _this.state = {
184 active: false
185 };
186 _this.touchable = { touchState: undefined };
187 _this.onTouchStart = function (e) {
188 _this.callChildEvent('onTouchStart', e);
189 _this.lockMouse = true;
190 if (_this.releaseLockTimer) {
191 clearTimeout(_this.releaseLockTimer);
192 }
193 _this.touchableHandleResponderGrant(e.nativeEvent);
194 };
195 _this.onTouchMove = function (e) {
196 _this.callChildEvent('onTouchMove', e);
197 _this.touchableHandleResponderMove(e.nativeEvent);
198 };
199 _this.onTouchEnd = function (e) {
200 _this.callChildEvent('onTouchEnd', e);
201 _this.releaseLockTimer = setTimeout(function () {
202 _this.lockMouse = false;
203 }, 300);
204 _this.touchableHandleResponderRelease(new PressEvent(e.nativeEvent));
205 };
206 _this.onTouchCancel = function (e) {
207 _this.callChildEvent('onTouchCancel', e);
208 _this.releaseLockTimer = setTimeout(function () {
209 _this.lockMouse = false;
210 }, 300);
211 _this.touchableHandleResponderTerminate(e.nativeEvent);
212 };
213 _this.onMouseDown = function (e) {
214 _this.callChildEvent('onMouseDown', e);
215 if (_this.lockMouse) {
216 return;
217 }
218 _this.touchableHandleResponderGrant(e.nativeEvent);
219 document.addEventListener('mousemove', _this.touchableHandleResponderMove, false);
220 document.addEventListener('mouseup', _this.onMouseUp, false);
221 };
222 _this.onMouseUp = function (e) {
223 document.removeEventListener('mousemove', _this.touchableHandleResponderMove, false);
224 document.removeEventListener('mouseup', _this.onMouseUp, false);
225 _this.touchableHandleResponderRelease(new PressEvent(e));
226 };
227 _this.touchableHandleResponderMove = function (e) {
228 if (!_this.touchable.startMouse) {
229 return;
230 }
231 // Measurement may not have returned yet.
232 if (!_this.touchable.dimensionsOnActivate || _this.touchable.touchState === States.NOT_RESPONDER) {
233 return;
234 }
235 // Not enough time elapsed yet, wait for highlight -
236 // this is just a perf optimization.
237 if (_this.touchable.touchState === States.RESPONDER_INACTIVE_PRESS_IN) {
238 return;
239 }
240 var touch = extractSingleTouch(e);
241 var pageX = touch && touch.pageX;
242 var pageY = touch && touch.pageY;
243 if (_this.pressInLocation) {
244 var movedDistance = _this._getDistanceBetweenPoints(pageX, pageY, _this.pressInLocation.pageX, _this.pressInLocation.pageY);
245 if (movedDistance > LONG_PRESS_ALLOWED_MOVEMENT) {
246 _this._cancelLongPressDelayTimeout();
247 }
248 }
249 if (_this.checkTouchWithinActive(e)) {
250 _this._receiveSignal(Signals.ENTER_PRESS_RECT, e);
251 var curState = _this.touchable.touchState;
252 if (curState === States.RESPONDER_INACTIVE_PRESS_IN) {
253 _this._cancelLongPressDelayTimeout();
254 }
255 } else {
256 _this._cancelLongPressDelayTimeout();
257 _this._receiveSignal(Signals.LEAVE_PRESS_RECT, e);
258 }
259 };
260 return _this;
261 }
262
263 _createClass(Touchable, [{
264 key: 'componentDidMount',
265 value: function componentDidMount() {
266 this.root = ReactDOM.findDOMNode(this);
267 }
268 }, {
269 key: 'componentDidUpdate',
270 value: function componentDidUpdate() {
271 this.root = ReactDOM.findDOMNode(this);
272 // disabled auto clear active state
273 if (this.props.disabled && this.state.active) {
274 this.setState({
275 active: false
276 });
277 }
278 }
279 }, {
280 key: 'componentWillUnmount',
281 value: function componentWillUnmount() {
282 if (this.releaseLockTimer) {
283 clearTimeout(this.releaseLockTimer);
284 }
285 if (this.touchableDelayTimeout) {
286 clearTimeout(this.touchableDelayTimeout);
287 }
288 if (this.longPressDelayTimeout) {
289 clearTimeout(this.longPressDelayTimeout);
290 }
291 if (this.pressOutDelayTimeout) {
292 clearTimeout(this.pressOutDelayTimeout);
293 }
294 }
295 }, {
296 key: 'callChildEvent',
297 value: function callChildEvent(event, e) {
298 var childHandle = React.Children.only(this.props.children).props[event];
299 if (childHandle) {
300 childHandle(e);
301 }
302 }
303 }, {
304 key: '_remeasureMetricsOnInit',
305 value: function _remeasureMetricsOnInit(e) {
306 var root = this.root;
307
308 var touch = extractSingleTouch(e);
309 var boundingRect = root.getBoundingClientRect();
310 this.touchable = {
311 touchState: this.touchable.touchState,
312 startMouse: {
313 pageX: touch.pageX,
314 pageY: touch.pageY
315 },
316 positionOnGrant: {
317 left: boundingRect.left + window.pageXOffset,
318 top: boundingRect.top + window.pageYOffset,
319 width: boundingRect.width,
320 height: boundingRect.height,
321 clientLeft: boundingRect.left,
322 clientTop: boundingRect.top
323 }
324 };
325 }
326 }, {
327 key: 'processActiveStopPropagation',
328 value: function processActiveStopPropagation(e) {
329 var nativeEvent = e.nativeEvent || e;
330 this.shouldActive = !nativeEvent.__activeStopPropagation;
331 if (this.props.activeStopPropagation) {
332 nativeEvent.__activeStopPropagation = 1;
333 }
334 }
335 }, {
336 key: 'touchableHandleResponderGrant',
337 value: function touchableHandleResponderGrant(e) {
338 var _this2 = this;
339
340 this.touchable.touchState = States.NOT_RESPONDER;
341 if (this.pressOutDelayTimeout) {
342 clearTimeout(this.pressOutDelayTimeout);
343 this.pressOutDelayTimeout = null;
344 }
345 if (this.props.fixClickPenetration && !isAllowPress()) {
346 return;
347 }
348 this._remeasureMetricsOnInit(e);
349 this._receiveSignal(Signals.RESPONDER_GRANT, e);
350 var _props = this.props,
351 delayMS = _props.delayPressIn,
352 longDelayMS = _props.delayLongPress;
353
354 this.processActiveStopPropagation(e);
355 if (delayMS) {
356 this.touchableDelayTimeout = setTimeout(function () {
357 _this2._handleDelay(e);
358 }, delayMS);
359 } else {
360 this._handleDelay(e);
361 }
362 var longPressEvent = new PressEvent(e);
363 this.longPressDelayTimeout = setTimeout(function () {
364 _this2._handleLongDelay(longPressEvent);
365 }, longDelayMS + delayMS);
366 }
367 }, {
368 key: 'checkScroll',
369 value: function checkScroll(e) {
370 var positionOnGrant = this.touchable.positionOnGrant;
371 // container or window scroll
372 var boundingRect = this.root.getBoundingClientRect();
373 if (boundingRect.left !== positionOnGrant.clientLeft || boundingRect.top !== positionOnGrant.clientTop) {
374 this._receiveSignal(Signals.RESPONDER_TERMINATED, e);
375 return true;
376 }
377 return false;
378 }
379 }, {
380 key: 'touchableHandleResponderRelease',
381 value: function touchableHandleResponderRelease(e) {
382 if (!this.touchable.startMouse) {
383 return;
384 }
385 var touch = extractSingleTouch(e);
386 if (Math.abs(touch.pageX - this.touchable.startMouse.pageX) > 30 || Math.abs(touch.pageY - this.touchable.startMouse.pageY) > 30) {
387 this._receiveSignal(Signals.RESPONDER_TERMINATED, e);
388 return;
389 }
390 if (this.checkScroll(e)) {
391 return;
392 }
393 this._receiveSignal(Signals.RESPONDER_RELEASE, e);
394 }
395 }, {
396 key: 'touchableHandleResponderTerminate',
397 value: function touchableHandleResponderTerminate(e) {
398 if (!this.touchable.startMouse) {
399 return;
400 }
401 this._receiveSignal(Signals.RESPONDER_TERMINATED, e);
402 }
403 }, {
404 key: 'checkTouchWithinActive',
405 value: function checkTouchWithinActive(e) {
406 var positionOnGrant = this.touchable.positionOnGrant;
407 var _props2 = this.props,
408 _props2$pressRetentio = _props2.pressRetentionOffset,
409 pressRetentionOffset = _props2$pressRetentio === undefined ? {} : _props2$pressRetentio,
410 hitSlop = _props2.hitSlop;
411
412 var pressExpandLeft = pressRetentionOffset.left;
413 var pressExpandTop = pressRetentionOffset.top;
414 var pressExpandRight = pressRetentionOffset.right;
415 var pressExpandBottom = pressRetentionOffset.bottom;
416 if (hitSlop) {
417 pressExpandLeft += hitSlop.left;
418 pressExpandTop += hitSlop.top;
419 pressExpandRight += hitSlop.right;
420 pressExpandBottom += hitSlop.bottom;
421 }
422 var touch = extractSingleTouch(e);
423 var pageX = touch && touch.pageX;
424 var pageY = touch && touch.pageY;
425 return pageX > positionOnGrant.left - pressExpandLeft && pageY > positionOnGrant.top - pressExpandTop && pageX < positionOnGrant.left + positionOnGrant.width + pressExpandRight && pageY < positionOnGrant.top + positionOnGrant.height + pressExpandBottom;
426 }
427 }, {
428 key: 'callProp',
429 value: function callProp(name, e) {
430 if (this.props[name] && !this.props.disabled) {
431 this.props[name](e);
432 }
433 }
434 }, {
435 key: 'touchableHandleActivePressIn',
436 value: function touchableHandleActivePressIn(e) {
437 if (this.shouldActive) {
438 this.setActive(true);
439 }
440 this.callProp('onPressIn', e);
441 }
442 }, {
443 key: 'touchableHandleActivePressOut',
444 value: function touchableHandleActivePressOut(e) {
445 this.setActive(false);
446 this.callProp('onPressOut', e);
447 }
448 }, {
449 key: 'touchableHandlePress',
450 value: function touchableHandlePress(e) {
451 if (shouldFirePress(e)) {
452 this.callProp('onPress', e);
453 }
454 lastClickTime = Date.now();
455 }
456 }, {
457 key: 'touchableHandleLongPress',
458 value: function touchableHandleLongPress(e) {
459 if (shouldFirePress(e)) {
460 this.callProp('onLongPress', e);
461 }
462 }
463 }, {
464 key: 'setActive',
465 value: function setActive(active) {
466 if (this.state.active !== active && (this.props.activeClassName || this.props.activeStyle)) {
467 this.setState({
468 active: active
469 });
470 }
471 }
472 }, {
473 key: '_remeasureMetricsOnActivation',
474 value: function _remeasureMetricsOnActivation() {
475 this.touchable.dimensionsOnActivate = this.touchable.positionOnGrant;
476 }
477 }, {
478 key: '_handleDelay',
479 value: function _handleDelay(e) {
480 this.touchableDelayTimeout = null;
481 this._receiveSignal(Signals.DELAY, e);
482 }
483 }, {
484 key: '_handleLongDelay',
485 value: function _handleLongDelay(e) {
486 this.longPressDelayTimeout = null;
487 var curState = this.touchable.touchState;
488 if (curState !== States.RESPONDER_ACTIVE_PRESS_IN && curState !== States.RESPONDER_ACTIVE_LONG_PRESS_IN) {
489 console.error('Attempted to transition from state `' + curState + '` to `' + States.RESPONDER_ACTIVE_LONG_PRESS_IN + '`, which is not supported. This is ' + 'most likely due to `Touchable.longPressDelayTimeout` not being cancelled.');
490 } else {
491 this._receiveSignal(Signals.LONG_PRESS_DETECTED, e);
492 }
493 }
494 }, {
495 key: '_receiveSignal',
496 value: function _receiveSignal(signal, e) {
497 var curState = this.touchable.touchState;
498 var nextState = Transitions[curState] && Transitions[curState][signal];
499 if (!nextState) {
500 return;
501 }
502 if (nextState === States.ERROR) {
503 return;
504 }
505 if (curState !== nextState) {
506 this._performSideEffectsForTransition(curState, nextState, signal, e);
507 this.touchable.touchState = nextState;
508 }
509 }
510 }, {
511 key: '_cancelLongPressDelayTimeout',
512 value: function _cancelLongPressDelayTimeout() {
513 if (this.longPressDelayTimeout) {
514 clearTimeout(this.longPressDelayTimeout);
515 this.longPressDelayTimeout = null;
516 }
517 }
518 }, {
519 key: '_isHighlight',
520 value: function _isHighlight(state) {
521 return state === States.RESPONDER_ACTIVE_PRESS_IN || state === States.RESPONDER_ACTIVE_LONG_PRESS_IN;
522 }
523 }, {
524 key: '_savePressInLocation',
525 value: function _savePressInLocation(e) {
526 var touch = extractSingleTouch(e);
527 var pageX = touch && touch.pageX;
528 var pageY = touch && touch.pageY;
529 this.pressInLocation = { pageX: pageX, pageY: pageY };
530 }
531 }, {
532 key: '_getDistanceBetweenPoints',
533 value: function _getDistanceBetweenPoints(aX, aY, bX, bY) {
534 var deltaX = aX - bX;
535 var deltaY = aY - bY;
536 return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
537 }
538 }, {
539 key: '_performSideEffectsForTransition',
540 value: function _performSideEffectsForTransition(curState, nextState, signal, e) {
541 var curIsHighlight = this._isHighlight(curState);
542 var newIsHighlight = this._isHighlight(nextState);
543 var isFinalSignal = signal === Signals.RESPONDER_TERMINATED || signal === Signals.RESPONDER_RELEASE;
544 if (isFinalSignal) {
545 this._cancelLongPressDelayTimeout();
546 }
547 if (!IsActive[curState] && IsActive[nextState]) {
548 this._remeasureMetricsOnActivation();
549 }
550 if (IsPressingIn[curState] && signal === Signals.LONG_PRESS_DETECTED) {
551 this.touchableHandleLongPress(e);
552 }
553 if (newIsHighlight && !curIsHighlight) {
554 this._startHighlight(e);
555 } else if (!newIsHighlight && curIsHighlight) {
556 this._endHighlight(e);
557 }
558 if (IsPressingIn[curState] && signal === Signals.RESPONDER_RELEASE) {
559 var hasLongPressHandler = !!this.props.onLongPress;
560 var pressIsLongButStillCallOnPress = IsLongPressingIn[curState] && ( // We *are* long pressing..
561 !hasLongPressHandler || // But either has no long handler
562 !this.props.longPressCancelsPress // or we're told to ignore it.
563 );
564 var shouldInvokePress = !IsLongPressingIn[curState] || pressIsLongButStillCallOnPress;
565 if (shouldInvokePress) {
566 if (!newIsHighlight && !curIsHighlight) {
567 // we never highlighted because of delay, but we should highlight now
568 this._startHighlight(e);
569 this._endHighlight(e);
570 }
571 this.touchableHandlePress(e);
572 }
573 }
574 if (this.touchableDelayTimeout) {
575 clearTimeout(this.touchableDelayTimeout);
576 this.touchableDelayTimeout = null;
577 }
578 }
579 }, {
580 key: '_startHighlight',
581 value: function _startHighlight(e) {
582 this._savePressInLocation(e);
583 this.touchableHandleActivePressIn(e);
584 }
585 }, {
586 key: '_endHighlight',
587 value: function _endHighlight(e) {
588 var _this3 = this;
589
590 if (this.props.delayPressOut) {
591 this.pressOutDelayTimeout = setTimeout(function () {
592 _this3.touchableHandleActivePressOut(e);
593 }, this.props.delayPressOut);
594 } else {
595 this.touchableHandleActivePressOut(e);
596 }
597 }
598 }, {
599 key: 'render',
600 value: function render() {
601 var _props3 = this.props,
602 children = _props3.children,
603 disabled = _props3.disabled,
604 activeStyle = _props3.activeStyle,
605 activeClassName = _props3.activeClassName;
606
607 var events = disabled ? undefined : copy(this, ['onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel', 'onMouseDown']);
608 var child = React.Children.only(children);
609 if (!disabled && this.state.active) {
610 var _child$props = child.props,
611 style = _child$props.style,
612 className = _child$props.className;
613
614 if (activeStyle) {
615 style = _extends({}, style, activeStyle);
616 }
617 if (activeClassName) {
618 if (className) {
619 className += ' ' + activeClassName;
620 } else {
621 className = activeClassName;
622 }
623 }
624 return React.cloneElement(child, _extends({ className: className,
625 style: style }, events));
626 }
627 return React.cloneElement(child, events);
628 }
629 }]);
630
631 return Touchable;
632}(React.Component);
633
634export default Touchable;
635
636Touchable.defaultProps = {
637 fixClickPenetration: false,
638 disabled: false,
639 delayPressIn: HIGHLIGHT_DELAY_MS,
640 delayLongPress: LONG_PRESS_DELAY_MS,
641 delayPressOut: 100,
642 pressRetentionOffset: {
643 left: PRESS_EXPAND_PX,
644 right: PRESS_EXPAND_PX,
645 top: PRESS_EXPAND_PX,
646 bottom: PRESS_EXPAND_PX
647 },
648 hitSlop: undefined,
649 longPressCancelsPress: true
650};
\No newline at end of file