Skip to content

Commit d1977ac

Browse files
committed
✨ feat: useOutsideInteraction 개선
1 parent c4df0a4 commit d1977ac

File tree

10 files changed

+91
-70
lines changed

10 files changed

+91
-70
lines changed

src/hooks/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export { useLocalStorage } from './useLocalStorage';
1616
export { useLongPress } from './useLongPress';
1717
export { useMousePosition } from './useMousePosition';
1818
export { useOnlineStatus } from './useOnlineStatus';
19-
export { useOutsideInteraction } from './useOutsideInteraction';
19+
export { useOutsideClick } from './useOutsideClick';
2020
export { usePrefersColorScheme } from './usePrefersColorScheme';
2121
export { useScrollLock } from './useScrollLock';
2222
export { useScrollY } from './useScrollY';
@@ -27,3 +27,4 @@ export { useTranslation } from './useTranslation';
2727
export { useUnmountEffect } from './useUnmountEffect';
2828
export { useWindowSize } from './useWindowSize';
2929
export { useWorker } from './useWorker';
30+
export { useKeyDown } from './useKeyDown';

src/hooks/useKeyDown/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as useKeyDown } from './useKeyDown';

src/hooks/useKeyDown/type.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface UseKeyDownProps {
2+
key: string;
3+
onKeyPress: () => void;
4+
}

src/hooks/useKeyDown/useKeyDown.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useEffect } from 'react';
2+
import { UseKeyDownProps } from '@/hooks/useKeyDown/type';
3+
4+
/**
5+
* 주어진 키 입력에 대한 이벤트를 처리하는 훅
6+
*
7+
* @param {string} key - 감지할 키 값 (예: 'Escape', 'Enter' 등)
8+
* @param {() => void} onKeyPress - 지정된 키가 눌렸을 때 실행할 콜백 함수
9+
*
10+
* @returns {void}
11+
*/
12+
const useKeyDown = ({ key, onKeyPress }: UseKeyDownProps): void => {
13+
useEffect(() => {
14+
const handleKeyDown = (event: KeyboardEvent) => {
15+
if (event.key === key && !event.repeat) {
16+
onKeyPress();
17+
}
18+
};
19+
20+
document.addEventListener('keydown', handleKeyDown);
21+
return () => {
22+
document.removeEventListener('keydown', handleKeyDown);
23+
};
24+
}, [key, onKeyPress]);
25+
};
26+
27+
export default useKeyDown;

src/hooks/useOutsideClick/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as useOutsideClick } from './useOutsideClick';

src/hooks/useOutsideClick/type.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export type EventType = 'mousedown' | 'mouseup' | 'touchstart' | 'touchend';
2+
3+
export interface UseOutsideClickProps {
4+
onClickOutside: () => void;
5+
events?: EventType[];
6+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useCallback, useEffect, useRef, RefObject } from 'react';
2+
import { EventType, UseOutsideClickProps } from './type';
3+
4+
const defaultEvents: EventType[] = ['mousedown', 'touchstart'];
5+
6+
/**
7+
* 지정된 element 외부의 click event를 감지하는 hook
8+
* onClickOutside 함수를 통해 마우스 클릭 이벤트를 처리할 수 있습니다.
9+
*
10+
* @param {Object} props - hook props
11+
* @param {() => void} props.onClickOutside - 외부 interaction 발생 시 실행될 콜백 함수
12+
* @param {EventType[]} [props.events] - 감지할 이벤트 (default :['mousedown', 'touchstart'])
13+
*
14+
* @returns {React.RefObject<HTMLElement>} element에 연결할 ref 객체
15+
*/
16+
17+
const useOutsideClick = ({
18+
onClickOutside,
19+
events = defaultEvents,
20+
}: UseOutsideClickProps): RefObject<HTMLElement> => {
21+
const ref = useRef<HTMLElement>(null);
22+
23+
const handleClick = useCallback(
24+
(event: Event) => {
25+
const target = event.target as Node | null;
26+
if (!target) return;
27+
28+
if (ref.current && !ref.current.contains(target)) {
29+
onClickOutside();
30+
}
31+
},
32+
[onClickOutside]
33+
);
34+
35+
useEffect(() => {
36+
if (events.length === 0) return;
37+
38+
events.forEach((event) => document.addEventListener(event, handleClick));
39+
40+
return () => {
41+
events.forEach((event) =>
42+
document.removeEventListener(event, handleClick)
43+
);
44+
};
45+
}, [handleClick, events]);
46+
47+
return ref;
48+
};
49+
50+
export default useOutsideClick;

src/hooks/useOutsideInteraction/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/hooks/useOutsideInteraction/type.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/hooks/useOutsideInteraction/useOutsideInteraction.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)