Skip to content

Commit 7878b0f

Browse files
committed
Merge remote-tracking branch 'origin/master' into URH-103
2 parents 3613866 + 689f0b4 commit 7878b0f

29 files changed

+727
-88
lines changed

docs/pages/docs/hooks/_meta.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
{
2+
"useConfirm": "useConfirm",
3+
"useDeepCompareEffect": "useDeepCompareEffect",
24
"useDelayFlag": "useDelayFlag",
5+
"useDetectDevice": "useDetectDevice",
6+
"useKeyCombination": "useKeyCombination",
7+
"useLongPress": "useLongPress",
38
"useMousePosition": "useMousePosition",
9+
"useScrollLock": "useScrollLock",
10+
"useSound": "useSound",
411
"useTimer": "useTimer",
12+
"useToggle": "useToggle",
513
"useTranslation": "useTranslation"
614
}

docs/pages/docs/hooks/useConfirm.mdx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# useConfirm
2+
3+
## Introduce
4+
5+
- 컨펌 로직을 담고 있는 훅입니다.
6+
- 컨펌 다이얼로그를 구현할 때 유용하게 사용할 수 있습니다.
7+
8+
```ts
9+
interface UseConfirmReturns {
10+
message?: string;
11+
isOpen: boolean;
12+
confirm: (message: string) => Promise<boolean>;
13+
onConfirm: () => void;
14+
onCancel: () => void;
15+
}
16+
17+
const useConfirm = (): UseConfirmReturns
18+
```
19+
20+
### Returns
21+
22+
- `message`: 컨펌 메시지. confirm() 함수에 전달된 값을 그대로 반환.
23+
- `isOpen`: 컨펌 다이얼로그 open/close 상태를 제어할 수 있는 값. confirm() 함수 실행 단계에서 message를 체크하여 값을 반환.
24+
- `confirm`: 컨펌 로직을 실행하는 비동기 함수. 컨펌 다이얼로그를 열고 사용자의 컨펌 여부를 반환.
25+
- `onConfirm`: 컨펌을 실행하는 함수.
26+
- `onCancel`: 취소를 실행하는 함수.
27+
28+
## Examples
29+
30+
import { Callout } from 'nextra/components';
31+
32+
<Callout type="info">
33+
`useConfirm()`을 사용하기 전에 먼저 `ConfirmProvider`를 선언해야 합니다.
34+
</Callout>
35+
36+
```tsx copy filename="App.tsx"
37+
import { ConfirmProvider } from '@frontend-opensource/use-react-hooks';
38+
39+
function App() {
40+
return (
41+
<ConfirmProvider>
42+
<TestComponent />
43+
</ConfirmProvider>
44+
);
45+
}
46+
```
47+
48+
```tsx copy filename="TestComponent.tsx"
49+
import { useConfirm } from '@frontend-opensource/use-react-hooks';
50+
51+
const TestComponent = () => {
52+
const { message, isOpen, confirm, onConfirm, onCancel } = useConfirm();
53+
54+
const handleRemove = async () => {
55+
if (await confirm('정말 삭제하시겠습니까?')) {
56+
// 컨펌 로직
57+
} else {
58+
// 취소 로직
59+
}
60+
};
61+
62+
return (
63+
<>
64+
<button onClick={handleRemove}>삭제하기</button>
65+
66+
<Dialog open={isOpen}>
67+
<p>{message}</p>
68+
<button onClick={onConfirm}>확인</button>
69+
<button onClick={onCancel}>취소</button>
70+
</Dialog>
71+
</>
72+
);
73+
};
74+
```
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# useDeepCompareEffect
2+
3+
## Introduce
4+
5+
의존성 배열의 깊은 비교를 통해 변화를 감지하고 콜백을 실행시키는 훅입니다.
6+
7+
```ts
8+
const useDeepCompareEffect = (callback: () => void, dependencies: unknown[]) => void
9+
```
10+
11+
### Props
12+
13+
- `callback` : 의존성 배열의 변화가 감지되었을 때 실행할 콜백 함수
14+
- `dependencies` : 의존성 배열
15+
16+
## Examples
17+
18+
```tsx copy filename="TestComponent.tsx"
19+
function App() {
20+
const [, setCount] = useState(0);
21+
const effectCountRef = useRef(0);
22+
const deepCompareCountRef = useRef(0);
23+
24+
useEffect(() => {
25+
effectCountRef.current += 1;
26+
// 빈 객체는 매번 새로운 참조를 갖기 때문에 effectCount는 계속 증가
27+
}, [{}]);
28+
29+
useDeepCompareEffect(() => {
30+
deepCompareCountRef.current += 1;
31+
// 빈 객체를 같은 값으로 판단해 deepCompareCountRef는 한 번(첫 시도)만 증가
32+
}, [{}]);
33+
34+
return (
35+
<div>
36+
<p>effectCount: {effectCountRef.current}</p>
37+
<p>deepCompareCount: {deepCompareCountRef.current}</p>
38+
<p>
39+
<button type="button" onClick={() => setCount((c) => c + 1)}>
40+
리렌더링 발생
41+
</button>
42+
</p>
43+
</div>
44+
);
45+
}
46+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# useDetectDevice
2+
3+
## Introduce
4+
5+
현재 디바이스의 유형(moblie, desktop), OS 및 Browser를 감지합니다.
6+
7+
import { Callout } from 'nextra/components';
8+
9+
<Callout type="info">
10+
userAgent의 업데이트로 인하여 올바르게 작동하지 않을 수 있습니다. 유의해서
11+
사용해주세요.
12+
</Callout>
13+
14+
```ts
15+
interface UseDeviceDetectReturns {
16+
isMobile: boolean;
17+
isDesktop: boolean;
18+
os: string;
19+
browser: string;
20+
}
21+
22+
const useDetectDevice = (): UseDeviceDetectReturns
23+
```
24+
25+
### Returns
26+
27+
- `isMobile` : 사용 중인 디바이스의 Mobile 여부를 나타냅니다.
28+
- `isDesktop` : 사용 중인 디바이스의 Desktop 여부를 나타냅니다.
29+
- `os` : 사용 중인 디바이스의 OS 이름(문자열)을 나타냅니다.\
30+
cf) Windows, macOS, Linux, Android, iOS
31+
- `browser` : 사용 중인 브라우저의 이름(문자열)을 나타냅니다.\
32+
cf) Chrome, Safari, Whale, Edge, Firefox
33+
34+
## Examples
35+
36+
```tsx copy filename="TestComponent.tsx"
37+
const TestComponent = () => {
38+
39+
const { isMobile, os, browser } = useDeviceDetect();
40+
41+
return (
42+
<div>
43+
<div>
44+
{isMobile && (
45+
<>
46+
<div>모바일 환경에 최적화된 콘텐츠</div>
47+
<div>...</div>
48+
</>
49+
)}
50+
</div>
51+
);
52+
};
53+
```
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# useKeyCombination
2+
3+
## Introduce
4+
5+
지정된 키 조합을 눌렀을 때 콜백 함수를 호출하는 훅입니다.
6+
7+
- 지정된 키들을 모두 눌렀을 때 콜백 함수를 호출하며, 필요에 따라 기본 동작을 막을 수도 있습니다.
8+
- 예를 들어, `Ctrl + K` 키 조합을 감지하여 특정 작업을 실행하고자 할 때 사용할 수 있습니다.
9+
10+
```ts
11+
interface UseKeyCombinationProps {
12+
shortcutKeys: string[];
13+
callback: () => void;
14+
isPrevent?: boolean;
15+
}
16+
17+
const useKeyCombination = ({
18+
shortcutKeys,
19+
callback,
20+
isPrevent = false,
21+
}: UseKeyCombinationProps): void
22+
```
23+
24+
### Props
25+
26+
- `shortcutKeys` : 키 조합을 나타내는 키 코드의 배열
27+
- `callback` : 키 조합이 감지되었을 때 실행할 콜백 함수
28+
- `isPrevent` : true로 설정하면 키 조합이 눌렸을 때 기본 동작 방지 (기본값: false)
29+
30+
## Examples
31+
32+
```tsx copy filename="TestComponent.tsx"
33+
import { useCallback, useRef, useState } from 'react';
34+
import useKeyCombination from './hooks/useKeyCombination';
35+
36+
function TestComponent() {
37+
const [bold, setBold] = useState(false);
38+
const [isSave, setIsSave] = useState(false);
39+
const input = useRef<HTMLInputElement>(null);
40+
41+
const keyActions = {
42+
toggleBold: {
43+
shortcutKeys: ['ControlLeft', 'KeyB'],
44+
callback: useCallback(() => {
45+
setBold((state) => !state);
46+
}, [setBold]),
47+
},
48+
save: {
49+
shortcutKeys: ['MetaLeft', 'KeyS'],
50+
callback: useCallback(() => setIsSave((state) => !state), [setIsSave]),
51+
isPrevent: true,
52+
},
53+
search: {
54+
shortcutKeys: ['MetaLeft', 'KeyK'],
55+
callback: useCallback(() => input.current?.focus(), []),
56+
},
57+
};
58+
59+
useKeyCombination(keyActions.toggleBold);
60+
useKeyCombination(keyActions.save);
61+
useKeyCombination(keyActions.search);
62+
63+
return (
64+
<div>
65+
<input type="text" ref={input} placeholder="Press command + K" />
66+
<div>USE-REACT-HOOKS</div>
67+
<ul>
68+
<li style={{ fontWeight: bold ? 'bold' : 'normal' }}>
69+
command + B : Bold
70+
</li>
71+
<li>command + S: {isSave ? 'SAVE!' : 'Not saved yet'}</li>
72+
</ul>
73+
</div>
74+
);
75+
}
76+
```
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# useLongPress
2+
3+
## Introduce
4+
5+
사용자가 요소를 길게 눌렀을 때 콜백 함수를 호출합니다.
6+
7+
```ts
8+
export type Fn = () => void;
9+
10+
export interface UseLongPressReturns {
11+
onMouseDown: Fn;
12+
onMouseUp: Fn;
13+
onMouseLeave: Fn;
14+
onTouchStart: Fn;
15+
onTouchEnd: Fn;
16+
}
17+
18+
const useLongPress = (callback: Fn, delay: number = 500): UseLongPressReturns
19+
```
20+
21+
사용자가 요소를 지정한 시간 이상 누르고 있을 때 콜백 함수가 호출되며, 마우스와 터치 이벤트를 모두 지원합니다.
22+
23+
### Props
24+
25+
- `callback` : 사용자가 요소를 길게 눌렀을 때 호출될 콜백 함수
26+
- `delay` : 사용자가 요소를 길게 눌러야 하는 시간(밀리초, 기본값 500ms)
27+
28+
### Returns
29+
30+
- UseLongPressReturns : 요소에 연결될 이벤트 핸들러 객체. 다음 다섯 가지 이벤트가 반환됩니다.
31+
- onMouseDown
32+
- onMouseUp
33+
- onMouseLeave
34+
- onTouchStart
35+
- onTouchEnd
36+
37+
## Examples
38+
39+
```tsx copy filename="TestComponent.tsx"
40+
function TestComponent() {
41+
const [isLongPressed, setLongPressed] = useState(false);
42+
43+
const attrs = useLongPress(() => {
44+
setLongPressed(true);
45+
});
46+
47+
return (
48+
<div>
49+
<h1>{isLongPressed ? '✨ LONG PRESS ✨' : 'USE-REACT-HOOKS'}</h1>
50+
<button {...attrs}>PRESS</button>
51+
<button onClick={() => setLongPressed(false)}>RESET</button>
52+
</div>
53+
);
54+
}
55+
```
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# useScrollLock
2+
3+
## Introduce
4+
5+
페이지의 스크롤을 잠궈 사용자가 스크롤할 수 없도록 합니다.
6+
7+
(스크롤 바가 비활성화된 상태로, UI형태가 유지된 형태)
8+
9+
```ts
10+
const useScrollLock = (props: boolean): void
11+
```
12+
13+
### Props
14+
15+
boolean 값으로 스크롤의 잠금 여부를 관리합니다.
16+
17+
## Examples
18+
19+
```tsx copy filename="TestComponent.tsx"
20+
21+
const TestComponent = () => {
22+
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
23+
24+
useScrollLock(isModalOpen);
25+
26+
const openModal = () => {
27+
setIsModalOpen(true);
28+
};
29+
30+
const closeModal = () => {
31+
setIsModalOpen(false);
32+
};
33+
34+
return (
35+
<div style={styles.container}>
36+
{isModalOpen && (
37+
<div style={styles.modal}>
38+
<div style={styles.modalContent}>
39+
...
40+
</div>
41+
);
42+
};
43+
44+
```

0 commit comments

Comments
 (0)