├── .editorconfig
├── .eslintrc
├── .gitignore
├── .travis.yml
├── README.md
├── package.json
├── rollup.config.js
├── src
└── index.js
└── test
└── index.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | end_of_line = lf
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [{package.json,.*rc,*.yml}]
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "eslint:recommended",
4 | "env": {
5 | "browser": true
6 | },
7 | "plugins": [
8 | "react"
9 | ],
10 | "settings": {
11 | "react": {
12 | "pragma": "h"
13 | }
14 | },
15 | "parserOptions": {
16 | "ecmaVersion": 6,
17 | "sourceType": "module",
18 | "ecmaFeatures": {
19 | "modules": true,
20 | "jsx": true
21 | }
22 | },
23 | "rules": {
24 | "react/jsx-uses-react": 2,
25 | "react/jsx-uses-vars": 2,
26 | "no-unused-vars": [1, { "varsIgnorePattern": "^h$" }],
27 | "no-cond-assign": 1,
28 | "semi": 2,
29 | "camelcase": 0,
30 | "comma-style": 2,
31 | "comma-dangle": [2, "never"],
32 | "indent": [2, "tab", {"SwitchCase": 1}],
33 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"],
34 | "no-trailing-spaces": [2, { "skipBlankLines": true }],
35 | "max-nested-callbacks": [2, 3],
36 | "no-eval": 2,
37 | "no-implied-eval": 2,
38 | "no-new-func": 2,
39 | "guard-for-in": 2,
40 | "eqeqeq": 2,
41 | "no-else-return": 2,
42 | "no-redeclare": 2,
43 | "no-dupe-keys": 2,
44 | "radix": 2,
45 | "strict": [2, "never"],
46 | "no-shadow": 0,
47 | "callback-return": [1, ["callback", "cb", "next", "done"]],
48 | "no-delete-var": 2,
49 | "no-undef-init": 2,
50 | "no-shadow-restricted-names": 2,
51 | "handle-callback-err": 0,
52 | "no-lonely-if": 2,
53 | "keyword-spacing": 2,
54 | "constructor-super": 2,
55 | "no-this-before-super": 2,
56 | "no-dupe-class-members": 2,
57 | "no-const-assign": 2,
58 | "prefer-spread": 2,
59 | "no-useless-concat": 2,
60 | "no-var": 2,
61 | "object-shorthand": 2,
62 | "prefer-arrow-callback": 2
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /node_modules
3 | /npm-debug.log
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - stable
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # preact-tap-event-plugin: `onTouchTap` _for [Preact]_
2 |
3 | [](https://www.npmjs.com/package/preact-tap-event-plugin)
4 | [](https://travis-ci.org/developit/preact-tap-event-plugin)
5 |
6 | `onTouchTap` is a [FastClick]-style instant "click" event, triggered by `touchstart` and `touchend` occurring within a 10-pixel radius.
7 |
8 | > This module intentionally has the same interface as [react-tap-event-plugin](https://github.com/zilverline/react-tap-event-plugin) so that it can be used as a drop-in alias when working with [preact-compat](https://github.com/developit/preact-compat).
9 |
10 | #### [JSFiddle Demo](https://jsfiddle.net/developit/rq877gp3/)
11 |
12 |
13 | ---
14 |
15 |
16 | ## Usage Example
17 |
18 | `npm i -S preact-tap-event-plugin`
19 |
20 |
21 | ```js
22 | import injectTapEventPlugin from 'preact-tap-event-plugin';
23 |
24 | injectTapEventPlugin();
25 | ```
26 |
27 |
28 | ---
29 |
30 |
31 | ## License
32 |
33 | [MIT]
34 |
35 |
36 | [Preact]: https://github.com/developit/preact
37 | [FastClick]: https://github.com/ftlabs/fastclick
38 | [MIT]: http://choosealicense.com/licenses/mit/
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "preact-tap-event-plugin",
3 | "amdName": "injectTapEventPlugin",
4 | "version": "0.1.2",
5 | "description": "Use onTouchTap in Preact",
6 | "main": "dist/preact-tap-event-plugin.js",
7 | "minified:main": "dist/preact-tap-event-plugin.min.js",
8 | "jsnext:main": "src/index.js",
9 | "scripts": {
10 | "build": "npm-run-all transpile optimize minify",
11 | "transpile": "rollup -c rollup.config.js -m ${npm_package_main}.map -f umd -n $npm_package_amdName $npm_package_jsnext_main -o $npm_package_main",
12 | "optimize": "uglifyjs $npm_package_main -bc dead_code --pure-funcs _possibleConstructorReturn _classCallCheck -o $npm_package_main -p relative --in-source-map ${npm_package_main}.map --source-map ${npm_package_main}.map",
13 | "minify": "uglifyjs $npm_package_main -mc collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code --pure-funcs _possibleConstructorReturn _classCallCheck -o $npm_package_minified_main -p relative --in-source-map ${npm_package_main}.map --source-map ${npm_package_minified_main}.map",
14 | "test": "eslint {src,test} && mocha --compilers js:babel-register test/**/*.js",
15 | "prepublish": "npm run build",
16 | "release": "npm run build && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"
17 | },
18 | "babel": {
19 | "presets": [
20 | "es2015",
21 | "stage-0"
22 | ],
23 | "plugins": [
24 | "transform-class-properties",
25 | [
26 | "transform-react-jsx",
27 | {
28 | "pragma": "h"
29 | }
30 | ]
31 | ]
32 | },
33 | "keywords": [
34 | "preact",
35 | "tap",
36 | "event",
37 | "plugin"
38 | ],
39 | "files": [
40 | "src",
41 | "dist"
42 | ],
43 | "author": "Jason Miller ",
44 | "license": "MIT",
45 | "repository": {
46 | "type": "git",
47 | "url": "git+https://github.com/developit/preact-tap-event-plugin.git"
48 | },
49 | "bugs": {
50 | "url": "https://github.com/developit/preact-tap-event-plugin/issues"
51 | },
52 | "homepage": "https://github.com/developit/preact-tap-event-plugin",
53 | "devDependencies": {
54 | "babel": "^6.5.2",
55 | "babel-eslint": "^7.1.0",
56 | "babel-plugin-transform-class-properties": "^6.18.0",
57 | "babel-plugin-transform-es2015-classes-simple": "^1.0.0",
58 | "babel-plugin-transform-react-jsx": "^6.8.0",
59 | "babel-preset-es2015": "^6.18.0",
60 | "babel-preset-stage-0": "^6.16.0",
61 | "babel-register": "^6.18.0",
62 | "chai": "^3.5.0",
63 | "eslint": "^3.10.2",
64 | "eslint-plugin-react": "^6.7.1",
65 | "mocha": "^3.1.2",
66 | "npm-run-all": "^3.1.1",
67 | "preact": "^7.1.0",
68 | "rollup": "^0.36.3",
69 | "rollup-plugin-babel": "^2.6.1",
70 | "rollup-plugin-es3": "^1.0.3",
71 | "uglify-js": "^2.7.4"
72 | },
73 | "peerDependencies": {
74 | "preact": "*"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import es3 from 'rollup-plugin-es3';
3 |
4 | export default {
5 | useStrict: false,
6 | plugins: [
7 | babel({
8 | babelrc: false,
9 | sourceMap: true,
10 | exclude: 'node_modules/**',
11 | presets: [
12 | ['es2015', { modules:false, loose:true }],
13 | 'stage-0'
14 | ],
15 | plugins: [
16 | 'transform-class-properties',
17 | ['transform-react-jsx', { pragma:'h' }]
18 | ]
19 | }),
20 | es3()
21 | ]
22 | };
23 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { options } from 'preact';
2 |
3 |
4 | const OPTS = {
5 | // # of pixels after which to discount as drag op
6 | threshold: 10
7 | };
8 |
9 |
10 | let injected, hasTouch;
11 |
12 |
13 | // in case someone calls inject():
14 | export default opts => {
15 | for (let i in opts) if (opts.hasOwnProperty(i)) OPTS[i] = opts[i];
16 |
17 | if (injected) return;
18 | injected = true;
19 |
20 | let oldHook = options.vnode;
21 | options.vnode = vnode => {
22 | let attrs = 'props' in vnode ? vnode.props : vnode.attributes;
23 | if (attrs) {
24 | for (let i in attrs) {
25 | if (attrs.hasOwnProperty(i) && i.toLowerCase()==='ontouchtap') {
26 | proxy(attrs);
27 | break;
28 | }
29 | }
30 | }
31 | if (oldHook) oldHook(vnode);
32 | };
33 | };
34 |
35 |
36 | function proxy(attrs) {
37 | let map = {};
38 | for (let i in attrs) if (attrs.hasOwnProperty(i)) {
39 | map[i.toLowerCase()] = i;
40 | }
41 |
42 | let start = attrs[map.ontouchstart],
43 | tap = attrs[map.ontouchtap],
44 | click = attrs[map.onclick];
45 |
46 | delete attrs[map.ontouchtap];
47 |
48 | attrs[map.onclick || 'onClick'] = e => {
49 | if (click) click(e);
50 | if (!hasTouch) return tap(e);
51 | };
52 |
53 | attrs[map.ontouchstart || 'onTouchStart'] = e => {
54 | let down = coords(e);
55 | hasTouch = true;
56 |
57 | addEventListener('touchend', function onEnd(e) {
58 | removeEventListener('touchend', onEnd);
59 | let up = coords(e),
60 | dist = Math.sqrt( Math.pow(up.x-down.x,2) + Math.pow(up.y-down.y,2) );
61 | if (dist {
8 | it('should export a class', () => {
9 | expect(injectTapEventPlugin).to.be.a('function');
10 | });
11 |
12 | xit('should have proper tests', () => {});
13 | });
14 |
--------------------------------------------------------------------------------