Skip to content

Commit

Permalink
✨ (@hzcore/hook-press) add hook-press
Browse files Browse the repository at this point in the history
Ref GH-24
  • Loading branch information
elainen committed Apr 22, 2019
1 parent d0de573 commit 73ec14d
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 0 deletions.
4 changes: 4 additions & 0 deletions packages/behaviors/hzcore-hook-press/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
165 changes: 165 additions & 0 deletions packages/behaviors/hzcore-hook-press/README.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
---
name: usePress
menu: Hooks
route: /use-press
---

import {Playground} from 'docz';
import {useState} from 'react';
import usePress from '@hzcore/hook-press';

# usePress

A [hook] that tracks events when the user presses the mouse button over a component.

Main features:
- Determines when an element is being pressed
- Records the number of times an element has been pressed
- Consumes a callback handler when an element is pressed

---

## Installation

```shell
yarn add @hzcore/hook-press
```

---

## Options
```js
const {isPressed, pressCount, pressibleEl, pressProps} = usePress({defaultCount, handler});

interface UsePressReturn {
// If element is pressed
isPressed: boolean;

// Number of how many times the element was pressed
pressCount: number;

// Listeners of the press event
pressProps: PressPropsReturn;

// Element reference
pressibleEl: object;
}

interface UsePressProps {
// Default count number to start from, optional, default = 0
defaultCount: number;

// Direct handler attached to the element, optional, default = null
handler: (args: {isPressed: boolean, pressCount: number}) => void;
}
```

---

## Usage

### Simple Usage
```js
export default Button = () => {
const {isPressed, pressProps} = usePress();
return (
<button
style={{background: isPressed ? 'orange' : 'gray'}}
{...pressProps}
>
Press Me
</button>
);
}
```

### Using Count
<Playground>
{() => {

const plainStyles = {
color: 'white',
padding: '10px 20px',
fontSize: '16px',
borderRadius: '3px',
outline: 'none',
cursor: 'pointer',
}

const Button = () => {

const {isPressed, pressCount, pressProps} = usePress({defaultCount: 7});

return (
<>
<button
style={{
background: isPressed ? '#f38230' : '#43454d',
...plainStyles,
}}
{...pressProps}
ref={null}
>
Press Me
</button>
<p>I have been pressed {pressCount} time{pressCount > 1 ? 's': ''}.</p>
</>
);
}

return <Button />;
}}
</Playground>


### Using Handlers
<Playground>
{() => {

const plainStyles = {
color: 'white',
padding: '10px 20px',
fontSize: '16px',
borderRadius: '3px',
outline: 'none',
cursor: 'pointer',
}

const Button = () => {
// Saving the current color of the button
const [color, setColor] = useState('#43454d');

// Generate and set a random color for the button when clicked
const handleClick = (event, args) => {
const newColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
setColor(newColor);
}

// Setting press features with a default count number as 1
// and attaching the handler specific to this press
const {pressCount, pressProps} = usePress({handler: handleClick});

return (
<>
<button
style={{
background: color,
...plainStyles,
}}
{...pressProps}
>
Press Me
</button>
<p>I have been pressed {pressCount} time{pressCount > 1 ? 's': ''}.</p>
</>
)
}

return <Button />;
}}
</Playground>




[hook]: https://reactjs.org/docs/hooks-overview.html
14 changes: 14 additions & 0 deletions packages/behaviors/hzcore-hook-press/__tests__/usePress_test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* eslint-env jest, browser */
import React from 'react';
import {render} from 'react-testing-library';
import usePress from '../src';

test('usePress is implemented', () => {
const PressUser = (): JSX.Element => {
usePress();
return <div />;
}
const {container} = render(<PressUser />);
expect(container).toBeInTheDocument();
throw new Error('implement usePress and write some tests!');
});
17 changes: 17 additions & 0 deletions packages/behaviors/hzcore-hook-press/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "@hzcore/hook-press",
"version": "0.0.1",
"main": "cjs/index.js",
"module": "es/index.js",
"typings": "src/index.tsx",
"license": "MIT",
"publishConfig": {
"registry": "http://npmregistry.hzdg.com"
},
"files": [
"cjs",
"es",
"src",
"!*/__test*"
]
}
51 changes: 51 additions & 0 deletions packages/behaviors/hzcore-hook-press/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {useState, useEffect, useRef} from 'react';

interface UsePressReturn {
isPressed: boolean;
pressCount: number;
pressProps: {
onMouseDown: () => void;
onMouseUp: () => void;
};
pressibleEl: React.MutableRefObject<JSX.Element | null>;
}

const usePress = (props: {
defaultCount: number;
handler: (args: {isPressed: boolean; pressCount: number}) => void | null;
}): UsePressReturn => {
const {defaultCount, handler} = props;
const [isPressed, setIsPressed] = useState(false);
const [pressCount, setPressCount] = useState(defaultCount);
const pressibleEl = useRef(null);

const pressProps = {
ref: pressibleEl,
onMouseDown: () => {
if (!isPressed) {
setIsPressed(true);
setPressCount(pressCount + 1);
}
},
onMouseUp: () => {
if (isPressed) {
setIsPressed(false);
}
},
};

useEffect(() => {
if (handler && isPressed) {
handler.call(pressibleEl, {isPressed, pressCount});
}
}, [isPressed, pressCount]);

return {isPressed, pressCount, pressProps, pressibleEl};
};

usePress.defaultProps = {
defaultCount: 0,
handler: null,
};

export default usePress;

0 comments on commit 73ec14d

Please sign in to comment.