Skip to content

Commit

Permalink
V2.2.0: Support Hover Intent + Environment Detection
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanselzer committed Jul 24, 2017
1 parent 09ec794 commit 2e60d5b
Show file tree
Hide file tree
Showing 49 changed files with 4,140 additions and 1,606 deletions.
20 changes: 10 additions & 10 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
"rules": {
"no-unused-expressions": 0,
"chai-friendly/no-unused-expressions": 2,
"import/default": "warn",
"import/export": "warn",
"import/named": "warn",
"import/namespace": "warn",
"import/no-amd": "warn",
"import/no-duplicates": "warn",
"import/no-extraneous-dependencies": "warn",
"import/no-named-as-default": "warn",
"import/no-named-as-default-member": "warn",
"import/no-unresolved": ["warn", { "commonjs": true }],
"import/default": "error",
"import/export": "error",
"import/named": "error",
"import/namespace": "error",
"import/no-amd": "error",
"import/no-duplicates": "error",
"import/no-extraneous-dependencies": "error",
"import/no-named-as-default": "error",
"import/no-named-as-default-member": "error",
"import/no-unresolved": ["error", { "commonjs": true }],
"indent": ["error", 4]
}
}
38 changes: 23 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ See the [react-cursor-position demo site](https://ethanselzer.github.io/react-cu

Experiment with react-cursor-position [live on CodePen](http://codepen.io/ethanselzer/pen/ryayLK).

## Related Project

For hover monitoring, please consider [react-hover-observer](https://www.npmjs.com/package/react-hover-observer).
It has a similar interface to react-cursor-position, and can be used in combination with it.

## Installation

```sh
Expand All @@ -45,13 +40,17 @@ import ReactCursorPosition from 'react-cursor-position';
</ReactCursorPosition>
```

react-cursor-position wraps its children in a div, which cursor and touch position
react-cursor-position wraps its children in a div, which mouse and touch position
are plotted relative to.

Each child component will receive the following props:

```JavaScript
{
detectedEnvironment: {
isMouseDetected: false,
isTouchDetected: false,
},
elementDimensions: {
width: Number,
height: Number
Expand All @@ -66,36 +65,45 @@ Each child component will receive the following props:
```
This structure may be customized by implementing `mapChildProps` API feature.

The information in `detectedEnvironment` is acquired from interaction with this component and will be unset until the first interaction.

## Props API

All props are optional.

**className** : String - CSS class name(s) to be applied to the div rendered by react-cursor-position.

**style** : Object - Style to be applied to the div rendered by react-cursor-position.
**hoverDelayInMs** : Number - Amount of time, in milliseconds, to delay hover interaction from activating. Defaults to 0.

**onActivationChanged** : Function - Called when the component is active.
Function receives one parameter with the signature `{ isActive: Boolean }`.
**hoverOffDelayInMs** : Number - Amount of time, in milliseconds, to delay hover off interaciton from deactivating. Defaults to 0.

**onPositionChanged** : Function - Called when cursor or touch position changes.
Function receives one parameter with the signature `{ elementDimensions: { width: Number, height: Number }, isPositionOutside: Boolean, position: { x: Number, y: Number } }`.
**isActivatedOnTouch** : Boolean - Activate immediately on touch. Scrolling may not be possible when scroll
gesture begins on target area. Recommended only when scrolling is not an expected use case. Defaults to false.

**mapChildProps** : Function - Model child component props to your custom shape.
Function receives one parameter with the signature
`{ isActive: Boolean, isPositionOutside: Boolean, position: { x: Number, y: Number } }`.
It should return an object that is compatible with the props interface of your child components.
See [example demo](https://ethanselzer.github.io/react-cursor-position/#/map-child-props).

**shouldDecorateChildren** : Boolean - Suppress decoration of child components by
setting this prop false. Defaults to true.
**onActivationChanged** : Function - Called when the component is active.
Function receives one parameter with the signature `{ isActive: Boolean }`.

**isActivatedOnTouch** : Boolean - Activate immediately on touch. Scrolling may not be possible when scroll
gesture begins on target area. Recommended only when scrolling is not an expected use case. Defaults to false.
**onPositionChanged** : Function - Called when cursor or touch position changes.
Function receives one parameter with the signature `{ elementDimensions: { width: Number, height: Number }, isPositionOutside: Boolean, position: { x: Number, y: Number } }`.

**onDetectedEnvironmentChanged** : Function - Called when detected environment (mouse or touch) changes.
Function receives one parameter with the signature `{ isMouseDetected: Boolean, isTouchDetected: Boolean }`.

**pressDuration** : Number - Milliseconds delay before press gesture is activated. Defaults to 500.

**pressMoveThreshold** : Number - Amount of movement, in pixels, allowed during press gesture detection. Defaults to 5.

**shouldDecorateChildren** : Boolean - Suppress decoration of child components by
setting this prop false. Defaults to true.

**style** : Object - Style to be applied to the div rendered by react-cursor-position.

See API Examples section of the [demo site](https://ethanselzer.github.io/react-cursor-position/#/) for more.

## Support
Expand Down
19 changes: 9 additions & 10 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
{
"name": "react-cursor-position-example",
"version": "0.1.0",
"version": "1.0.0",
"homepage": "http://ethanselzer.github.io/react-cursor-position",
"devDependencies": {
"react-scripts": "^0.9.5"
"react-scripts": "^1.0.10"
},
"dependencies": {
"bootstrap": "^3.3.7",
"highlightjs": "^9.10.0",
"prop-types": "^15.5.8",
"react": "^15.5.4",
"react-bootstrap": "^0.31.0",
"react-dom": "^15.5.4",
"react-helmet": "^5.0.3",
"react-image-magnify": "^1.4.8",
"prop-types": "^15.5.10",
"react": "^15.6.1",
"react-bootstrap": "^0.31.1",
"react-dom": "^15.6.1",
"react-helmet": "^5.1.3",
"react-image-magnify": "^1.8.0",
"react-router": "3.0.5",
"react-syntax-highlighter": "^5.5.2"
"react-syntax-highlighter": "^5.6.2"
},
"scripts": {
"start": "react-scripts start",
Expand Down
38 changes: 38 additions & 0 deletions example/public/hover-delay.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//cdn.jsdelivr.net/highlight.js/9.9.0/styles/solarized-light.min.css">
<script src="//cdn.jsdelivr.net/highlight.js/9.9.0/highlight.min.js"></script>
<link rel="stylesheet" href="styles.css">
<title>Class Name | Code Example | React Cursor Position</title>
</head>
<body>
<pre>
<code>
import React from 'react';
import ReactCursorPosition from 'react-cursor-position';

import PositionLabel from './PositionLabel';
import InstructionsLabel from './InstructionsLabel';

export default () => (
&lt;ReactCursorPosition
className="example__target"
hoverDelayInMs={1000}
hoverOffDelayInMs={500}
&gt;
&lt;PositionLabel /&gt;
&lt;InstructionsLabel /&gt;
&lt;/ReactCursorPosition&gt;
);
</code>
</pre>

<script>
hljs.initHighlightingOnLoad();
</script>

</body>
</html>
50 changes: 50 additions & 0 deletions example/public/on-detected-environment-changed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//cdn.jsdelivr.net/highlight.js/9.9.0/styles/solarized-light.min.css">
<script src="//cdn.jsdelivr.net/highlight.js/9.9.0/highlight.min.js"></script>
<link rel="stylesheet" href="styles.css">
<title>On Detected Environment Changed | Code Example | React Cursor Position</title>
</head>
<body>
<pre>
<code class="JavaScript">
import React from 'react';
import ReactCursorPosition from 'react-cursor-position';

import DetectedEnvironmentChangeLabel from './DetectedEnvironmentChangeLabel';
import InstructionsLabel from './InstructionsLabel';

export default class extends React.Component {
constructor(props) {
super(props);
this.state = { detectedEnvironment: {} };
}

render() {
return (
&lt;div className="example"&gt;
&lt;ReactCursorPosition {...{
className: 'example__target',
onDetectedEnvironmentChanged: (detectedEnvironment) =&gt; {
this.setState({ detectedEnvironment });
}
}}&gt;
&lt;InstructionsLabel /&gt;
&lt;/ReactCursorPosition&gt;
&lt;DetectedEnvironmentChangeLabel {...this.state} /&gt;
&lt;/div&gt;
);
}
}
</code>
</pre>

<script>
hljs.initHighlightingOnLoad();
</script>

</body>
</html>
4 changes: 2 additions & 2 deletions example/src/components/ActivationChanged.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import ReactCursorPosition from '../../../dist/ReactCursorPosition';
import ReactCursorPosition from '../pkg-lnk/ReactCursorPosition';
import ActivationChangedLabel from './ActivationChangedLabel';
import InstructionsLabel from './InstructionsLabel';

Expand All @@ -20,7 +20,7 @@ export default class extends React.Component {
this.setState({ isActive });
}
}}>
<InstructionsLabel className="example__instructions--center"/>
<InstructionsLabel className="example__instructions example__instructions--solo"/>
</ReactCursorPosition>
<ActivationChangedLabel {...this.state} />
</div>
Expand Down
16 changes: 7 additions & 9 deletions example/src/components/BasicExample.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import React from 'react';
import ReactCursorPosition from '../../../dist/ReactCursorPosition';
import ReactCursorPosition from '../pkg-lnk/ReactCursorPosition';

import PositionLabel from './PositionLabel';
import InstructionsLabel from './InstructionsLabel';

export default class extends React.Component {
render() {
return (
<div className="example">
<ReactCursorPosition {...{
className: 'example__target example__target--basic'
}}>
<PositionLabel />
<InstructionsLabel className="example__instructions--low" />
</ReactCursorPosition>
</div>
<ReactCursorPosition {...{
className: 'example__target example__target--basic'
}}>
<PositionLabel />
<InstructionsLabel className="example__instructions" />
</ReactCursorPosition>
);
}
}
2 changes: 1 addition & 1 deletion example/src/components/ClassName.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import ReactCursorPosition from '../../../dist/ReactCursorPosition';
import ReactCursorPosition from '../pkg-lnk/ReactCursorPosition';
import PositionLabel from './PositionLabel';
import InstructionsLabel from './InstructionsLabel';

Expand Down
29 changes: 29 additions & 0 deletions example/src/components/DetectedEnvironmentChanged.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import ReactCursorPosition from '../pkg-lnk/ReactCursorPosition';
import DetectedEnvironmentChangedLabel from './DetectedEnvironmentChangedLabel';
import InstructionsLabel from './InstructionsLabel';

export default class extends React.Component {
constructor(props) {
super(props);
this.state = {
detectedEnvironment: {}
};
}

render() {
return (
<div className="example">
<ReactCursorPosition {...{
className: 'example__target',
onDetectedEnvironmentChanged: (detectedEnvironment) => {
this.setState({ detectedEnvironment });
}
}}>
<InstructionsLabel className="example__instructions example__instructions--solo"/>
</ReactCursorPosition>
<DetectedEnvironmentChangedLabel {...this.state} />
</div>
);
}
}
16 changes: 16 additions & 0 deletions example/src/components/DetectedEnvironmentChangedLabel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

export default (props) => {
const {
detectedEnvironment: {
isMouseDetected = false,
isTouchDetected = false
} = {}
} = props;
return (
<div className="example__external-label">
{`isMouseDetected: ${isMouseDetected ? 'true' : 'false'}`}<br />
{`isTouchDetected: ${isTouchDetected ? 'true' : 'false'}`}
</div>
);
}
12 changes: 9 additions & 3 deletions example/src/components/Header.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import { MenuItem, Navbar, Nav, NavItem, NavDropdown } from 'react-bootstrap';

import npmLogo from '../../images/npm-logo.png';
import githubLogo from '../../images/github-logo.png';
import npmLogo from '../images/npm-logo.png';
import githubLogo from '../images/github-logo.png';

import '../../styles/header.css';
import '../styles/header.css';

class Navigation extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -45,6 +45,10 @@ class Navigation extends React.Component {
return 2.8;
case '/on-activation-changed' :
return 2.9;
case '/hover-delay' :
return 2.11;
case '/detected-environment-changed' :
return 2.12;
case '/image-magnify' :
return 3.1;
case '/support' :
Expand All @@ -70,8 +74,10 @@ class Navigation extends React.Component {
<NavItem eventKey={1} href="#/">Home</NavItem>
<NavDropdown eventKey={2} title="API Examples" id="nav-dropdown">
<MenuItem eventKey={2.4} href="#/class-name">Class Name</MenuItem>
<MenuItem eventKey={2.11} href="#/hover-delay">Hover Delay</MenuItem>
<MenuItem eventKey={2.6} href="#/is-activated-on-touch">Is Activated On Touch</MenuItem>
<MenuItem eventKey={2.1} href="#/map-child-props">Map Child Props</MenuItem>
<MenuItem eventKey={2.12} href="#/detected-environment-changed">On Detected Environment Changed</MenuItem>
<MenuItem eventKey={2.2} href="#/on-position-changed">On Position Changed</MenuItem>
<MenuItem eventKey={2.9} href="#/on-activation-changed">On Activation Changed</MenuItem>
<MenuItem eventKey={2.7} href="#/press-duration">Press Duration</MenuItem>
Expand Down
18 changes: 18 additions & 0 deletions example/src/components/HoverDelay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import ReactCursorPosition from '../pkg-lnk/ReactCursorPosition';
import PositionLabel from './PositionLabel';
import InstructionsLabel from './InstructionsLabel';

export default () => (
<ReactCursorPosition
className="example__target"
hoverDelayInMs={1000}
hoverOffDelayInMs={500}
>
<PositionLabel />
<div className="example__instructions">
<InstructionsLabel />
</div>
</ReactCursorPosition>
);

2 changes: 1 addition & 1 deletion example/src/components/IsActivatedOnTouch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import ReactCursorPosition from '../../../dist/ReactCursorPosition';
import ReactCursorPosition from '../pkg-lnk/ReactCursorPosition';
import PositionLabel from './PositionLabel';

export default () => (
Expand Down
Loading

0 comments on commit 2e60d5b

Please sign in to comment.