Skip to content

Commit

Permalink
Merge pull request #563 from blackLearning/feature/useClickAway
Browse files Browse the repository at this point in the history
feat: support multiple target on useClickAway
  • Loading branch information
awmleer authored Aug 7, 2020
2 parents ec1fd08 + 70ebfe3 commit 2ac1967
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 9 deletions.
21 changes: 21 additions & 0 deletions packages/hooks/src/useClickAway/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,25 @@ describe('useClickAway', () => {
document.body.click();
expect(state).toEqual(2);
});

it('should works on multiple target', async () => {
let state: number = 0;
const { rerender, unmount } = renderHook((dom: any) =>
useClickAway(() => {
state++;
}, dom),
);

rerender([container, container1]);
container.click();
expect(state).toEqual(0);
container1.click();
expect(state).toEqual(0);
document.body.click();
expect(state).toEqual(1);

unmount();
document.body.click();
expect(state).toEqual(1);
});
});
31 changes: 31 additions & 0 deletions packages/hooks/src/useClickAway/demo/demo3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* title: Custom multiple DOM target
* desc: Support pass multiple DOM elements, or functions which returns the DOM element.
*
* title.zh-CN: 支持多个 DOM 对象
* desc.zh-CN: 支持传入多个目标对象。
*/

import React, { useState, useRef } from 'react';
import useClickAway from '../index';

export default () => {
const [counter, setCounter] = useState(0);
const ref1 = useRef();
const ref2 = useRef();
useClickAway(() => {
setCounter((s) => s + 1);
}, [ref1, ref2]);

return (
<div>
<button type="button" ref={ref1}>
box1
</button>
<button type="button" ref={ref2}>
box2
</button>
<p>counter: {counter}</p>
</div>
);
};
7 changes: 5 additions & 2 deletions packages/hooks/src/useClickAway/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ A hook that elegantly manages click outside of target elements.

<code src="./demo/demo2.tsx" />

<code src="./demo/demo3.tsx" />

## API

```ts
useClickAway(
onClickAway: (event: MouseEvent | TouchEvent) => void,
target: (() => HTMLElement) | HTMLElement | React.MutableRefObject,
target: (() => HTMLElement) | HTMLElement | React.MutableRefObject |
((() => HTMLElement) | HTMLElement | React.MutableRefObject)[],
);
```

Expand All @@ -36,4 +39,4 @@ useClickAway(
| Property | Description | Type | Default |
|---------|----------------------------------------------|------------------------|--------|
| onClickAway | Trigger Function | (event) => void | - |
| target | DOM element or Ref Object | (() => HTMLElement) \| HTMLElement \| React.MutableRefObject | - |
| target | DOM elements or Ref Objects | (() => HTMLElement) \| HTMLElement \| React.MutableRefObject \| ((() => HTMLElement) \| HTMLElement \| React.MutableRefObject)[] | - |
15 changes: 10 additions & 5 deletions packages/hooks/src/useClickAway/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@ type EventType = MouseEvent | TouchEvent;

export default function useClickAway(
onClickAway: (event: EventType) => void,
target: BasicTarget,
target: BasicTarget | BasicTarget[],
eventName: string = defaultEvent,
) {
const handler = useCallback(
(event) => {
const targetElement = getTargetElement(target) as HTMLElement;

if (!targetElement || targetElement.contains(event.target)) {
const targets = Array.isArray(target) ? target : [target];
const targetElements = targets.map((targetItem) =>
getTargetElement(targetItem),
) as HTMLElement[];
if (
targetElements.some(
(targetElement) => !targetElement || targetElement.contains(event.target),
)
) {
return;
}

onClickAway(event);
},
[onClickAway, typeof target === 'function' ? undefined : target],
Expand Down
7 changes: 5 additions & 2 deletions packages/hooks/src/useClickAway/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ legacy: /zh-CN/dom/use-click-away

<code src="./demo/demo2.tsx" />

<code src="./demo/demo3.tsx" />

## API

```ts
useClickAway(
onClickAway: (event: MouseEvent | TouchEvent) => void,
target: (() => HTMLElement) | HTMLElement | React.MutableRefObject,
target: (() => HTMLElement) | HTMLElement | React.MutableRefObject |
((() => HTMLElement) | HTMLElement | React.MutableRefObject)[],
);
```

Expand All @@ -34,4 +37,4 @@ useClickAway(
| 参数 | 说明 | 类型 | 默认值 |
|---------|----------------------------------------------|------------------------|--------|
| onClickAway | 触发事件的函数 | (event) => void | - |
| target | DOM 节点或者 Ref 对象 | (() => HTMLElement) \| HTMLElement \| React.MutableRefObject | - |
| target | DOM 节点或者 Ref 对象,支持数组 | (() => HTMLElement) \| HTMLElement \| React.MutableRefObject \| ((() => HTMLElement) \| HTMLElement \| React.MutableRefObject)[] | - |

0 comments on commit 2ac1967

Please sign in to comment.