├── index.js
├── dist
├── bundle.css.map
├── index.html
├── bundle.css
└── components
│ └── index.js
├── .eslintignore
├── mocha.opts
├── test
└── tools
│ ├── cssNullCompiler.js
│ ├── renderPage.js
│ └── setup.js
├── .editorconfig
├── .travis.yml
├── CHANGELOG.md
├── .babelrc
├── src
├── index.html
├── index.js
├── style.scss
└── components
│ └── index.js
├── .gitignore
├── webpack.config.js
├── LICENSE.md
├── .eslintrc
├── README.md
└── package.json
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./dist/components/index')
2 |
--------------------------------------------------------------------------------
/dist/bundle.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"bundle.css","sourceRoot":""}
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 | dist/**
3 | webpack*
4 | src/public/*
5 | src/tracking/omniture.js
6 | src/bundles/click/index.js
7 |
--------------------------------------------------------------------------------
/mocha.opts:
--------------------------------------------------------------------------------
1 | --compilers js:babel-register,css:test/tools/cssNullCompiler.js
2 | --recursive
3 | --require ./test/tools/setup.js
4 | --timeout 15000
5 | --slow 150
6 |
--------------------------------------------------------------------------------
/test/tools/cssNullCompiler.js:
--------------------------------------------------------------------------------
1 | /* This will effectively ignore any require() or import() for css or png files */
2 | function doNothing () {
3 | return null
4 | }
5 |
6 | require.extensions['.scss'] = doNothing
7 | require.extensions['.css'] = doNothing
8 |
--------------------------------------------------------------------------------
/test/tools/renderPage.js:
--------------------------------------------------------------------------------
1 | import { mount } from 'enzyme'
2 | import React from 'react'
3 |
4 | function renderPage (component) {
5 | return mount(
6 |
7 | {component}
8 |
9 | )
10 | }
11 |
12 | module.exports = renderPage
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - stable
5 |
6 | install:
7 | - npm install
8 |
9 | script:
10 | - npm run cover
11 |
12 | # Send coverage data to Coveralls
13 | after_script: "cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js"
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## v0.1.0
2 | - `ToggleIcon` now tages an object just like onProps instead of the previous version where `ToggleButton` could have been a string or a react component.
3 | - color and backgroundColor can not be added to `ToggleIcon`
4 |
5 | ## v0.1.6
6 | - Change `IosToggle` default off `backgroundColor`
7 |
8 | ## v0.2.0
9 | - Comes with inbuild css files that can be used instead of inline css
10 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "stage-0",
5 | "react"
6 | ],
7 | "plugins": [
8 | "babel-plugin-add-module-exports",
9 | "babel-plugin-transform-runtime"
10 | ],
11 | "env": {
12 | "test": {
13 | "presets": [
14 | "es2015",
15 | "stage-0",
16 | "react"
17 | ],
18 | "plugins": [ "babel-plugin-istanbul" ]
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-toggle
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-toggle
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/test/tools/setup.js:
--------------------------------------------------------------------------------
1 | global.PAGE_TIMEOUT = 1000
2 |
3 | let jsdom = require('jsdom')
4 | global.document = jsdom.jsdom({src: ''})
5 | global.window = document.defaultView
6 | Object.keys(document.defaultView).forEach((property) => {
7 | if (typeof global[property] === 'undefined') {
8 | global[property] = document.defaultView[property]
9 | }
10 | })
11 | global.navigator = {userAgent: 'Mocha Test node.js'}
12 |
13 | export function consoleError (error) {
14 | this.log(error)
15 | throw new Error(error)
16 | }
17 |
18 | console.error = consoleError // eslint-disable-line no-console
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 |
29 | #build folder
30 | build
31 |
32 | #Webstorm metadata
33 | .idea
34 |
35 | # Mac files
36 | .DS_Store
37 |
38 | # dotenv file
39 | .env
40 |
41 |
42 | #nyc
43 | .nyc_output/
44 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { render } from 'react-dom'
3 | import classnames from 'classnames'
4 | import HoverIntent from './components/index'
5 |
6 | require('./style.scss')
7 |
8 | class App extends Component {
9 | constructor() {
10 | super()
11 | this.state = { mouseover: false }
12 | }
13 | onMouseOver = () => {
14 | this.setState({ mouseover: true })
15 | }
16 | onMouseOut = () => {
17 | this.setState({ mouseover: false })
18 | }
19 | render() {
20 | const { mouseover } = this.state
21 | return (
22 |
23 |
27 |
28 | -
29 | Hover
30 | Hover
31 |
32 |
33 |
34 |
35 | )
36 | }
37 | }
38 |
39 | render(, document.getElementById('root'))
40 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var CopyWebpackPlugin = require('copy-webpack-plugin')
2 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
3 | var path = require('path')
4 |
5 | module.exports = {
6 | entry: './src/index.js',
7 | devtool: 'source-map',
8 |
9 | output: {
10 | path: path.join(__dirname, 'dist'),
11 | filename: 'bundle.js'
12 | },
13 | module: {
14 | loaders: [
15 | {
16 | test: /\.js$/,
17 | exclude: /node_modules/,
18 | loader: 'babel-loader',
19 | },
20 | {
21 | test: /\.(scss|css)$/,
22 | loader: ExtractTextPlugin.extract("style-loader", ["css-loader", "postcss-loader", "sass-loader"]),
23 | },
24 | ],
25 | },
26 | postcss: () => {
27 | return [
28 | require('autoprefixer')
29 | ];
30 | },
31 | devServer: {
32 | port: 4000,
33 | host: 'localhost',
34 | inline: true,
35 | info: false,
36 | },
37 | plugins: [
38 | new CopyWebpackPlugin([
39 | { from: path.join(__dirname, 'src/index.html') },
40 | ]),
41 | new ExtractTextPlugin('bundle.css', { allChunks: true }),
42 | ],
43 | }
44 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License (MIT)
2 | =====================
3 |
4 | Copyright © 2017 Yatin Gera
5 |
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the “Software”), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | OTHER DEALINGS IN THE SOFTWARE.
26 |
27 |
--------------------------------------------------------------------------------
/src/style.scss:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Bitter');
2 |
3 | .container {
4 | padding-top: 40px;
5 | }
6 |
7 | body {
8 | background:
9 | linear-gradient(limegreen, transparent), linear-gradient(90deg, skyblue, transparent), linear-gradient(-90deg, coral, transparent);
10 | height: 100vh;
11 | background-blend-mode: screen;
12 | font: bold 18px/24px 'Bitter', serif;
13 | color: #000;
14 | margin:0;
15 | padding:0;
16 | overflow-x: hidden;
17 | -webkit-font-smoothing: antialiased;
18 | }
19 | ul {
20 | margin:0;
21 | padding:0;
22 | list-style:none;
23 | }
24 | li {
25 | position: relative;
26 | }
27 |
28 | .popover {
29 | display:none;
30 | position: absolute;
31 | border:1px solid #101010;
32 | background:#fff;
33 | z-index:1000;
34 | position:absolute;
35 | width:170px;
36 | margin-left:-105px;
37 | border:none;
38 | padding:20px;
39 | font-size:22px;
40 | animation-duration:500ms;
41 | animation-fill-mode:both;
42 | box-shadow:0 4px 8px rgba(0,0,0,0.25);
43 | border-radius:4px;
44 | }
45 | .popover.open {
46 | display:block;
47 | top: 25px;
48 | left: 40px;
49 | animation-name:fadeInUp;
50 | }
51 |
52 | @keyframes fadeInUp {
53 | 0% { opacity:0; transform:translateY(5px); }
54 | 100% { opacity:1; transform:translateY(0); }
55 | }
--------------------------------------------------------------------------------
/dist/bundle.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=Bitter);.container {
2 | padding-top: 40px; }
3 |
4 | body {
5 | background: linear-gradient(limegreen, transparent), linear-gradient(90deg, skyblue, transparent), linear-gradient(-90deg, coral, transparent);
6 | height: 100vh;
7 | background-blend-mode: screen;
8 | font: bold 18px/24px 'Bitter', serif;
9 | color: #000;
10 | margin: 0;
11 | padding: 0;
12 | overflow-x: hidden;
13 | -webkit-font-smoothing: antialiased; }
14 |
15 | ul {
16 | margin: 0;
17 | padding: 0;
18 | list-style: none; }
19 |
20 | li {
21 | position: relative; }
22 |
23 | .popover {
24 | display: none;
25 | position: absolute;
26 | border: 1px solid #101010;
27 | background: #fff;
28 | z-index: 1000;
29 | position: absolute;
30 | width: 170px;
31 | margin-left: -105px;
32 | border: none;
33 | padding: 20px;
34 | font-size: 22px;
35 | animation-duration: 500ms;
36 | animation-fill-mode: both;
37 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.25);
38 | border-radius: 4px; }
39 |
40 | .popover.open {
41 | display: block;
42 | top: 25px;
43 | left: 40px;
44 | animation-name: fadeInUp; }
45 |
46 | @keyframes fadeInUp {
47 | 0% {
48 | opacity: 0;
49 | transform: translateY(5px); }
50 | 100% {
51 | opacity: 1;
52 | transform: translateY(0); } }
53 |
54 | /*# sourceMappingURL=bundle.css.map*/
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "standard",
5 | "standard-react",
6 | "eslint:recommended",
7 | "plugin:react/recommended"
8 | ],
9 | "plugins": [
10 | "react",
11 | "babel",
12 | "mocha",
13 | "import"
14 | ],
15 | "parserOptions": {
16 | "ecmaVersion": 6,
17 | "sourceType": "module",
18 | "ecmaFeatures": {
19 | "jsx": true
20 | }
21 | },
22 | "globals": {
23 | "__DEV__": true
24 | },
25 | "env": {
26 | "es6": true,
27 | "browser": true,
28 | "node": true,
29 | "jquery": true,
30 | "mocha": true
31 | },
32 | "rules": {
33 | "quotes": 0,
34 | "no-console": 1,
35 | "no-debugger": 1,
36 | "no-var": 1,
37 | "semi": [1, "never"],
38 | "no-trailing-spaces": 0,
39 | "eol-last": 0,
40 | "no-unused-vars": 0,
41 | "no-underscore-dangle": 0,
42 | "no-alert": 0,
43 | "no-lone-blocks": 0,
44 | "jsx-quotes": 1,
45 | "import/extensions": 1,
46 | "comma-dangle": ["warn", "always-multiline"],
47 | "react/display-name": [ 1, {"ignoreTranspilerName": false }],
48 | "react/forbid-prop-types": [1, {"forbid": ["any"]}],
49 | "react/jsx-boolean-value": 1,
50 | "react/jsx-closing-bracket-location": 0,
51 | "react/jsx-curly-spacing": 1,
52 | "react/jsx-indent-props": 0,
53 | "react/jsx-key": 1,
54 | "react/jsx-max-props-per-line": 0,
55 | "react/jsx-no-bind": 1,
56 | "react/jsx-no-duplicate-props": 1,
57 | "react/jsx-no-literals": 0,
58 | "react/jsx-no-undef": 1,
59 | "react/jsx-pascal-case": 1,
60 | "react/jsx-sort-prop-types": 0,
61 | "react/jsx-sort-props": 0,
62 | "react/jsx-uses-react": 1,
63 | "react/jsx-uses-vars": 1,
64 | "react/no-danger": 1,
65 | "react/no-did-mount-set-state": 1,
66 | "react/no-did-update-set-state": 1,
67 | "react/no-direct-mutation-state": 1,
68 | "react/no-multi-comp": 1,
69 | "react/no-set-state": 0,
70 | "react/no-unknown-property": 1,
71 | "react/prefer-es6-class": 1,
72 | "react/prop-types": 1,
73 | "react/react-in-jsx-scope": 1,
74 | "react/self-closing-comp": 1,
75 | "react/sort-comp": 1,
76 | "react/jsx-wrap-multilines": 1
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | class HoverIntent extends Component {
5 | constructor() {
6 | super()
7 | this.x = 0
8 | this.y = 0
9 | this.pX = 0
10 | this.pY = 0
11 | this.status = 0
12 | this.timer = 0
13 | }
14 | componentDidMount() {
15 | this.element.addEventListener('mouseover', this.dispatchOver, false)
16 | this.element.addEventListener('mouseout', this.dispatchOut, false)
17 | }
18 | componentWillUnmount() {
19 | this.element.removeEventListener('mouseover', this.dispatchOver, false)
20 | this.element.removeEventListener('mouseout', this.dispatchOut, false)
21 | }
22 | delay = (e) => {
23 | if (this.timer) { this.timer = clearTimeout(this.timer) }
24 | this.status = 0
25 | return this.props.onMouseOut.call(this.element, e)
26 | }
27 | tracker = (e) => {
28 | this.x = e.clientX
29 | this.y = e.clientY
30 | }
31 | compare = (e) => {
32 | if (this.timer) { this.timer = clearTimeout(this.timer) }
33 | if ((Math.abs(this.pX - this.x) + Math.abs(this.pY - this.y)) < this.props.sensitivity) {
34 | this.status = 1
35 | return this.props.onMouseOver.call(this.element, e)
36 | } else {
37 | this.pX = this.x
38 | this.pY = this.y
39 | this.timer = setTimeout(() => this.compare(e), this.props.interval)
40 | }
41 | }
42 | dispatchOver = (e) => {
43 | if (this.timer) { this.timer = clearTimeout(this.timer) }
44 | this.element.removeEventListener('mousemove', this.tracker, false)
45 | if (this.status !== 1) {
46 | this.pX = e.clientX
47 | this.pY = e.clientY
48 | this.element.addEventListener('mousemove', this.tracker, false)
49 | this.timer = setTimeout(() => this.compare(e), this.props.interval)
50 | }
51 | }
52 | dispatchOut = (e) => {
53 | if (this.timer) { this.timer = clearTimeout(this.timer) }
54 | this.element.removeEventListener('mousemove', this.tracker, false)
55 | if (this.status === 1) {
56 | this.timer = setTimeout(() => this.delay(e), this.props.timeout)
57 | }
58 | }
59 | render() {
60 | return React.cloneElement(this.props.children, {
61 | ref: (element) => { this.element = element },
62 | })
63 | }
64 | }
65 |
66 | HoverIntent.defaultProps = {
67 | sensitivity: 7,
68 | interval: 100,
69 | timeout: 0,
70 | }
71 |
72 | HoverIntent.propTypes = {
73 | sensitivity: PropTypes.number,
74 | interval: PropTypes.number,
75 | timeout: PropTypes.number,
76 | onMouseOver: PropTypes.func,
77 | onMouseOut: PropTypes.func,
78 | children: PropTypes.node,
79 | }
80 |
81 | export default HoverIntent
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## React Hoverintent
2 |
3 |
4 | react-hoverintent is a react wrapper over jquery-hoverintent plugin.
5 |
6 | "hoverIntent is a plug-in that attempts to determine the user's intent... like a crystal ball, only with mouse movement! It is similar to jQuery's hover method. However, instead of calling the handlerIn function immediately, hoverIntent waits until the user's mouse slows down enough before making the call."
7 |
8 | [jquery-hoverintent](https://github.com/briancherne/jquery-hoverIntent).
9 |
10 |
11 | ## Installation
12 | ```npm install react-hoverintent```
13 |
14 | ## Demo
15 |
16 | The demo with live examples can be viewed [here](https://vijayranghar.github.io/).
17 |
18 |
19 | ## Props
20 |
21 | ```onMouseOver``` : The callback to fire on mouse over event
22 |
23 | ```onMouseOut``` : The callback to fire on mouse out event
24 |
25 | ```timeout``` :
26 | A simple delay, in milliseconds, before the ```onMouseOut``` callback is fired. If the user mouses back over the element before the timeout has expired the ```onMouseOut``` callback will not be called (nor will the ```onMouseOver``` callback be called). This is primarily to protect against sloppy/human mousing trajectories that temporarily (and unintentionally) take the user off of the target element... giving them time to return.
27 |
28 | Default ```timeout: 0```
29 |
30 | ```sensitivity``` :
31 | If the mouse travels fewer than this number of pixels between polling intervals, then the ```onMouseOver``` callback will be called. With the minimum sensitivity threshold of 1, the mouse must not move between polling intervals. With higher sensitivity thresholds you are more likely to receive a false positive.
32 |
33 | Default ```sensitivity: 7```
34 |
35 | ```interval``` :
36 | The number of milliseconds hoverIntent waits between reading/comparing mouse coordinates. When the user's mouse first enters the element its coordinates are recorded. The soonest the ```onMouseOut``` callback can be called is after a single polling interval. Setting the polling interval higher will increase the delay before the first possible ```onMouseOver``` call, but also increases the time to the next point of comparison.
37 |
38 | Default ```interval: 700```
39 |
40 |
41 | ## Use
42 |
43 | ```javascript
44 | import HoverIntet from 'react-hoverintent'
45 | import classnames from 'classnames'
46 |
47 | class App extends Component {
48 | constructor () {
49 | super()
50 | this.state = { mouseover: false }
51 | this.onMouseOver = this.onMouseOver.bind(this)
52 | this.onMouseOut = this.onMouseOut.bind(this)
53 | }
54 | onMouseOver () {
55 | this.setState({mouseover: true})
56 | }
57 | onMouseOut () {
58 | this.setState({mouseover: false})
59 | }
60 | render () {
61 | let {mouseover} = this.state
62 | return (
63 |
64 |
71 |
72 |
73 | Hover
74 |
75 | )
76 | }
77 | }
78 | ```
79 |
80 |
81 |
82 | ## Repo
83 | https://github.com/nerdchacha/react-hoverintent
84 |
85 |
86 |
87 | ## Authors
88 | **Yatin Gera**
89 |
90 | **Vijay Mohan Singh Ranghar**
91 |
92 | ## Credits
93 |
94 | **[briancherne](https://github.com/briancherne/jquery-hoverIntent)** - initial work and setup
95 |
96 |
97 | ## Issue tracker
98 | https://github.com/nerdchacha/react-hoverintent/issues
99 |
100 |
101 | ## License
102 |
103 | This project is licensed under the MIT License
104 |
105 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-hoverintent",
3 | "version": "0.0.10",
4 | "description": "A simple react implementation over jquery-hoverintent",
5 | "scripts": {
6 | "lint": "eslint src",
7 | "lint:changed": "LIST=`git diff-index --name-only HEAD | grep '.jsx\\{0,1\\}'$`; if [ \"$LIST\" ]; then eslint $LIST; fi",
8 | "lint:fix": "npm run lint -- --fix",
9 | "lint:changed:fix": "LIST=`git diff-index --name-only HEAD | grep '.jsx\\{0,1\\}'$`; if [ \"$LIST\" ]; then eslint $LIST --fix; fi",
10 | "lint:changed-PR": "LIST=`git diff-index --name-only HEAD^ | grep '.jsx\\{0,1\\}'$`; if [ \"$LIST\" ]; then eslint $LIST; fi",
11 | "test": "npm run test:local && npm run build:component",
12 | "test:local": "env NODE_ENV=test mocha --opts mocha.opts",
13 | "build:component": "babel src/components --out-dir dist/components",
14 | "add:component": "git add dist/",
15 | "start": "webpack-dev-server",
16 | "build:bundle": "webpack",
17 | "cover": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text mocha --opts mocha.opts"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/nerdchacha/react-hoverintent"
22 | },
23 | "author": {
24 | "name": "Yatin Gera",
25 | "email": "yatin.gera5@gmail.com"
26 | },
27 | "bugs": {
28 | "url": "https://github.com/nerdchacha/react-hoverintent/issues"
29 | },
30 | "main": "index.js",
31 | "keywords": [
32 | "hover",
33 | "hover intent",
34 | "delay"
35 | ],
36 | "license": "MIT",
37 | "precommit": {
38 | "run": [
39 | "build:component",
40 | "build:bundle",
41 | "add:component",
42 | "lint:changed"
43 | ]
44 | },
45 | "dependencies": {
46 | "prop-types": "^15.5.10",
47 | "react": "^15.4.1",
48 | "react-dom": "^15.4.1"
49 | },
50 | "devDependencies": {
51 | "autoprefixer-loader": "^3.2.0",
52 | "babel-cli": "^6.8.0",
53 | "babel-core": "^6.8.0",
54 | "babel-eslint": "^7.1.1",
55 | "babel-istanbul": "^0.12.2",
56 | "babel-loader": "^6.2.10",
57 | "babel-plugin-add-module-exports": "^0.2.1",
58 | "babel-plugin-istanbul": "^4.0.0",
59 | "babel-plugin-react-display-name": "2.0.0",
60 | "babel-plugin-react-transform": "^2.0.2",
61 | "babel-plugin-transform-imports": "^1.1.0",
62 | "babel-plugin-transform-runtime": "^6.15.0",
63 | "babel-polyfill": "^6.20.0",
64 | "babel-preset-es2015": "^6.6.0",
65 | "babel-preset-react": "^6.5.0",
66 | "babel-preset-react-hmre": "1.1.1",
67 | "babel-preset-stage-0": "^6.16.0",
68 | "babel-register": "^6.8.0",
69 | "babel-runtime": "^6.20.0",
70 | "browser-sync": "^2.18.5",
71 | "chai": "^3.5.0",
72 | "classnames": "^2.2.5",
73 | "copy-webpack-plugin": "^4.0.1",
74 | "coveralls": "^2.12.0",
75 | "cross-env": "^3.2.4",
76 | "css-loader": "^0.27.3",
77 | "enzyme": "2.2.0",
78 | "eslint": "^3.12.2",
79 | "eslint-config-standard": "^6.2.1",
80 | "eslint-config-standard-react": "^4.2.0",
81 | "eslint-loader": "^1.5.0",
82 | "eslint-plugin-babel": "^4.0.0",
83 | "eslint-plugin-import": "^2.2.0",
84 | "eslint-plugin-mocha": "^4.3.0",
85 | "eslint-plugin-promise": "^3.4.0",
86 | "eslint-plugin-react": "^6.8.0",
87 | "eslint-plugin-standard": "^2.0.0",
88 | "eventsource-polyfill": "0.9.6",
89 | "expect": "1.19.0",
90 | "extract-text-webpack-plugin": "^1.0.1",
91 | "jsdom": "8.5.0",
92 | "mocha": "2.4.5",
93 | "ncp": "^2.0.0",
94 | "node-sass": "^4.5.0",
95 | "nyc": "^10.1.2",
96 | "postcss-loader": "^1.3.3",
97 | "pre-commit": "^1.2.2",
98 | "react-addons-test-utils": "^15.0.2",
99 | "react-bootstrap": "^0.30.8",
100 | "react-fontawesome": "^1.5.0",
101 | "sass-loader": "^6.0.2",
102 | "scss-loader": "0.0.1",
103 | "style-loader": "^0.13.2",
104 | "webpack": "^1.13.2",
105 | "webpack-dev-middleware": "1.6.1",
106 | "webpack-dev-server": "^1.16.0",
107 | "webpack-hot-middleware": "^2.10.0",
108 | "webpack-middleware": "^1.5.1"
109 | },
110 | "nyc": {
111 | "sourceMap": false,
112 | "instrument": false
113 | }
114 | }
--------------------------------------------------------------------------------
/dist/components/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | var _propTypes = require('prop-types');
32 |
33 | var _propTypes2 = _interopRequireDefault(_propTypes);
34 |
35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36 |
37 | var HoverIntent = function (_Component) {
38 | (0, _inherits3.default)(HoverIntent, _Component);
39 |
40 | function HoverIntent() {
41 | (0, _classCallCheck3.default)(this, HoverIntent);
42 |
43 | var _this = (0, _possibleConstructorReturn3.default)(this, (HoverIntent.__proto__ || (0, _getPrototypeOf2.default)(HoverIntent)).call(this));
44 |
45 | _this.delay = function (e) {
46 | if (_this.timer) {
47 | _this.timer = clearTimeout(_this.timer);
48 | }
49 | _this.status = 0;
50 | return _this.props.onMouseOut.call(_this.element, e);
51 | };
52 |
53 | _this.tracker = function (e) {
54 | _this.x = e.clientX;
55 | _this.y = e.clientY;
56 | };
57 |
58 | _this.compare = function (e) {
59 | if (_this.timer) {
60 | _this.timer = clearTimeout(_this.timer);
61 | }
62 | if (Math.abs(_this.pX - _this.x) + Math.abs(_this.pY - _this.y) < _this.props.sensitivity) {
63 | _this.status = 1;
64 | return _this.props.onMouseOver.call(_this.element, e);
65 | } else {
66 | _this.pX = _this.x;
67 | _this.pY = _this.y;
68 | _this.timer = setTimeout(function () {
69 | return _this.compare(e);
70 | }, _this.props.interval);
71 | }
72 | };
73 |
74 | _this.dispatchOver = function (e) {
75 | if (_this.timer) {
76 | _this.timer = clearTimeout(_this.timer);
77 | }
78 | _this.element.removeEventListener('mousemove', _this.tracker, false);
79 | if (_this.status !== 1) {
80 | _this.pX = e.clientX;
81 | _this.pY = e.clientY;
82 | _this.element.addEventListener('mousemove', _this.tracker, false);
83 | _this.timer = setTimeout(function () {
84 | return _this.compare(e);
85 | }, _this.props.interval);
86 | }
87 | };
88 |
89 | _this.dispatchOut = function (e) {
90 | if (_this.timer) {
91 | _this.timer = clearTimeout(_this.timer);
92 | }
93 | _this.element.removeEventListener('mousemove', _this.tracker, false);
94 | if (_this.status === 1) {
95 | _this.timer = setTimeout(function () {
96 | return _this.delay(e);
97 | }, _this.props.timeout);
98 | }
99 | };
100 |
101 | _this.x = 0;
102 | _this.y = 0;
103 | _this.pX = 0;
104 | _this.pY = 0;
105 | _this.status = 0;
106 | _this.timer = 0;
107 | return _this;
108 | }
109 |
110 | (0, _createClass3.default)(HoverIntent, [{
111 | key: 'componentDidMount',
112 | value: function componentDidMount() {
113 | this.element.addEventListener('mouseover', this.dispatchOver, false);
114 | this.element.addEventListener('mouseout', this.dispatchOut, false);
115 | }
116 | }, {
117 | key: 'componentWillUnmount',
118 | value: function componentWillUnmount() {
119 | this.element.removeEventListener('mouseover', this.dispatchOver, false);
120 | this.element.removeEventListener('mouseout', this.dispatchOut, false);
121 | }
122 | }, {
123 | key: 'render',
124 | value: function render() {
125 | var _this2 = this;
126 |
127 | return _react2.default.cloneElement(this.props.children, {
128 | ref: function ref(element) {
129 | _this2.element = element;
130 | }
131 | });
132 | }
133 | }]);
134 | return HoverIntent;
135 | }(_react.Component);
136 |
137 | HoverIntent.defaultProps = {
138 | sensitivity: 7,
139 | interval: 100,
140 | timeout: 0
141 | };
142 |
143 | HoverIntent.propTypes = {
144 | sensitivity: _propTypes2.default.number,
145 | interval: _propTypes2.default.number,
146 | timeout: _propTypes2.default.number,
147 | onMouseOver: _propTypes2.default.func,
148 | onMouseOut: _propTypes2.default.func,
149 | children: _propTypes2.default.node
150 | };
151 |
152 | exports.default = HoverIntent;
153 | module.exports = exports['default'];
--------------------------------------------------------------------------------