import { useState, useEffect, useCallback } from "react"; interface VirtualKeyboardState { isOpen: boolean; height: number; viewportHeight: number; } export function useVirtualKeyboard() { const [state, setState] = useState({ isOpen: false, height: 0, viewportHeight: typeof window !== "undefined" ? window.innerHeight : 0, }); const updateKeyboardState = useCallback(() => { const visualViewport = window.visualViewport; const windowHeight = window.innerHeight; if (visualViewport) { const viewportHeight = visualViewport.height; const keyboardHeight = windowHeight - viewportHeight; const isOpen = keyboardHeight > 100; // Threshold to avoid false positives setState({ isOpen, height: keyboardHeight, viewportHeight, }); } else { // Fallback: compare window height to a stored reference // This is less reliable but works on older browsers const currentHeight = windowHeight; const isOpen = currentHeight < state.viewportHeight - 100; setState((prev) => ({ isOpen, height: isOpen ? prev.viewportHeight - currentHeight : 0, viewportHeight: isOpen ? prev.viewportHeight : currentHeight, })); } }, [state.viewportHeight]); useEffect(() => { const visualViewport = window.visualViewport; if (visualViewport) { visualViewport.addEventListener("resize", updateKeyboardState); visualViewport.addEventListener("scroll", updateKeyboardState); } else { window.addEventListener("resize", updateKeyboardState); } // Initial check updateKeyboardState(); return () => { if (visualViewport) { visualViewport.removeEventListener("resize", updateKeyboardState); visualViewport.removeEventListener("scroll", updateKeyboardState); } else { window.removeEventListener("resize", updateKeyboardState); } }; }, [updateKeyboardState]); return state; }