From de14d19a050ec2aa03ead49e4371b73501b98adf Mon Sep 17 00:00:00 2001 From: Matt Colman Date: Wed, 21 Dec 2016 11:56:31 +1100 Subject: [PATCH] build --- dist/react-tappable.js | 37 +- dist/react-tappable.min.js | 2 +- example/dist/bundle.js | 37 +- example/dist/common.js | 33495 ++++++++++++++++++----------------- lib/TappableMixin.js | 41 +- 5 files changed, 16860 insertions(+), 16752 deletions(-) diff --git a/dist/react-tappable.js b/dist/react-tappable.js index c0136fb..20470ea 100644 --- a/dist/react-tappable.js +++ b/dist/react-tappable.js @@ -34,13 +34,19 @@ function getTouchProps(touch) { var Mixin = { propTypes: { moveThreshold: React.PropTypes.number, // pixels to move before cancelling tap + moveXThreshold: React.PropTypes.number, // pixels on the x axis to move before cancelling tap (overrides moveThreshold) + moveYThreshold: React.PropTypes.number, // pixels on the y axis to move before cancelling tap (overrides moveThreshold) activeDelay: React.PropTypes.number, // ms to wait before adding the `-active` class + allowReactivation: React.PropTypes.bool, // after moving outside of the moveThreshold will you allow + // reactivation by moving back within the moveThreshold? pressDelay: React.PropTypes.number, // ms to wait before detecting a press pressMoveThreshold: React.PropTypes.number, // pixels to move before cancelling press preventDefault: React.PropTypes.bool, // whether to preventDefault on all events stopPropagation: React.PropTypes.bool, // whether to stopPropagation on all events onTap: React.PropTypes.func, // fires when a tap is detected + onDeactivate: React.PropTypes.func, // fires when you move outside the moveThreshold + onReactivate: React.PropTypes.func, // fires when you move back within the moveThreshold onPress: React.PropTypes.func, // fires when a press is detected onTouchStart: React.PropTypes.func, // pass-through touch event onTouchMove: React.PropTypes.func, // pass-through touch event @@ -56,6 +62,7 @@ var Mixin = { getDefaultProps: function getDefaultProps() { return { activeDelay: 0, + allowReactivation: true, moveThreshold: 100, pressDelay: 1000, pressMoveThreshold: 5 @@ -76,28 +83,46 @@ var Mixin = { this.clearActiveTimeout(); }, + componentWillUpdate: function componentWillUpdate(nextProps, nextState) { + if (this.state.isActive && !nextState.isActive) { + this.props.onDeactivate && this.props.onDeactivate(); + } else if (!this.state.isActive && nextState.isActive) { + this.props.onReactivate && this.props.onReactivate(); + } + }, + processEvent: function processEvent(event) { if (this.props.preventDefault) event.preventDefault(); if (this.props.stopPropagation) event.stopPropagation(); }, onTouchStart: function onTouchStart(event) { + console.log('1'); if (this.props.onTouchStart && this.props.onTouchStart(event) === false) return; + console.log('2'); this.processEvent(event); window._blockMouseEvents = true; if (event.touches.length === 1) { + console.log('3'); this._initialTouch = this._lastTouch = getTouchProps(event.touches[0]); this.initScrollDetection(); this.initPressDetection(event, this.endTouch); this.initTouchmoveDetection(); - this._activeTimeout = setTimeout(this.makeActive, this.props.activeDelay); + console.log('setTimeout', this.props.activeDelay); + if (this.props.activeDelay === 0) { + this.makeActive(); + } else { + this._activeTimeout = setTimeout(this.makeActive, this.props.activeDelay); + } } else if (this.onPinchStart && (this.props.onPinchStart || this.props.onPinchMove || this.props.onPinchEnd) && event.touches.length === 2) { this.onPinchStart(event); } }, makeActive: function makeActive() { + console.log('makeActive'); if (!this.isMounted()) return; + console.log('really'); this.clearActiveTimeout(); this.setState({ isActive: true @@ -194,15 +219,19 @@ var Mixin = { if (movement.x > this.props.pressMoveThreshold || movement.y > this.props.pressMoveThreshold) { this.cancelPressDetection(); } - if (movement.x > this.props.moveThreshold || movement.y > this.props.moveThreshold) { + console.log('moving', movement.y); + if (movement.x > (this.props.moveThresholdX || this.props.moveThreshold) || movement.y > (this.props.moveThresholdY || this.props.moveThreshold)) { + console.log('a', this.state.isActive); if (this.state.isActive) { + console.log('d'); this.setState({ isActive: false }); } else if (this._activeTimeout) { this.clearActiveTimeout(); } - } else { + } else if (this.props.allowReactivation) { + console.log('b'); if (!this.state.isActive && !this._activeTimeout) { this.setState({ isActive: true @@ -222,7 +251,7 @@ var Mixin = { this.processEvent(event); var afterEndTouch; var movement = this.calculateMovement(this._lastTouch); - if (movement.x <= this.props.moveThreshold && movement.y <= this.props.moveThreshold && this.props.onTap) { + if (movement.x <= (this.props.moveThresholdX || this.props.moveThreshold) && movement.y <= (this.props.moveThresholdY || this.props.moveThreshold) && this.props.onTap) { event.preventDefault(); afterEndTouch = function () { var finalParentScrollPos = _this._scrollParents.map(function (node) { diff --git a/dist/react-tappable.min.js b/dist/react-tappable.min.js index 8583142..49fca4a 100644 --- a/dist/react-tappable.min.js +++ b/dist/react-tappable.min.js @@ -1 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Tappable=e()}}(function(){return function e(t,o,s){function n(c,r){if(!o[c]){if(!t[c]){var h="function"==typeof require&&require;if(!r&&h)return h(c,!0);if(i)return i(c,!0);var l=new Error("Cannot find module '"+c+"'");throw l.code="MODULE_NOT_FOUND",l}var u=o[c]={exports:{}};t[c][0].call(u.exports,function(e){var o=t[c][1][e];return n(o?o:e)},u,u.exports,e,t,o,s)}return o[c].exports}for(var i="function"==typeof require&&require,c=0;ce.offsetHeight||e.scrollWidth>e.offsetWidth)&&(this._scrollParents.push(e),this._scrollParentPos.push(e.scrollTop+e.scrollLeft),this._scrollPos.top+=e.scrollTop,this._scrollPos.left+=e.scrollLeft),e=e.parentNode},initTouchmoveDetection:function(){this._touchmoveTriggeredTimes=0},cancelTouchmoveDetection:function(){this._touchmoveDetectionTimeout&&(clearTimeout(this._touchmoveDetectionTimeout),this._touchmoveDetectionTimeout=null,this._touchmoveTriggeredTimes=0)},calculateMovement:function(e){return{x:Math.abs(e.clientX-this._initialTouch.clientX),y:Math.abs(e.clientY-this._initialTouch.clientY)}},detectScroll:function(){for(var e={top:0,left:0},t=0;tthis.props.pressMoveThreshold||t.y>this.props.pressMoveThreshold)&&this.cancelPressDetection(),t.x>this.props.moveThreshold||t.y>this.props.moveThreshold?this.state.isActive?this.setState({isActive:!1}):this._activeTimeout&&this.clearActiveTimeout():this.state.isActive||this._activeTimeout||this.setState({isActive:!0})}else this._initialPinch&&2===e.touches.length&&this.onPinchMove&&(this.onPinchMove(e),e.preventDefault())},onTouchEnd:function(e){var t=this;if(this._initialTouch){this.processEvent(e);var o,s=this.calculateMovement(this._lastTouch);s.x<=this.props.moveThreshold&&s.y<=this.props.moveThreshold&&this.props.onTap&&(e.preventDefault(),o=function(){var o=t._scrollParents.map(function(e){return e.scrollTop+e.scrollLeft}),s=t._scrollParentPos.some(function(e,t){return e!==o[t]});s||t.props.onTap(e)}),this.endTouch(e,o)}else this.onPinchEnd&&this._initialPinch&&e.touches.length+e.changedTouches.length===2&&(this.onPinchEnd(e),e.preventDefault())},endTouch:function(e,t){this.cancelTouchmoveDetection(),this.cancelPressDetection(),this.clearActiveTimeout(),e&&this.props.onTouchEnd&&this.props.onTouchEnd(e),this._initialTouch=null,this._lastTouch=null,t&&t(),this.state.isActive&&this.setState({isActive:!1})},onMouseDown:function(e){return window._blockMouseEvents?void(window._blockMouseEvents=!1):void(this.props.onMouseDown&&this.props.onMouseDown(e)===!1||(this.processEvent(e),this.initPressDetection(e,this.endMouseEvent),this._mouseDown=!0,this.setState({isActive:!0})))},onMouseMove:function(e){!window._blockMouseEvents&&this._mouseDown&&(this.processEvent(e),this.props.onMouseMove&&this.props.onMouseMove(e))},onMouseUp:function(e){!window._blockMouseEvents&&this._mouseDown&&(this.processEvent(e),this.props.onMouseUp&&this.props.onMouseUp(e),this.props.onTap&&this.props.onTap(e),this.endMouseEvent())},onMouseOut:function(e){!window._blockMouseEvents&&this._mouseDown&&(this.processEvent(e),this.props.onMouseOut&&this.props.onMouseOut(e),this.endMouseEvent())},endMouseEvent:function(){this.cancelPressDetection(),this._mouseDown=!1,this.setState({isActive:!1})},onKeyUp:function(e){this._keyDown&&(this.processEvent(e),this.props.onKeyUp&&this.props.onKeyUp(e),this.props.onTap&&this.props.onTap(e),this._keyDown=!1,this.cancelPressDetection(),this.setState({isActive:!1}))},onKeyDown:function(e){this.props.onKeyDown&&this.props.onKeyDown(e)===!1||e.which!==i&&e.which!==c||this._keyDown||(this.initPressDetection(e,this.endKeyEvent),this.processEvent(e),this._keyDown=!0,this.setState({isActive:!0}))},endKeyEvent:function(){this.cancelPressDetection(),this._keyDown=!1,this.setState({isActive:!1})},cancelTap:function(){this.endTouch(),this._mouseDown=!1},handlers:function(){return{onTouchStart:this.onTouchStart,onTouchMove:this.onTouchMove,onTouchEnd:this.onTouchEnd,onMouseDown:this.onMouseDown,onMouseUp:this.onMouseUp,onMouseMove:this.onMouseMove,onMouseOut:this.onMouseOut,onKeyDown:this.onKeyDown,onKeyUp:this.onKeyUp}}};t.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],3:[function(e,t,o){(function(o){"use strict";var s=Object.assign||function(e){for(var t=1;te.offsetHeight||e.scrollWidth>e.offsetWidth)&&(this._scrollParents.push(e),this._scrollParentPos.push(e.scrollTop+e.scrollLeft),this._scrollPos.top+=e.scrollTop,this._scrollPos.left+=e.scrollLeft),e=e.parentNode},initTouchmoveDetection:function(){this._touchmoveTriggeredTimes=0},cancelTouchmoveDetection:function(){this._touchmoveDetectionTimeout&&(clearTimeout(this._touchmoveDetectionTimeout),this._touchmoveDetectionTimeout=null,this._touchmoveTriggeredTimes=0)},calculateMovement:function(e){return{x:Math.abs(e.clientX-this._initialTouch.clientX),y:Math.abs(e.clientY-this._initialTouch.clientY)}},detectScroll:function(){for(var e={top:0,left:0},t=0;tthis.props.pressMoveThreshold||t.y>this.props.pressMoveThreshold)&&this.cancelPressDetection(),console.log("moving",t.y),t.x>(this.props.moveThresholdX||this.props.moveThreshold)||t.y>(this.props.moveThresholdY||this.props.moveThreshold)?(console.log("a",this.state.isActive),this.state.isActive?(console.log("d"),this.setState({isActive:!1})):this._activeTimeout&&this.clearActiveTimeout()):this.props.allowReactivation&&(console.log("b"),this.state.isActive||this._activeTimeout||this.setState({isActive:!0}))}else this._initialPinch&&2===e.touches.length&&this.onPinchMove&&(this.onPinchMove(e),e.preventDefault())},onTouchEnd:function(e){var t=this;if(this._initialTouch){this.processEvent(e);var o,s=this.calculateMovement(this._lastTouch);s.x<=(this.props.moveThresholdX||this.props.moveThreshold)&&s.y<=(this.props.moveThresholdY||this.props.moveThreshold)&&this.props.onTap&&(e.preventDefault(),o=function(){var o=t._scrollParents.map(function(e){return e.scrollTop+e.scrollLeft}),s=t._scrollParentPos.some(function(e,t){return e!==o[t]});s||t.props.onTap(e)}),this.endTouch(e,o)}else this.onPinchEnd&&this._initialPinch&&e.touches.length+e.changedTouches.length===2&&(this.onPinchEnd(e),e.preventDefault())},endTouch:function(e,t){this.cancelTouchmoveDetection(),this.cancelPressDetection(),this.clearActiveTimeout(),e&&this.props.onTouchEnd&&this.props.onTouchEnd(e),this._initialTouch=null,this._lastTouch=null,t&&t(),this.state.isActive&&this.setState({isActive:!1})},onMouseDown:function(e){return window._blockMouseEvents?void(window._blockMouseEvents=!1):void(this.props.onMouseDown&&this.props.onMouseDown(e)===!1||(this.processEvent(e),this.initPressDetection(e,this.endMouseEvent),this._mouseDown=!0,this.setState({isActive:!0})))},onMouseMove:function(e){!window._blockMouseEvents&&this._mouseDown&&(this.processEvent(e),this.props.onMouseMove&&this.props.onMouseMove(e))},onMouseUp:function(e){!window._blockMouseEvents&&this._mouseDown&&(this.processEvent(e),this.props.onMouseUp&&this.props.onMouseUp(e),this.props.onTap&&this.props.onTap(e),this.endMouseEvent())},onMouseOut:function(e){!window._blockMouseEvents&&this._mouseDown&&(this.processEvent(e),this.props.onMouseOut&&this.props.onMouseOut(e),this.endMouseEvent())},endMouseEvent:function(){this.cancelPressDetection(),this._mouseDown=!1,this.setState({isActive:!1})},onKeyUp:function(e){this._keyDown&&(this.processEvent(e),this.props.onKeyUp&&this.props.onKeyUp(e),this.props.onTap&&this.props.onTap(e),this._keyDown=!1,this.cancelPressDetection(),this.setState({isActive:!1}))},onKeyDown:function(e){this.props.onKeyDown&&this.props.onKeyDown(e)===!1||e.which!==i&&e.which!==c||this._keyDown||(this.initPressDetection(e,this.endKeyEvent),this.processEvent(e),this._keyDown=!0,this.setState({isActive:!0}))},endKeyEvent:function(){this.cancelPressDetection(),this._keyDown=!1,this.setState({isActive:!1})},cancelTap:function(){this.endTouch(),this._mouseDown=!1},handlers:function(){return{onTouchStart:this.onTouchStart,onTouchMove:this.onTouchMove,onTouchEnd:this.onTouchEnd,onMouseDown:this.onMouseDown,onMouseUp:this.onMouseUp,onMouseMove:this.onMouseMove,onMouseOut:this.onMouseOut,onKeyDown:this.onKeyDown,onKeyUp:this.onKeyUp}}};t.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],3:[function(e,t,o){(function(o){"use strict";var s=Object.assign||function(e){for(var t=1;t this.props.pressMoveThreshold || movement.y > this.props.pressMoveThreshold) { this.cancelPressDetection(); } - if (movement.x > this.props.moveThreshold || movement.y > this.props.moveThreshold) { + console.log('moving', movement.y); + if (movement.x > (this.props.moveThresholdX || this.props.moveThreshold) || movement.y > (this.props.moveThresholdY || this.props.moveThreshold)) { + console.log('a', this.state.isActive); if (this.state.isActive) { + console.log('d'); this.setState({ isActive: false }); } else if (this._activeTimeout) { this.clearActiveTimeout(); } - } else { + } else if (this.props.allowReactivation) { + console.log('b'); if (!this.state.isActive && !this._activeTimeout) { this.setState({ isActive: true @@ -208,7 +237,7 @@ var Mixin = { this.processEvent(event); var afterEndTouch; var movement = this.calculateMovement(this._lastTouch); - if (movement.x <= this.props.moveThreshold && movement.y <= this.props.moveThreshold && this.props.onTap) { + if (movement.x <= (this.props.moveThresholdX || this.props.moveThreshold) && movement.y <= (this.props.moveThresholdY || this.props.moveThreshold) && this.props.onTap) { event.preventDefault(); afterEndTouch = function () { var finalParentScrollPos = _this._scrollParents.map(function (node) { diff --git a/example/dist/common.js b/example/dist/common.js index c0c531a..1602f9e 100644 --- a/example/dist/common.js +++ b/example/dist/common.js @@ -1,1682 +1,1443 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); + if ("production" !== 'production') { + console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.'); + } + return { + remove: emptyFunction + }; } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; + }, -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); + registerDefault: function registerDefault() {} }; -process.umask = function() { return 0; }; -},{}],2:[function(require,module,exports){ +module.exports = EventListener; +},{"./emptyFunction":8}],2:[function(require,module,exports){ /** - * Copyright 2013-present, Facebook, Inc. + * Copyright (c) 2013-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule AutoFocusUtils */ 'use strict'; -var ReactDOMComponentTree = require('./ReactDOMComponentTree'); +var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); -var focusNode = require('fbjs/lib/focusNode'); +/** + * Simple, lightweight module assisting with the detection and context of + * Worker. Helps avoid circular dependencies and allows code to reason about + * whether or not they are in a Worker, even if they never include the main + * `ReactWorker` dependency. + */ +var ExecutionEnvironment = { + + canUseDOM: canUseDOM, + + canUseWorkers: typeof Worker !== 'undefined', + + canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent), + + canUseViewport: canUseDOM && !!window.screen, + + isInWorker: !canUseDOM // For now, this is true - might change in the future. -var AutoFocusUtils = { - focusDOMComponent: function () { - focusNode(ReactDOMComponentTree.getNodeFromInstance(this)); - } }; -module.exports = AutoFocusUtils; -},{"./ReactDOMComponentTree":43,"fbjs/lib/focusNode":153}],3:[function(require,module,exports){ +module.exports = ExecutionEnvironment; +},{}],3:[function(require,module,exports){ +"use strict"; + /** - * Copyright 2013-present Facebook, Inc. + * Copyright (c) 2013-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule BeforeInputEventPlugin + * @typechecks */ -'use strict'; - -var EventConstants = require('./EventConstants'); -var EventPropagators = require('./EventPropagators'); -var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); -var FallbackCompositionState = require('./FallbackCompositionState'); -var SyntheticCompositionEvent = require('./SyntheticCompositionEvent'); -var SyntheticInputEvent = require('./SyntheticInputEvent'); - -var keyOf = require('fbjs/lib/keyOf'); - -var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space -var START_KEYCODE = 229; - -var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window; - -var documentMode = null; -if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) { - documentMode = document.documentMode; -} - -// Webkit offers a very useful `textInput` event that can be used to -// directly represent `beforeInput`. The IE `textinput` event is not as -// useful, so we don't use it. -var canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto(); - -// In IE9+, we have access to composition events, but the data supplied -// by the native compositionend event may be incorrect. Japanese ideographic -// spaces, for instance (\u3000) are not recorded correctly. -var useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); +var _hyphenPattern = /-(.)/g; /** - * Opera <= 12 includes TextEvent in window, but does not fire - * text input events. Rely on keypress instead. + * Camelcases a hyphenated string, for example: + * + * > camelize('background-color') + * < "backgroundColor" + * + * @param {string} string + * @return {string} */ -function isPresto() { - var opera = window.opera; - return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12; +function camelize(string) { + return string.replace(_hyphenPattern, function (_, character) { + return character.toUpperCase(); + }); } -var SPACEBAR_CODE = 32; -var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); - -var topLevelTypes = EventConstants.topLevelTypes; +module.exports = camelize; +},{}],4:[function(require,module,exports){ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @typechecks + */ -// Events and their corresponding property names. -var eventTypes = { - beforeInput: { - phasedRegistrationNames: { - bubbled: keyOf({ onBeforeInput: null }), - captured: keyOf({ onBeforeInputCapture: null }) - }, - dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste] - }, - compositionEnd: { - phasedRegistrationNames: { - bubbled: keyOf({ onCompositionEnd: null }), - captured: keyOf({ onCompositionEndCapture: null }) - }, - dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] - }, - compositionStart: { - phasedRegistrationNames: { - bubbled: keyOf({ onCompositionStart: null }), - captured: keyOf({ onCompositionStartCapture: null }) - }, - dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] - }, - compositionUpdate: { - phasedRegistrationNames: { - bubbled: keyOf({ onCompositionUpdate: null }), - captured: keyOf({ onCompositionUpdateCapture: null }) - }, - dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] - } -}; +'use strict'; -// Track whether we've ever handled a keypress on the space key. -var hasSpaceKeypress = false; +var camelize = require('./camelize'); -/** - * Return whether a native keypress event is assumed to be a command. - * This is required because Firefox fires `keypress` events for key commands - * (cut, copy, select-all, etc.) even though no character is inserted. - */ -function isKeypressCommand(nativeEvent) { - return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && - // ctrlKey && altKey is equivalent to AltGr, and is not a command. - !(nativeEvent.ctrlKey && nativeEvent.altKey); -} +var msPattern = /^-ms-/; /** - * Translate native top level events into event types. + * Camelcases a hyphenated CSS property name, for example: * - * @param {string} topLevelType - * @return {object} + * > camelizeStyleName('background-color') + * < "backgroundColor" + * > camelizeStyleName('-moz-transition') + * < "MozTransition" + * > camelizeStyleName('-ms-transition') + * < "msTransition" + * + * As Andi Smith suggests + * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix + * is converted to lowercase `ms`. + * + * @param {string} string + * @return {string} */ -function getCompositionEventType(topLevelType) { - switch (topLevelType) { - case topLevelTypes.topCompositionStart: - return eventTypes.compositionStart; - case topLevelTypes.topCompositionEnd: - return eventTypes.compositionEnd; - case topLevelTypes.topCompositionUpdate: - return eventTypes.compositionUpdate; - } +function camelizeStyleName(string) { + return camelize(string.replace(msPattern, 'ms-')); } +module.exports = camelizeStyleName; +},{"./camelize":3}],5:[function(require,module,exports){ +'use strict'; + /** - * Does our fallback best-guess model think this event signifies that - * composition has begun? + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * */ -function isFallbackCompositionStart(topLevelType, nativeEvent) { - return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE; -} + +var isTextNode = require('./isTextNode'); + +/*eslint-disable no-bitwise */ /** - * Does our fallback mode think that this event is the end of composition? - * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} + * Checks if a given DOM node contains or is another DOM node. */ -function isFallbackCompositionEnd(topLevelType, nativeEvent) { - switch (topLevelType) { - case topLevelTypes.topKeyUp: - // Command keys insert or clear IME input. - return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; - case topLevelTypes.topKeyDown: - // Expect IME keyCode on each keydown. If we get any other - // code we must have exited earlier. - return nativeEvent.keyCode !== START_KEYCODE; - case topLevelTypes.topKeyPress: - case topLevelTypes.topMouseDown: - case topLevelTypes.topBlur: - // Events are not possible without cancelling IME. - return true; - default: - return false; +function containsNode(outerNode, innerNode) { + if (!outerNode || !innerNode) { + return false; + } else if (outerNode === innerNode) { + return true; + } else if (isTextNode(outerNode)) { + return false; + } else if (isTextNode(innerNode)) { + return containsNode(outerNode, innerNode.parentNode); + } else if ('contains' in outerNode) { + return outerNode.contains(innerNode); + } else if (outerNode.compareDocumentPosition) { + return !!(outerNode.compareDocumentPosition(innerNode) & 16); + } else { + return false; } } +module.exports = containsNode; +},{"./isTextNode":18}],6:[function(require,module,exports){ +'use strict'; + /** - * Google Input Tools provides composition data via a CustomEvent, - * with the `data` property populated in the `detail` object. If this - * is available on the event object, use it. If not, this is a plain - * composition event and we have nothing special to extract. + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. * - * @param {object} nativeEvent - * @return {?string} + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @typechecks */ -function getDataFromCustomEvent(nativeEvent) { - var detail = nativeEvent.detail; - if (typeof detail === 'object' && 'data' in detail) { - return detail.data; - } - return null; -} -// Track the current IME composition fallback object, if any. -var currentComposition = null; +var invariant = require('./invariant'); /** - * @return {?object} A SyntheticCompositionEvent. + * Convert array-like objects to arrays. + * + * This API assumes the caller knows the contents of the data type. For less + * well defined inputs use createArrayFromMixed. + * + * @param {object|function|filelist} obj + * @return {array} */ -function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var eventType; - var fallbackData; +function toArray(obj) { + var length = obj.length; - if (canUseCompositionEvent) { - eventType = getCompositionEventType(topLevelType); - } else if (!currentComposition) { - if (isFallbackCompositionStart(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionStart; - } - } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionEnd; - } + // Some browsers builtin objects can report typeof 'function' (e.g. NodeList + // in old versions of Safari). + !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? "production" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0; - if (!eventType) { - return null; - } + !(typeof length === 'number') ? "production" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0; - if (useFallbackCompositionData) { - // The current composition is stored statically and must not be - // overwritten while composition continues. - if (!currentComposition && eventType === eventTypes.compositionStart) { - currentComposition = FallbackCompositionState.getPooled(nativeEventTarget); - } else if (eventType === eventTypes.compositionEnd) { - if (currentComposition) { - fallbackData = currentComposition.getData(); - } - } - } + !(length === 0 || length - 1 in obj) ? "production" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0; - var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget); + !(typeof obj.callee !== 'function') ? "production" !== 'production' ? invariant(false, 'toArray: Object can\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0; - if (fallbackData) { - // Inject data generated from fallback path into the synthetic event. - // This matches the property of native CompositionEventInterface. - event.data = fallbackData; - } else { - var customData = getDataFromCustomEvent(nativeEvent); - if (customData !== null) { - event.data = customData; + // Old IE doesn't give collections access to hasOwnProperty. Assume inputs + // without method will throw during the slice call and skip straight to the + // fallback. + if (obj.hasOwnProperty) { + try { + return Array.prototype.slice.call(obj); + } catch (e) { + // IE < 9 does not support Array#slice on collections objects } } - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; -} - -/** - * @param {string} topLevelType Record from `EventConstants`. - * @param {object} nativeEvent Native browser event. - * @return {?string} The string corresponding to this `beforeInput` event. - */ -function getNativeBeforeInputChars(topLevelType, nativeEvent) { - switch (topLevelType) { - case topLevelTypes.topCompositionEnd: - return getDataFromCustomEvent(nativeEvent); - case topLevelTypes.topKeyPress: - /** - * If native `textInput` events are available, our goal is to make - * use of them. However, there is a special case: the spacebar key. - * In Webkit, preventing default on a spacebar `textInput` event - * cancels character insertion, but it *also* causes the browser - * to fall back to its default spacebar behavior of scrolling the - * page. - * - * Tracking at: - * https://code.google.com/p/chromium/issues/detail?id=355103 - * - * To avoid this issue, use the keypress event as if no `textInput` - * event is available. - */ - var which = nativeEvent.which; - if (which !== SPACEBAR_CODE) { - return null; - } - - hasSpaceKeypress = true; - return SPACEBAR_CHAR; - - case topLevelTypes.topTextInput: - // Record the characters to be added to the DOM. - var chars = nativeEvent.data; - - // If it's a spacebar character, assume that we have already handled - // it at the keypress level and bail immediately. Android Chrome - // doesn't give us keycodes, so we need to blacklist it. - if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { - return null; - } - - return chars; - - default: - // For other native event types, do nothing. - return null; + // Fall back to copying key by key. This assumes all keys have a value, + // so will not preserve sparsely populated inputs. + var ret = Array(length); + for (var ii = 0; ii < length; ii++) { + ret[ii] = obj[ii]; } + return ret; } /** - * For browsers that do not provide the `textInput` event, extract the - * appropriate string to use for SyntheticInputEvent. + * Perform a heuristic test to determine if an object is "array-like". * - * @param {string} topLevelType Record from `EventConstants`. - * @param {object} nativeEvent Native browser event. - * @return {?string} The fallback string for this `beforeInput` event. - */ -function getFallbackBeforeInputChars(topLevelType, nativeEvent) { - // If we are currently composing (IME) and using a fallback to do so, - // try to extract the composed characters from the fallback object. - if (currentComposition) { - if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) { - var chars = currentComposition.getData(); - FallbackCompositionState.release(currentComposition); - currentComposition = null; - return chars; - } - return null; - } - - switch (topLevelType) { - case topLevelTypes.topPaste: - // If a paste event occurs after a keypress, throw out the input - // chars. Paste events should not lead to BeforeInput events. - return null; - case topLevelTypes.topKeyPress: - /** - * As of v27, Firefox may fire keypress events even when no character - * will be inserted. A few possibilities: - * - * - `which` is `0`. Arrow keys, Esc key, etc. - * - * - `which` is the pressed key code, but no char is available. - * Ex: 'AltGr + d` in Polish. There is no modified character for - * this key combination and no character is inserted into the - * document, but FF fires the keypress for char code `100` anyway. - * No `input` event will occur. - * - * - `which` is the pressed key code, but a command combination is - * being used. Ex: `Cmd+C`. No character is inserted, and no - * `input` event will occur. - */ - if (nativeEvent.which && !isKeypressCommand(nativeEvent)) { - return String.fromCharCode(nativeEvent.which); - } - return null; - case topLevelTypes.topCompositionEnd: - return useFallbackCompositionData ? null : nativeEvent.data; - default: - return null; - } -} - -/** - * Extract a SyntheticInputEvent for `beforeInput`, based on either native - * `textInput` or fallback behavior. + * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?" + * Joshu replied: "Mu." * - * @return {?object} A SyntheticInputEvent. + * This function determines if its argument has "array nature": it returns + * true if the argument is an actual array, an `arguments' object, or an + * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()). + * + * It will return false for other array-like objects like Filelist. + * + * @param {*} obj + * @return {boolean} */ -function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var chars; - - if (canUseTextInputEvent) { - chars = getNativeBeforeInputChars(topLevelType, nativeEvent); - } else { - chars = getFallbackBeforeInputChars(topLevelType, nativeEvent); - } - - // If no characters are being inserted, no BeforeInput event should - // be fired. - if (!chars) { - return null; - } - - var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget); - - event.data = chars; - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; +function hasArrayNature(obj) { + return ( + // not null/false + !!obj && ( + // arrays are objects, NodeLists are functions in Safari + typeof obj == 'object' || typeof obj == 'function') && + // quacks like an array + 'length' in obj && + // not window + !('setInterval' in obj) && + // no DOM node should be considered an array-like + // a 'select' element has 'length' and 'item' properties on IE8 + typeof obj.nodeType != 'number' && ( + // a real array + Array.isArray(obj) || + // arguments + 'callee' in obj || + // HTMLCollection/NodeList + 'item' in obj) + ); } /** - * Create an `onBeforeInput` event to match - * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. + * Ensure that the argument is an array by wrapping it in an array if it is not. + * Creates a copy of the argument if it is already an array. * - * This event plugin is based on the native `textInput` event - * available in Chrome, Safari, Opera, and IE. This event fires after - * `onKeyPress` and `onCompositionEnd`, but before `onInput`. + * This is mostly useful idiomatically: * - * `beforeInput` is spec'd but not implemented in any browsers, and - * the `input` event does not provide any useful information about what has - * actually been added, contrary to the spec. Thus, `textInput` is the best - * available event to identify the characters that have actually been inserted - * into the target node. + * var createArrayFromMixed = require('createArrayFromMixed'); * - * This plugin is also responsible for emitting `composition` events, thus - * allowing us to share composition fallback code for both `beforeInput` and - * `composition` event types. + * function takesOneOrMoreThings(things) { + * things = createArrayFromMixed(things); + * ... + * } + * + * This allows you to treat `things' as an array, but accept scalars in the API. + * + * If you need to convert an array-like object, like `arguments`, into an array + * use toArray instead. + * + * @param {*} obj + * @return {array} */ -var BeforeInputEventPlugin = { - - eventTypes: eventTypes, - - extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { - return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)]; +function createArrayFromMixed(obj) { + if (!hasArrayNature(obj)) { + return [obj]; + } else if (Array.isArray(obj)) { + return obj.slice(); + } else { + return toArray(obj); } -}; +} + +module.exports = createArrayFromMixed; +},{"./invariant":16}],7:[function(require,module,exports){ +'use strict'; -module.exports = BeforeInputEventPlugin; -},{"./EventConstants":17,"./EventPropagators":21,"./FallbackCompositionState":22,"./SyntheticCompositionEvent":100,"./SyntheticInputEvent":104,"fbjs/lib/ExecutionEnvironment":145,"fbjs/lib/keyOf":163}],4:[function(require,module,exports){ /** - * Copyright 2013-present, Facebook, Inc. + * Copyright (c) 2013-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule CSSProperty + * @typechecks */ -'use strict'; +/*eslint-disable fb-www/unsafe-html*/ + +var ExecutionEnvironment = require('./ExecutionEnvironment'); + +var createArrayFromMixed = require('./createArrayFromMixed'); +var getMarkupWrap = require('./getMarkupWrap'); +var invariant = require('./invariant'); /** - * CSS properties which accept numbers but are not in units of "px". + * Dummy container used to render all markup. */ +var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; -var isUnitlessNumber = { - animationIterationCount: true, - borderImageOutset: true, - borderImageSlice: true, - borderImageWidth: true, - boxFlex: true, - boxFlexGroup: true, - boxOrdinalGroup: true, - columnCount: true, - flex: true, - flexGrow: true, - flexPositive: true, - flexShrink: true, - flexNegative: true, - flexOrder: true, - gridRow: true, - gridColumn: true, - fontWeight: true, - lineClamp: true, - lineHeight: true, - opacity: true, - order: true, - orphans: true, - tabSize: true, - widows: true, - zIndex: true, - zoom: true, +/** + * Pattern used by `getNodeName`. + */ +var nodeNamePattern = /^\s*<(\w+)/; - // SVG-related properties - fillOpacity: true, - floodOpacity: true, - stopOpacity: true, - strokeDasharray: true, - strokeDashoffset: true, - strokeMiterlimit: true, - strokeOpacity: true, - strokeWidth: true -}; +/** + * Extracts the `nodeName` of the first element in a string of markup. + * + * @param {string} markup String of markup. + * @return {?string} Node name of the supplied markup. + */ +function getNodeName(markup) { + var nodeNameMatch = markup.match(nodeNamePattern); + return nodeNameMatch && nodeNameMatch[1].toLowerCase(); +} /** - * @param {string} prefix vendor-specific prefix, eg: Webkit - * @param {string} key style name, eg: transitionDuration - * @return {string} style name prefixed with `prefix`, properly camelCased, eg: - * WebkitTransitionDuration + * Creates an array containing the nodes rendered from the supplied markup. The + * optionally supplied `handleScript` function will be invoked once for each + *