Skip to content

Commit ae82195

Browse files
feat(hooks): add useLongPress hook (#239)
Co-authored-by: seungrodotlee <seungrodotlee@gmail.com>
1 parent d6cbe07 commit ae82195

5 files changed

Lines changed: 760 additions & 0 deletions

File tree

src/hooks/useLongPress/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { useLongPress } from './useLongPress.ts';
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# useLongPress
2+
3+
`useLongPress`는 요소가 지정된 시간 동안 눌리고 유지되는 것을 감지하는 리액트 훅이에요. 마우스와 터치 이벤트를 모두 처리하여 데스크톱과 모바일 기기에서 일관되게 작동해요.
4+
5+
## 인터페이스
6+
7+
```ts
8+
function useLongPress<E extends HTMLElement>(
9+
onLongPress: (event: React.MouseEvent<E> | React.TouchEvent<E>) => void,
10+
options: UseOptionsObject
11+
): Object;
12+
```
13+
14+
### 파라미터
15+
16+
<Interface
17+
required
18+
name="onLongPress"
19+
type="(event: React.MouseEvent<E> | React.TouchEvent<E>) => void"
20+
description="길게 누르기가 감지될 때 실행되는 콜백 함수예요."
21+
/>
22+
<Interface
23+
name="options"
24+
type="Object"
25+
description="길게 누르기 동작을 설정하는 옵션이에요."
26+
:nested="[
27+
{
28+
name: 'options.delay',
29+
type: 'number',
30+
required: false,
31+
defaultValue: '500',
32+
description: '길게 누르기를 트리거하기 전 시간(밀리초)이에요. 기본값은 500ms예요.'
33+
},
34+
{
35+
name: 'options.moveThreshold',
36+
type: 'Object',
37+
required: false,
38+
description: '길게 누르기를 취소하기 전에 허용되는 최대 이동 거리예요.'
39+
},
40+
{
41+
name: 'options.moveThreshold.x',
42+
type: 'number',
43+
required: false,
44+
description: '최대 수평 이동 거리(픽셀)예요.'
45+
},
46+
{
47+
name: 'options.moveThreshold.y',
48+
type: 'number',
49+
required: false,
50+
description: '최대 수직 이동 거리(픽셀)예요.'
51+
},
52+
{
53+
name: 'options.onClick',
54+
type: '(event) => void',
55+
required: false,
56+
description: '일반 클릭(지연 시간 전에 누르고 떼기)에 실행되는 선택적 함수예요.'
57+
},
58+
{
59+
name: 'options.onLongPressEnd',
60+
type: '(event) => void',
61+
required: false,
62+
description: '길게 누르기가 끝날 때 실행되는 선택적 함수예요.'
63+
}
64+
]"
65+
/>
66+
67+
### 반환 값
68+
69+
<Interface
70+
name=""
71+
type="Object"
72+
description="JSX 요소에 전달할 이벤트 핸들러가 포함된 객체예요."
73+
:nested="[
74+
{
75+
name: 'onMouseDown',
76+
type: 'function',
77+
description: '마우스 다운 이벤트 핸들러예요.'
78+
},
79+
{
80+
name: 'onMouseUp',
81+
type: 'function',
82+
description: '마우스 업 이벤트 핸들러예요.'
83+
},
84+
{
85+
name: 'onMouseLeave',
86+
type: 'function',
87+
description: '마우스 리브 이벤트 핸들러예요.'
88+
},
89+
{
90+
name: 'onTouchStart',
91+
type: 'function',
92+
description: '터치 시작 이벤트 핸들러예요.'
93+
},
94+
{
95+
name: 'onTouchEnd',
96+
type: 'function',
97+
description: '터치 종료 이벤트 핸들러예요.'
98+
},
99+
{
100+
name: 'onTouchMove',
101+
type: 'function',
102+
description: '터치 이동 이벤트 핸들러예요 (moveThreshold가 지정된 경우에만 포함).'
103+
},
104+
{
105+
name: 'onMouseMove',
106+
type: 'function',
107+
description: '마우스 이동 이벤트 핸들러예요 (moveThreshold가 지정된 경우에만 포함).'
108+
}
109+
]"
110+
/>
111+
112+
## 예시
113+
114+
```tsx
115+
import { useLongPress } from 'react-simplikit';
116+
import { useState } from 'react';
117+
118+
function ContextMenu() {
119+
const [menuVisible, setMenuVisible] = useState(false);
120+
121+
const longPressHandlers = useLongPress(() => setMenuVisible(true), {
122+
delay: 400,
123+
onClick: () => console.log('일반 클릭'),
124+
onLongPressEnd: () => console.log('길게 누르기 완료'),
125+
});
126+
127+
return (
128+
<div>
129+
<button {...longPressHandlers}>길게 누르세요</button>
130+
{menuVisible && <div className="context-menu">컨텍스트 메뉴</div>}
131+
</div>
132+
);
133+
}
134+
```
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# useLongPress
2+
3+
`useLongPress` is a React hook that detects when an element is pressed and held for a specified duration. It handles both mouse and touch events, making it work consistently across desktop and mobile devices.
4+
5+
## Interface
6+
7+
```ts
8+
function useLongPress<E extends HTMLElement>(
9+
onLongPress: (event: React.MouseEvent<E> | React.TouchEvent<E>) => void,
10+
options: UseOptionsObject
11+
): Object;
12+
```
13+
14+
### Parameters
15+
16+
<Interface
17+
required
18+
name="onLongPress"
19+
type="(event: React.MouseEvent<E> | React.TouchEvent<E>) => void"
20+
description="The callback function to be executed when a long press is detected."
21+
/>
22+
<Interface
23+
name="options"
24+
type="Object"
25+
description="Configuration options for the long press behavior."
26+
:nested="[
27+
{
28+
name: 'options.delay',
29+
type: 'number',
30+
required: false,
31+
defaultValue: '500',
32+
description: 'The time in milliseconds before triggering the long press. Defaults to 500ms.'
33+
},
34+
{
35+
name: 'options.moveThreshold',
36+
type: 'Object',
37+
required: false,
38+
description: 'Maximum movement allowed before canceling a long press.'
39+
},
40+
{
41+
name: 'options.moveThreshold.x',
42+
type: 'number',
43+
required: false,
44+
description: 'Maximum horizontal movement in pixels.'
45+
},
46+
{
47+
name: 'options.moveThreshold.y',
48+
type: 'number',
49+
required: false,
50+
description: 'Maximum vertical movement in pixels.'
51+
},
52+
{
53+
name: 'options.onClick',
54+
type: '(event) => void',
55+
required: false,
56+
description: 'Optional function to execute on a normal click (press and release before delay).'
57+
},
58+
{
59+
name: 'options.onLongPressEnd',
60+
type: '(event) => void',
61+
required: false,
62+
description: 'Optional function to execute when a long press ends.'
63+
}
64+
]"
65+
/>
66+
67+
### Return Value
68+
69+
<Interface
70+
name=""
71+
type="Object"
72+
description="An object containing event handlers to spread onto a JSX element."
73+
:nested="[
74+
{
75+
name: 'onMouseDown',
76+
type: 'function',
77+
description: 'Handler for mouse down events.'
78+
},
79+
{
80+
name: 'onMouseUp',
81+
type: 'function',
82+
description: 'Handler for mouse up events.'
83+
},
84+
{
85+
name: 'onMouseLeave',
86+
type: 'function',
87+
description: 'Handler for mouse leave events.'
88+
},
89+
{
90+
name: 'onTouchStart',
91+
type: 'function',
92+
description: 'Handler for touch start events.'
93+
},
94+
{
95+
name: 'onTouchEnd',
96+
type: 'function',
97+
description: 'Handler for touch end events.'
98+
},
99+
{
100+
name: 'onTouchMove',
101+
type: 'function',
102+
description: 'Handler for touch move events (only included when moveThreshold is specified).'
103+
},
104+
{
105+
name: 'onMouseMove',
106+
type: 'function',
107+
description: 'Handler for mouse move events (only included when moveThreshold is specified).'
108+
}
109+
]"
110+
/>
111+
112+
## Example
113+
114+
```tsx
115+
import { useLongPress } from 'react-simplikit';
116+
import { useState } from 'react';
117+
118+
function ContextMenu() {
119+
const [menuVisible, setMenuVisible] = useState(false);
120+
121+
const longPressHandlers = useLongPress(() => setMenuVisible(true), {
122+
delay: 400,
123+
onClick: () => console.log('Normal click'),
124+
onLongPressEnd: () => console.log('Long press completed'),
125+
});
126+
127+
return (
128+
<div>
129+
<button {...longPressHandlers}>Press and hold</button>
130+
{menuVisible && <div className="context-menu">Context Menu</div>}
131+
</div>
132+
);
133+
}
134+
```

0 commit comments

Comments
 (0)