89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
import { useEffect, useState, useMemo, CSSProperties } from 'react';
|
|
|
|
export interface UseKeyboardAwareOptions {
|
|
defaultPadding?: number;
|
|
heightRatio?: number;
|
|
maxPadding?: number;
|
|
transition?: string;
|
|
}
|
|
|
|
export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => {
|
|
const {
|
|
defaultPadding = 60,
|
|
heightRatio = 0.7,
|
|
maxPadding = 300,
|
|
transition = 'padding-bottom 0.2s ease'
|
|
} = options || {};
|
|
|
|
const [keyboardHeight, setKeyboardHeight] = useState<number>(0);
|
|
|
|
useEffect(() => {
|
|
let focusedElement: HTMLInputElement | null = null;
|
|
let isKeyboardOpen = false;
|
|
|
|
// 네이티브에서 호출할 전역 함수 등록
|
|
(window as any).onKeyboardShow = (height: number) => {
|
|
console.log('Keyboard shown, height:', height);
|
|
const wasKeyboardOpen = isKeyboardOpen;
|
|
isKeyboardOpen = true;
|
|
setKeyboardHeight(height);
|
|
|
|
// 키보드가 새로 열릴 때만 스크롤 (이미 열려있으면 스크롤 안함)
|
|
if (!wasKeyboardOpen && focusedElement) {
|
|
setTimeout(() => {
|
|
focusedElement?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
}, 250);
|
|
}
|
|
};
|
|
|
|
(window as any).onKeyboardHide = () => {
|
|
console.log('Keyboard hidden');
|
|
isKeyboardOpen = false;
|
|
setKeyboardHeight(0);
|
|
focusedElement = null;
|
|
};
|
|
|
|
// focus된 요소를 추적하기 위한 함수
|
|
(window as any).setFocusedElement = (element: HTMLInputElement) => {
|
|
focusedElement = element;
|
|
|
|
// 키보드가 이미 열려있으면 즉시 스크롤
|
|
if (isKeyboardOpen) {
|
|
setTimeout(() => {
|
|
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
}, 100);
|
|
}
|
|
};
|
|
|
|
return () => {
|
|
delete (window as any).onKeyboardShow;
|
|
delete (window as any).onKeyboardHide;
|
|
delete (window as any).setFocusedElement;
|
|
};
|
|
}, []);
|
|
|
|
// 모든 input에서 사용할 공통 핸들러
|
|
const handleInputFocus = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
// focus된 요소를 저장
|
|
(window as any).setFocusedElement?.(e.target);
|
|
};
|
|
|
|
// 동적 패딩 스타일 계산
|
|
const keyboardAwarePadding: CSSProperties = useMemo(() => {
|
|
const calculatedPadding = keyboardHeight > 0
|
|
? Math.min(keyboardHeight * heightRatio, maxPadding)
|
|
: defaultPadding;
|
|
|
|
return {
|
|
paddingBottom: `${calculatedPadding}px`,
|
|
transition
|
|
};
|
|
}, [keyboardHeight, defaultPadding, heightRatio, maxPadding, transition]);
|
|
|
|
return {
|
|
keyboardHeight,
|
|
handleInputFocus,
|
|
keyboardAwarePadding
|
|
};
|
|
};
|