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(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) => { // 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 }; };