├── .babelrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── bower.json ├── dist ├── react-hammerjs.es.js ├── react-hammerjs.js └── react-hammerjs.min.js ├── gulpfile.js ├── lib └── Hammer.js ├── package.json ├── rollup.config.js └── src └── Hammer.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "targets": { 7 | "browsers": ["last 2 versions", "ie 10"] 8 | } 9 | } 10 | ], 11 | "react" 12 | ], 13 | "plugins": ["transform-class-properties"] 14 | } 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = false 9 | insert_final_newline = true 10 | indent_style = tab 11 | 12 | [*.json] 13 | indent_style = space 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'babel-eslint', 3 | extends: ['keystone-react'], 4 | rules: { 'space-before-function-paren': 'off' }, 5 | }; 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Coverage tools 11 | lib-cov 12 | coverage 13 | 14 | # Dependency directory 15 | node_modules 16 | yarn.lock 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Jed Watson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | React-HammerJS 2 | ============== 3 | 4 | [ReactJS](http://facebook.github.io/react/) / [HammerJS](http://hammerjs.github.io) integration. Support touch events in your React app. 5 | 6 | If you're looking for native tap event handling in ReactJS, check out my [react-tappable](https://github.com/JedWatson/react-tappable) package. 7 | 8 | 9 | ## Installation 10 | 11 | The easiest way to use React-HammerJS is to install it from NPM and include it in your own React build process (using [Browserify](http://browserify.org), etc). 12 | 13 | You can also use the standalone build by including `dist/hammer.js` in your page. If you use this, make sure you have already included React, and it is available as a global variable. 14 | 15 | ``` 16 | npm install react-hammerjs --save 17 | ``` 18 | 19 | 20 | ## Usage 21 | 22 | React-HammerJS wraps a React component, binding Hammer events to it so it can fire the handlers specified. 23 | 24 | ## Properties 25 | 26 | ### Event Listener properties 27 | * `onTap` 28 | * `onDoubleTap` 29 | * `onPan` 30 | * `onPanCancel` 31 | * `onPanEnd` 32 | * `onPanStart` 33 | * `onPinch` 34 | * `onPinchCancel` 35 | * `onPinchEnd` 36 | * `onPinchIn` 37 | * `onPinchOut` 38 | * `onPinchStart` 39 | * `onPress` 40 | * `onPressUp` 41 | * `onRotate` 42 | * `onRotateCancel` 43 | * `onRotateEnd` 44 | * `onRotateMove` 45 | * `onRotateStart` 46 | * `onSwipe` 47 | * `action` - like the `onTap` event handler but will also be fired `onPress`. 48 | 49 | ### Behavior properties 50 | * `direction` - (string) `'DIRECTION_ALL'` | `'DIRECTION_HORIZONTAL'` | `'DIRECTION_VERTICAL'`. Used to restrict the `pan` and `swipe` direction. These string values may also work: `'DIRECTION_NONE'` |`'DIRECTION_LEFT'` | `'DIRECTION_RIGHT'` | `'DIRECTION_UP'` | `'DIRECTION_DOWN'`. 51 | 52 | * `options` - can be used to configure the Hammer manager. These properties will be merged with the default ones. 53 | 54 | ### Example 55 | 56 | ``` 57 | var Hammer = require('react-hammerjs'); 58 | 59 | // Default options 60 |
Tap Me
61 | 62 | // Custom options 63 | var options = { 64 | touchAction:'compute', 65 | recognizers: { 66 | tap: { 67 | time: 600, 68 | threshold: 100 69 | } 70 | } 71 | }; 72 | 73 |
Tap Me
74 | ``` 75 | 76 | # Disabled Events 77 | 78 | As a default, the `pinch` and `rotate` events are disabled in hammer.js, as they would make actions on an element "blocking". You may enable these events using the options object which is a attribute on the react `` element. 79 | 80 | For example, to activate the `pinch` event on a `canvas` element: 81 | 82 | ``` 83 | 90 | 91 | 92 | ``` 93 | 94 | Disabled events are detailed in the hammer.js api documentation: 95 | - http://hammerjs.github.io/recognizer-rotate/ 96 | - http://hammerjs.github.io/recognizer-pinch/ 97 | 98 | # License 99 | 100 | MIT Licensed. Copyright (c) Jed Watson 2017. 101 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-hammerjs", 3 | "main": "dist/react-hammerjs.min.js", 4 | "version": "1.0.1", 5 | "homepage": "https://github.com/JedWatson/react-hammerjs", 6 | "authors": [ 7 | "Jed Watson" 8 | ], 9 | "description": "ReactJS / HammerJS integration. Support touch events in your React app.", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "react", 17 | "react-component", 18 | "tap", 19 | "tappable", 20 | "touch", 21 | "hammer", 22 | "hammerjs", 23 | "mobile" 24 | ], 25 | "license": "MIT", 26 | "ignore": [ 27 | ".editorconfig", 28 | ".gitignore", 29 | "package.json", 30 | "src", 31 | "node_modules", 32 | "example", 33 | "test" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /dist/react-hammerjs.es.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | var _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; }; }(); 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 7 | 8 | function _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; } 9 | 10 | function _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; } 11 | 12 | // require('hammerjs') when in a browser. This is safe because Hammer is only 13 | // invoked in componentDidMount, which is not executed on the server. 14 | var Hammer = typeof window !== 'undefined' ? require('hammerjs') : undefined; 15 | 16 | var privateProps = { 17 | children: true, 18 | direction: true, 19 | options: true, 20 | recognizeWith: true, 21 | vertical: true 22 | }; 23 | 24 | /** 25 | * Hammer Component 26 | * ================ 27 | */ 28 | 29 | var handlerToEvent = { 30 | action: 'tap press', 31 | onDoubleTap: 'doubletap', 32 | onPan: 'pan', 33 | onPanCancel: 'pancancel', 34 | onPanEnd: 'panend', 35 | onPanStart: 'panstart', 36 | onPinch: 'pinch', 37 | onPinchCancel: 'pinchcancel', 38 | onPinchEnd: 'pinchend', 39 | onPinchIn: 'pinchin', 40 | onPinchOut: 'pinchout', 41 | onPinchStart: 'pinchstart', 42 | onPress: 'press', 43 | onPressUp: 'pressup', 44 | onRotate: 'rotate', 45 | onRotateCancel: 'rotatecancel', 46 | onRotateEnd: 'rotateend', 47 | onRotateMove: 'rotatemove', 48 | onRotateStart: 'rotatestart', 49 | onSwipe: 'swipe', 50 | onSwipeRight: 'swiperight', 51 | onSwipeLeft: 'swipeleft', 52 | onSwipeUp: 'swipeup', 53 | onSwipeDown: 'swipedown', 54 | onTap: 'tap' 55 | }; 56 | 57 | Object.keys(handlerToEvent).forEach(function (i) { 58 | privateProps[i] = true; 59 | }); 60 | 61 | function updateHammer(hammer, props) { 62 | if (props.hasOwnProperty('vertical')) { 63 | console.warn('vertical is deprecated, please use `direction` instead'); 64 | } 65 | 66 | var directionProp = props.direction; 67 | if (directionProp || props.hasOwnProperty('vertical')) { 68 | var direction = directionProp ? directionProp : props.vertical ? 'DIRECTION_ALL' : 'DIRECTION_HORIZONTAL'; 69 | hammer.get('pan').set({ direction: Hammer[direction] }); 70 | hammer.get('swipe').set({ direction: Hammer[direction] }); 71 | } 72 | 73 | if (props.options) { 74 | Object.keys(props.options).forEach(function (option) { 75 | if (option === 'recognizers') { 76 | Object.keys(props.options.recognizers).forEach(function (gesture) { 77 | var recognizer = hammer.get(gesture); 78 | recognizer.set(props.options.recognizers[gesture]); 79 | if (props.options.recognizers[gesture].requireFailure) { 80 | recognizer.requireFailure(props.options.recognizers[gesture].requireFailure); 81 | } 82 | }, this); 83 | } else { 84 | var key = option; 85 | var optionObj = {}; 86 | optionObj[key] = props.options[option]; 87 | hammer.set(optionObj); 88 | } 89 | }, this); 90 | } 91 | 92 | if (props.recognizeWith) { 93 | Object.keys(props.recognizeWith).forEach(function (gesture) { 94 | var recognizer = hammer.get(gesture); 95 | recognizer.recognizeWith(props.recognizeWith[gesture]); 96 | }, this); 97 | } 98 | 99 | Object.keys(props).forEach(function (p) { 100 | var e = handlerToEvent[p]; 101 | if (e) { 102 | hammer.off(e); 103 | hammer.on(e, props[p]); 104 | } 105 | }); 106 | } 107 | 108 | var HammerComponent = function (_React$Component) { 109 | _inherits(HammerComponent, _React$Component); 110 | 111 | function HammerComponent() { 112 | _classCallCheck(this, HammerComponent); 113 | 114 | return _possibleConstructorReturn(this, (HammerComponent.__proto__ || Object.getPrototypeOf(HammerComponent)).apply(this, arguments)); 115 | } 116 | 117 | _createClass(HammerComponent, [{ 118 | key: 'componentDidMount', 119 | value: function componentDidMount() { 120 | this.hammer = new Hammer(this.domElement); 121 | updateHammer(this.hammer, this.props); 122 | } 123 | }, { 124 | key: 'componentDidUpdate', 125 | value: function componentDidUpdate() { 126 | if (this.hammer) { 127 | updateHammer(this.hammer, this.props); 128 | } 129 | } 130 | }, { 131 | key: 'componentWillUnmount', 132 | value: function componentWillUnmount() { 133 | if (this.hammer) { 134 | this.hammer.stop(); 135 | this.hammer.destroy(); 136 | } 137 | this.hammer = null; 138 | } 139 | }, { 140 | key: 'render', 141 | value: function render() { 142 | var props = {}; 143 | 144 | Object.keys(this.props).forEach(function (i) { 145 | if (!privateProps[i]) { 146 | props[i] = this.props[i]; 147 | } 148 | }, this); 149 | 150 | var self = this; 151 | props.ref = function (domElement) { 152 | if (self.props.ref) { 153 | self.props.ref(domElement); 154 | } 155 | self.domElement = domElement; 156 | }; 157 | 158 | // Reuse the child provided 159 | // This makes it flexible to use whatever element is wanted (div, ul, etc) 160 | return React.cloneElement(React.Children.only(this.props.children), props); 161 | } 162 | }]); 163 | 164 | return HammerComponent; 165 | }(React.Component); 166 | 167 | HammerComponent.displayName = 'Hammer'; 168 | HammerComponent.propTypes = { 169 | className: PropTypes.string 170 | }; 171 | 172 | export default HammerComponent; 173 | -------------------------------------------------------------------------------- /dist/react-hammerjs.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('prop-types'), require('react')) : 3 | typeof define === 'function' && define.amd ? define(['prop-types', 'react'], factory) : 4 | (global.Hammer = factory(global.PropTypes,global.React)); 5 | }(this, (function (PropTypes,React) { 'use strict'; 6 | 7 | PropTypes = PropTypes && PropTypes.hasOwnProperty('default') ? PropTypes['default'] : PropTypes; 8 | React = React && React.hasOwnProperty('default') ? React['default'] : React; 9 | 10 | var _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; }; }(); 11 | 12 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 13 | 14 | function _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; } 15 | 16 | function _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; } 17 | 18 | // require('hammerjs') when in a browser. This is safe because Hammer is only 19 | // invoked in componentDidMount, which is not executed on the server. 20 | var Hammer = typeof window !== 'undefined' ? require('hammerjs') : undefined; 21 | 22 | var privateProps = { 23 | children: true, 24 | direction: true, 25 | options: true, 26 | recognizeWith: true, 27 | vertical: true 28 | }; 29 | 30 | /** 31 | * Hammer Component 32 | * ================ 33 | */ 34 | 35 | var handlerToEvent = { 36 | action: 'tap press', 37 | onDoubleTap: 'doubletap', 38 | onPan: 'pan', 39 | onPanCancel: 'pancancel', 40 | onPanEnd: 'panend', 41 | onPanStart: 'panstart', 42 | onPinch: 'pinch', 43 | onPinchCancel: 'pinchcancel', 44 | onPinchEnd: 'pinchend', 45 | onPinchIn: 'pinchin', 46 | onPinchOut: 'pinchout', 47 | onPinchStart: 'pinchstart', 48 | onPress: 'press', 49 | onPressUp: 'pressup', 50 | onRotate: 'rotate', 51 | onRotateCancel: 'rotatecancel', 52 | onRotateEnd: 'rotateend', 53 | onRotateMove: 'rotatemove', 54 | onRotateStart: 'rotatestart', 55 | onSwipe: 'swipe', 56 | onSwipeRight: 'swiperight', 57 | onSwipeLeft: 'swipeleft', 58 | onSwipeUp: 'swipeup', 59 | onSwipeDown: 'swipedown', 60 | onTap: 'tap' 61 | }; 62 | 63 | Object.keys(handlerToEvent).forEach(function (i) { 64 | privateProps[i] = true; 65 | }); 66 | 67 | function updateHammer(hammer, props) { 68 | if (props.hasOwnProperty('vertical')) { 69 | console.warn('vertical is deprecated, please use `direction` instead'); 70 | } 71 | 72 | var directionProp = props.direction; 73 | if (directionProp || props.hasOwnProperty('vertical')) { 74 | var direction = directionProp ? directionProp : props.vertical ? 'DIRECTION_ALL' : 'DIRECTION_HORIZONTAL'; 75 | hammer.get('pan').set({ direction: Hammer[direction] }); 76 | hammer.get('swipe').set({ direction: Hammer[direction] }); 77 | } 78 | 79 | if (props.options) { 80 | Object.keys(props.options).forEach(function (option) { 81 | if (option === 'recognizers') { 82 | Object.keys(props.options.recognizers).forEach(function (gesture) { 83 | var recognizer = hammer.get(gesture); 84 | recognizer.set(props.options.recognizers[gesture]); 85 | if (props.options.recognizers[gesture].requireFailure) { 86 | recognizer.requireFailure(props.options.recognizers[gesture].requireFailure); 87 | } 88 | }, this); 89 | } else { 90 | var key = option; 91 | var optionObj = {}; 92 | optionObj[key] = props.options[option]; 93 | hammer.set(optionObj); 94 | } 95 | }, this); 96 | } 97 | 98 | if (props.recognizeWith) { 99 | Object.keys(props.recognizeWith).forEach(function (gesture) { 100 | var recognizer = hammer.get(gesture); 101 | recognizer.recognizeWith(props.recognizeWith[gesture]); 102 | }, this); 103 | } 104 | 105 | Object.keys(props).forEach(function (p) { 106 | var e = handlerToEvent[p]; 107 | if (e) { 108 | hammer.off(e); 109 | hammer.on(e, props[p]); 110 | } 111 | }); 112 | } 113 | 114 | var HammerComponent = function (_React$Component) { 115 | _inherits(HammerComponent, _React$Component); 116 | 117 | function HammerComponent() { 118 | _classCallCheck(this, HammerComponent); 119 | 120 | return _possibleConstructorReturn(this, (HammerComponent.__proto__ || Object.getPrototypeOf(HammerComponent)).apply(this, arguments)); 121 | } 122 | 123 | _createClass(HammerComponent, [{ 124 | key: 'componentDidMount', 125 | value: function componentDidMount() { 126 | this.hammer = new Hammer(this.domElement); 127 | updateHammer(this.hammer, this.props); 128 | } 129 | }, { 130 | key: 'componentDidUpdate', 131 | value: function componentDidUpdate() { 132 | if (this.hammer) { 133 | updateHammer(this.hammer, this.props); 134 | } 135 | } 136 | }, { 137 | key: 'componentWillUnmount', 138 | value: function componentWillUnmount() { 139 | if (this.hammer) { 140 | this.hammer.stop(); 141 | this.hammer.destroy(); 142 | } 143 | this.hammer = null; 144 | } 145 | }, { 146 | key: 'render', 147 | value: function render() { 148 | var props = {}; 149 | 150 | Object.keys(this.props).forEach(function (i) { 151 | if (!privateProps[i]) { 152 | props[i] = this.props[i]; 153 | } 154 | }, this); 155 | 156 | var self = this; 157 | props.ref = function (domElement) { 158 | if (self.props.ref) { 159 | self.props.ref(domElement); 160 | } 161 | self.domElement = domElement; 162 | }; 163 | 164 | // Reuse the child provided 165 | // This makes it flexible to use whatever element is wanted (div, ul, etc) 166 | return React.cloneElement(React.Children.only(this.props.children), props); 167 | } 168 | }]); 169 | 170 | return HammerComponent; 171 | }(React.Component); 172 | 173 | HammerComponent.displayName = 'Hammer'; 174 | HammerComponent.propTypes = { 175 | className: PropTypes.string 176 | }; 177 | 178 | return HammerComponent; 179 | 180 | }))); 181 | -------------------------------------------------------------------------------- /dist/react-hammerjs.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("prop-types"),require("react")):"function"==typeof define&&define.amd?define(["prop-types","react"],t):e.Hammer=t(e.PropTypes,e.React)}(this,function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function r(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function i(e,t){t.hasOwnProperty("vertical")&&console.warn("vertical is deprecated, please use `direction` instead");var n=t.direction;if(n||t.hasOwnProperty("vertical")){var o=n||(t.vertical?"DIRECTION_ALL":"DIRECTION_HORIZONTAL");e.get("pan").set({direction:c[o]}),e.get("swipe").set({direction:c[o]})}t.options&&Object.keys(t.options).forEach(function(n){if("recognizers"===n)Object.keys(t.options.recognizers).forEach(function(n){var o=e.get(n);o.set(t.options.recognizers[n]),t.options.recognizers[n].requireFailure&&o.requireFailure(t.options.recognizers[n].requireFailure)},this);else{var o={};o[n]=t.options[n],e.set(o)}},this),t.recognizeWith&&Object.keys(t.recognizeWith).forEach(function(n){e.get(n).recognizeWith(t.recognizeWith[n])},this),Object.keys(t).forEach(function(n){var o=p[n];o&&(e.off(o),e.on(o,t[n]))})}e=e&&e.hasOwnProperty("default")?e.default:e,t=t&&t.hasOwnProperty("default")?t.default:t;var a=function(){function e(e,t){for(var n=0;n { 16 | let result = { 17 | babelrc: false, 18 | presets: [ 19 | [ 20 | 'env', 21 | { 22 | modules: false, 23 | targets: { 24 | browsers: ['last 2 versions', 'ie 10'], 25 | }, 26 | }, 27 | ], 28 | 'react', 29 | ], 30 | plugins: ['transform-class-properties'], 31 | }; 32 | if (production) { 33 | result.plugins.push('transform-react-remove-prop-types'); 34 | } 35 | return result; 36 | }; 37 | 38 | export default [ 39 | { 40 | input: input, 41 | output: { 42 | file: output + '.es.js', 43 | format: 'es', 44 | }, 45 | external: external, 46 | plugins: [babel(babelOptions(false))], 47 | }, 48 | { 49 | input: input, 50 | output: { 51 | name: name, 52 | file: output + '.js', 53 | format: 'umd', 54 | }, 55 | globals: globals, 56 | external: external, 57 | plugins: [babel(babelOptions(false)), resolve()], 58 | }, 59 | { 60 | input: input, 61 | output: { 62 | name: name, 63 | file: output + '.min.js', 64 | format: 'umd', 65 | }, 66 | globals: globals, 67 | external: external, 68 | plugins: [babel(babelOptions(true)), resolve(), uglify({}, minify)], 69 | }, 70 | ]; 71 | -------------------------------------------------------------------------------- /src/Hammer.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | // require('hammerjs') when in a browser. This is safe because Hammer is only 5 | // invoked in componentDidMount, which is not executed on the server. 6 | const Hammer = typeof window !== 'undefined' ? require('hammerjs') : undefined; 7 | 8 | var privateProps = { 9 | children: true, 10 | direction: true, 11 | options: true, 12 | recognizeWith: true, 13 | vertical: true, 14 | }; 15 | 16 | /** 17 | * Hammer Component 18 | * ================ 19 | */ 20 | 21 | const handlerToEvent = { 22 | action: 'tap press', 23 | onDoubleTap: 'doubletap', 24 | onPan: 'pan', 25 | onPanCancel: 'pancancel', 26 | onPanEnd: 'panend', 27 | onPanStart: 'panstart', 28 | onPinch: 'pinch', 29 | onPinchCancel: 'pinchcancel', 30 | onPinchEnd: 'pinchend', 31 | onPinchIn: 'pinchin', 32 | onPinchOut: 'pinchout', 33 | onPinchStart: 'pinchstart', 34 | onPress: 'press', 35 | onPressUp: 'pressup', 36 | onRotate: 'rotate', 37 | onRotateCancel: 'rotatecancel', 38 | onRotateEnd: 'rotateend', 39 | onRotateMove: 'rotatemove', 40 | onRotateStart: 'rotatestart', 41 | onSwipe: 'swipe', 42 | onSwipeRight: 'swiperight', 43 | onSwipeLeft: 'swipeleft', 44 | onSwipeUp: 'swipeup', 45 | onSwipeDown: 'swipedown', 46 | onTap: 'tap', 47 | }; 48 | 49 | Object.keys(handlerToEvent).forEach(function(i) { 50 | privateProps[i] = true; 51 | }); 52 | 53 | function updateHammer(hammer, props) { 54 | if (props.hasOwnProperty('vertical')) { 55 | console.warn('vertical is deprecated, please use `direction` instead'); 56 | } 57 | 58 | var directionProp = props.direction; 59 | if (directionProp || props.hasOwnProperty('vertical')) { 60 | var direction = directionProp 61 | ? directionProp 62 | : props.vertical ? 'DIRECTION_ALL' : 'DIRECTION_HORIZONTAL'; 63 | hammer.get('pan').set({ direction: Hammer[direction] }); 64 | hammer.get('swipe').set({ direction: Hammer[direction] }); 65 | } 66 | 67 | if (props.options) { 68 | Object.keys(props.options).forEach(function(option) { 69 | if (option === 'recognizers') { 70 | Object.keys(props.options.recognizers).forEach(function(gesture) { 71 | var recognizer = hammer.get(gesture); 72 | recognizer.set(props.options.recognizers[gesture]); 73 | if (props.options.recognizers[gesture].requireFailure) { 74 | recognizer.requireFailure( 75 | props.options.recognizers[gesture].requireFailure 76 | ); 77 | } 78 | }, this); 79 | } else { 80 | var key = option; 81 | var optionObj = {}; 82 | optionObj[key] = props.options[option]; 83 | hammer.set(optionObj); 84 | } 85 | }, this); 86 | } 87 | 88 | if (props.recognizeWith) { 89 | Object.keys(props.recognizeWith).forEach(function(gesture) { 90 | var recognizer = hammer.get(gesture); 91 | recognizer.recognizeWith(props.recognizeWith[gesture]); 92 | }, this); 93 | } 94 | 95 | Object.keys(props).forEach(function(p) { 96 | var e = handlerToEvent[p]; 97 | if (e) { 98 | hammer.off(e); 99 | hammer.on(e, props[p]); 100 | } 101 | }); 102 | } 103 | 104 | export default class HammerComponent extends React.Component { 105 | static displayName = 'Hammer'; 106 | 107 | static propTypes = { 108 | className: PropTypes.string, 109 | }; 110 | 111 | componentDidMount() { 112 | this.hammer = new Hammer(this.domElement); 113 | updateHammer(this.hammer, this.props); 114 | } 115 | 116 | componentDidUpdate() { 117 | if (this.hammer) { 118 | updateHammer(this.hammer, this.props); 119 | } 120 | } 121 | 122 | componentWillUnmount() { 123 | if (this.hammer) { 124 | this.hammer.stop(); 125 | this.hammer.destroy(); 126 | } 127 | this.hammer = null; 128 | } 129 | 130 | render() { 131 | var props = {}; 132 | 133 | Object.keys(this.props).forEach(function(i) { 134 | if (!privateProps[i]) { 135 | props[i] = this.props[i]; 136 | } 137 | }, this); 138 | 139 | var self = this; 140 | props.ref = function(domElement) { 141 | if (self.props.ref) { 142 | self.props.ref(domElement); 143 | } 144 | self.domElement = domElement; 145 | }; 146 | 147 | // Reuse the child provided 148 | // This makes it flexible to use whatever element is wanted (div, ul, etc) 149 | return React.cloneElement(React.Children.only(this.props.children), props); 150 | } 151 | } 152 | --------------------------------------------------------------------------------