-
Notifications
You must be signed in to change notification settings - Fork 68
feat(hooks): add useLongPress hook #239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
86e7b47
feat: implement useLongPress hook with mouse and touch event handling
jiji-hoon96 07dca60
feat: add useLongPress hook with mouse and touch event handling
jiji-hoon96 241f0c9
docs: add useLongPress hook documentation
jiji-hoon96 d71ef65
fix : hasThreshold remove
jiji-hoon96 1147529
chore: remove Korean comment and unnecessary short press description …
jiji-hoon96 f963a83
Merge branch 'main' into feat/useLongPress-hook
seungrodotlee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { useLongPress } from './useLongPress.ts'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| # useLongPress | ||
|
|
||
| `useLongPress`는 요소가 지정된 시간 동안 눌리고 유지되는 것을 감지하는 리액트 훅이에요. 마우스와 터치 이벤트를 모두 처리하여 데스크톱과 모바일 기기에서 일관되게 작동해요. | ||
|
|
||
| ## 인터페이스 | ||
|
|
||
| ```ts | ||
| function useLongPress<E extends HTMLElement>( | ||
| onLongPress: (event: React.MouseEvent<E> | React.TouchEvent<E>) => void, | ||
| options: UseOptionsObject | ||
| ): Object; | ||
| ``` | ||
|
|
||
| ### 파라미터 | ||
|
|
||
| <Interface | ||
| required | ||
| name="onLongPress" | ||
| type="(event: React.MouseEvent<E> | React.TouchEvent<E>) => void" | ||
| description="길게 누르기가 감지될 때 실행되는 콜백 함수예요." | ||
| /> | ||
| <Interface | ||
| name="options" | ||
| type="Object" | ||
| description="길게 누르기 동작을 설정하는 옵션이에요." | ||
| :nested="[ | ||
| { | ||
| name: 'options.delay', | ||
| type: 'number', | ||
| required: false, | ||
| defaultValue: '500', | ||
| description: '길게 누르기를 트리거하기 전 시간(밀리초)이에요. 기본값은 500ms예요.' | ||
| }, | ||
| { | ||
| name: 'options.moveThreshold', | ||
| type: 'Object', | ||
| required: false, | ||
| description: '길게 누르기를 취소하기 전에 허용되는 최대 이동 거리예요.' | ||
| }, | ||
| { | ||
| name: 'options.moveThreshold.x', | ||
| type: 'number', | ||
| required: false, | ||
| description: '최대 수평 이동 거리(픽셀)예요.' | ||
| }, | ||
| { | ||
| name: 'options.moveThreshold.y', | ||
| type: 'number', | ||
| required: false, | ||
| description: '최대 수직 이동 거리(픽셀)예요.' | ||
| }, | ||
| { | ||
| name: 'options.onClick', | ||
| type: '(event) => void', | ||
| required: false, | ||
| description: '일반 클릭(지연 시간 전에 누르고 떼기)에 실행되는 선택적 함수예요.' | ||
| }, | ||
| { | ||
| name: 'options.onLongPressEnd', | ||
| type: '(event) => void', | ||
| required: false, | ||
| description: '길게 누르기가 끝날 때 실행되는 선택적 함수예요.' | ||
| } | ||
| ]" | ||
| /> | ||
|
|
||
| ### 반환 값 | ||
|
|
||
| <Interface | ||
| name="" | ||
| type="Object" | ||
| description="JSX 요소에 전달할 이벤트 핸들러가 포함된 객체예요." | ||
| :nested="[ | ||
| { | ||
| name: 'onMouseDown', | ||
| type: 'function', | ||
| description: '마우스 다운 이벤트 핸들러예요.' | ||
| }, | ||
| { | ||
| name: 'onMouseUp', | ||
| type: 'function', | ||
| description: '마우스 업 이벤트 핸들러예요.' | ||
| }, | ||
| { | ||
| name: 'onMouseLeave', | ||
| type: 'function', | ||
| description: '마우스 리브 이벤트 핸들러예요.' | ||
| }, | ||
| { | ||
| name: 'onTouchStart', | ||
| type: 'function', | ||
| description: '터치 시작 이벤트 핸들러예요.' | ||
| }, | ||
| { | ||
| name: 'onTouchEnd', | ||
| type: 'function', | ||
| description: '터치 종료 이벤트 핸들러예요.' | ||
| }, | ||
| { | ||
| name: 'onTouchMove', | ||
| type: 'function', | ||
| description: '터치 이동 이벤트 핸들러예요 (moveThreshold가 지정된 경우에만 포함).' | ||
| }, | ||
| { | ||
| name: 'onMouseMove', | ||
| type: 'function', | ||
| description: '마우스 이동 이벤트 핸들러예요 (moveThreshold가 지정된 경우에만 포함).' | ||
| } | ||
| ]" | ||
| /> | ||
|
|
||
| ## 예시 | ||
|
|
||
| ```tsx | ||
| import { useLongPress } from 'react-simplikit'; | ||
| import { useState } from 'react'; | ||
|
|
||
| function ContextMenu() { | ||
| const [menuVisible, setMenuVisible] = useState(false); | ||
|
|
||
| const longPressHandlers = useLongPress(() => setMenuVisible(true), { | ||
| delay: 400, | ||
| onClick: () => console.log('일반 클릭'), | ||
| onLongPressEnd: () => console.log('길게 누르기 완료'), | ||
| }); | ||
|
|
||
| return ( | ||
| <div> | ||
| <button {...longPressHandlers}>길게 누르세요</button> | ||
| {menuVisible && <div className="context-menu">컨텍스트 메뉴</div>} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| # useLongPress | ||
|
|
||
| `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. | ||
|
|
||
| ## Interface | ||
|
|
||
| ```ts | ||
| function useLongPress<E extends HTMLElement>( | ||
| onLongPress: (event: React.MouseEvent<E> | React.TouchEvent<E>) => void, | ||
| options: UseOptionsObject | ||
| ): Object; | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| <Interface | ||
| required | ||
| name="onLongPress" | ||
| type="(event: React.MouseEvent<E> | React.TouchEvent<E>) => void" | ||
| description="The callback function to be executed when a long press is detected." | ||
| /> | ||
| <Interface | ||
| name="options" | ||
| type="Object" | ||
| description="Configuration options for the long press behavior." | ||
| :nested="[ | ||
| { | ||
| name: 'options.delay', | ||
| type: 'number', | ||
| required: false, | ||
| defaultValue: '500', | ||
| description: 'The time in milliseconds before triggering the long press. Defaults to 500ms.' | ||
| }, | ||
| { | ||
| name: 'options.moveThreshold', | ||
| type: 'Object', | ||
| required: false, | ||
| description: 'Maximum movement allowed before canceling a long press.' | ||
| }, | ||
| { | ||
| name: 'options.moveThreshold.x', | ||
| type: 'number', | ||
| required: false, | ||
| description: 'Maximum horizontal movement in pixels.' | ||
| }, | ||
| { | ||
| name: 'options.moveThreshold.y', | ||
| type: 'number', | ||
| required: false, | ||
| description: 'Maximum vertical movement in pixels.' | ||
| }, | ||
| { | ||
| name: 'options.onClick', | ||
| type: '(event) => void', | ||
| required: false, | ||
| description: 'Optional function to execute on a normal click (press and release before delay).' | ||
| }, | ||
| { | ||
| name: 'options.onLongPressEnd', | ||
| type: '(event) => void', | ||
| required: false, | ||
| description: 'Optional function to execute when a long press ends.' | ||
| } | ||
| ]" | ||
| /> | ||
|
|
||
| ### Return Value | ||
|
|
||
| <Interface | ||
| name="" | ||
| type="Object" | ||
| description="An object containing event handlers to spread onto a JSX element." | ||
| :nested="[ | ||
| { | ||
| name: 'onMouseDown', | ||
| type: 'function', | ||
| description: 'Handler for mouse down events.' | ||
| }, | ||
| { | ||
| name: 'onMouseUp', | ||
| type: 'function', | ||
| description: 'Handler for mouse up events.' | ||
| }, | ||
| { | ||
| name: 'onMouseLeave', | ||
| type: 'function', | ||
| description: 'Handler for mouse leave events.' | ||
| }, | ||
| { | ||
| name: 'onTouchStart', | ||
| type: 'function', | ||
| description: 'Handler for touch start events.' | ||
| }, | ||
| { | ||
| name: 'onTouchEnd', | ||
| type: 'function', | ||
| description: 'Handler for touch end events.' | ||
| }, | ||
| { | ||
| name: 'onTouchMove', | ||
| type: 'function', | ||
| description: 'Handler for touch move events (only included when moveThreshold is specified).' | ||
| }, | ||
| { | ||
| name: 'onMouseMove', | ||
| type: 'function', | ||
| description: 'Handler for mouse move events (only included when moveThreshold is specified).' | ||
| } | ||
| ]" | ||
| /> | ||
|
|
||
| ## Example | ||
|
|
||
| ```tsx | ||
| import { useLongPress } from 'react-simplikit'; | ||
| import { useState } from 'react'; | ||
|
|
||
| function ContextMenu() { | ||
| const [menuVisible, setMenuVisible] = useState(false); | ||
|
|
||
| const longPressHandlers = useLongPress(() => setMenuVisible(true), { | ||
| delay: 400, | ||
| onClick: () => console.log('Normal click'), | ||
| onLongPressEnd: () => console.log('Long press completed'), | ||
| }); | ||
|
|
||
| return ( | ||
| <div> | ||
| <button {...longPressHandlers}>Press and hold</button> | ||
| {menuVisible && <div className="context-menu">Context Menu</div>} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jiji-hoon96
Thank you for your hard work in writing the documentation. Just a quick tip — in
react-simplikit, documentation is automatically generated fromJSDocusingdeploymentaction'sgenerate-docsafter merged! You might find the link below helpful:Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for forwarding the documentation guide!
I didn't look closely enough at the contribution guide as I was working on it.
I spent more time writing the docs than I realized...🥲