Skip to content

Commit

Permalink
feat: 🎸 move extra mouse functionality into useMouseHovered
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Mar 26, 2019
1 parent 9bb02a1 commit 8b0580e
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .storybook/addons.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '@storybook/addon-knobs/register';
import '@storybook/addon-options/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-notes/register';
17 changes: 6 additions & 11 deletions src/__stories__/useMouse.story.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import * as React from 'react';
import {storiesOf} from '@storybook/react';
import {useMouse, useToggle} from '..';
import {useMouse} from '..';
import ShowDocs from '../util/ShowDocs';

const Demo = () => {
const [whenHovered, toggleWhenHovered] = useToggle(false);
const Demo: React.FC<any> = () => {
const ref = React.useRef(null);
const state = useMouse(ref, {whenHovered, bound: true})
const state = useMouse(ref)

return (
<>
<pre>
{JSON.stringify(state, null, 2)}
</pre>
<label>
<input type="checkbox" checked={whenHovered} onChange={() => toggleWhenHovered()} />
When hovered
</label>
<br />
<br />
<div
ref={ref}
style={{
Expand All @@ -40,6 +37,4 @@ const Demo = () => {

storiesOf('Sensors|useMouse', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useMouse.md')} />)
.add('Demo', () =>
<Demo/>
)
.add('Demo', () => <Demo />)
46 changes: 46 additions & 0 deletions src/__stories__/useMouseHovered.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';
import {storiesOf} from '@storybook/react';
import {withKnobs, boolean} from '@storybook/addon-knobs';
import {useMouseHovered} from '..';
import ShowDocs from '../util/ShowDocs';

const Demo: React.FC<any> = ({whenHovered, bound}) => {
const ref = React.useRef(null);
const state = useMouseHovered(ref, {whenHovered, bound})

return (
<>
<pre>
{JSON.stringify(state, null, 2)}
</pre>
<br />
<br />
<div
ref={ref}
style={{
position: 'relative',
width: '400px',
height: '400px',
backgroundColor: 'whitesmoke',
}}>
<span style={{
position: 'absolute',
left: `${state.elX}px`,
top: `${state.elY}px`,
pointerEvents: 'none',
transform: 'scale(4)'}}>
🐭
</span>
</div>
</>
);
};

storiesOf('Sensors|useMouseHovered', module)
.addDecorator(withKnobs)
.add('Docs', () => <ShowDocs md={require('../../docs/useMouse.md')} />)
.add('Demo', () => {
const bound = boolean('bound', false);
const whenHovered = boolean('whenHovered', false);
return <Demo whenHovered={whenHovered} bound={bound} />;
})
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import useMediaDevices from './useMediaDevices';
import useMotion from './useMotion';
import useMount from './useMount';
import useMouse from './useMouse';
import useMouseHovered from './useMouseHovered';
import useNetwork from './useNetwork';
import useNumber from './useNumber';
import useObservable from './useObservable';
Expand Down Expand Up @@ -86,6 +87,7 @@ export {
useMotion,
useMount,
useMouse,
useMouseHovered,
useNetwork,
useNumber,
useObservable,
Expand Down
25 changes: 7 additions & 18 deletions src/useMouse.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {useState, useEffect, useRef, RefObject} from 'react';
import useHoverDirty from "./useHoverDirty";

export interface State {
docX: number;
Expand All @@ -12,20 +11,14 @@ export interface State {
elW: number;
}

export interface UseMouseOptions {
whenHovered?: boolean;
bound?: boolean;
}

const useMouse = (ref: RefObject<HTMLElement>, {whenHovered = false, bound = false}: UseMouseOptions = {}): State => {
const useMouse = (ref: RefObject<HTMLElement>): State => {
if (process.env.NODE_ENV === 'development') {
if ((typeof ref !== 'object') || (typeof ref.current === 'undefined')) {
console.error('useMouse expects a single ref argument.');
}
}

const frame = useRef(0);
const isHovered = useHoverDirty(ref, whenHovered);
const [state, setState] = useState<State>({
docX: 0,
docY: 0,
Expand Down Expand Up @@ -54,26 +47,22 @@ const useMouse = (ref: RefObject<HTMLElement>, {whenHovered = false, bound = fal
docY: event.pageY,
posX,
posY,
elX: bound ? Math.max(0, Math.min(elX, elW)) : elX,
elY: bound ? Math.max(0, Math.min(elY, elH)) : elY,
elX,
elY,
elH,
elW,
});
}
});
}

if (isHovered || !whenHovered) {
document.addEventListener('mousemove', moveHandler);
}
document.addEventListener('mousemove', moveHandler);

return () => {
if (isHovered || !whenHovered) {
cancelAnimationFrame(frame.current);
document.removeEventListener('mousemove', moveHandler);
}
cancelAnimationFrame(frame.current);
document.removeEventListener('mousemove', moveHandler);
};
}, [isHovered, whenHovered, ref])
}, [ref.current])

return state;
}
Expand Down
27 changes: 27 additions & 0 deletions src/useMouseHovered.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {RefObject} from 'react';
import useHoverDirty from './useHoverDirty';
import useMouse, {State} from './useMouse';

export interface UseMouseHoveredOptions {
whenHovered?: boolean;
bound?: boolean;
}

const nullRef = {current: null};

const useMouseHovered = (ref: RefObject<HTMLElement>, options: UseMouseHoveredOptions = {}): State => {
const whenHovered = !!options.whenHovered;
const bound = !!options.bound;

const isHovered = useHoverDirty(ref, whenHovered);
const state = useMouse(whenHovered && !isHovered ? nullRef : ref);

if (bound) {
state.elX = Math.max(0, Math.min(state.elX, state.elW));
state.elY = Math.max(0, Math.min(state.elY, state.elH));
}

return state;
}

export default useMouseHovered;

0 comments on commit 8b0580e

Please sign in to comment.