import { useCallback } from 'react'; import { findNodeHandle, TextInput, type BlurEvent, type FocusEvent, } from 'react-native'; import GorhomBottomSheetPackage from '../../../optional/gorhom-bottom-sheet'; /** * Return type for the bottom-sheet-aware handlers hook */ interface UseBottomSheetAwareHandlersReturn { /** Focus handler that notifies the bottom sheet about the keyboard target */ onFocus: (e: FocusEvent) => void; /** Blur handler that conditionally clears the keyboard target in the bottom sheet */ onBlur: (e: BlurEvent) => void; } /** * Hook that provides onFocus/onBlur handlers for managing bottom sheet * keyboard state when an input is rendered inside a BottomSheet context. * * Uses `useBottomSheetInternal(true)` (unsafe mode) so it returns `null` * instead of throwing when called outside a BottomSheet. When inside a * BottomSheet it returns handlers that wire into the keyboard state * management logic required by `@gorhom/bottom-sheet`. * * Pass the returned handlers to your `` or `` component: * * ```tsx * const { onFocus, onBlur } = useBottomSheetAwareHandlers(); * * ``` * * @returns onFocus and onBlur handlers for bottom sheet keyboard management */ export function useBottomSheetAwareHandlers(): UseBottomSheetAwareHandlersReturn { const useBottomSheetInternal = GorhomBottomSheetPackage?.useBottomSheetInternal; const bottomSheetContext = useBottomSheetInternal?.(true) ?? null; const isActive = bottomSheetContext !== null; /** * Handles focus event: notifies the bottom sheet about the keyboard target. */ const onFocus = useCallback( (e: FocusEvent) => { if (isActive && bottomSheetContext) { bottomSheetContext.animatedKeyboardState.set( (state: Record) => ({ ...state, target: e.nativeEvent.target, }) ); } }, [isActive, bottomSheetContext] ); /** * Handles blur event: conditionally clears the keyboard target in the * bottom sheet state. */ const onBlur = useCallback( (e: BlurEvent) => { if (isActive && bottomSheetContext) { const keyboardState = bottomSheetContext.animatedKeyboardState.get(); // Legacy typings don't accept host instances in `findNodeHandle`. const currentFocusedInput = findNodeHandle( TextInput.State.currentlyFocusedInput() as unknown as Parameters< typeof findNodeHandle >[0] ); const shouldRemoveCurrentTarget = keyboardState.target === e.nativeEvent.target; const shouldIgnoreBlurEvent = currentFocusedInput && bottomSheetContext.textInputNodesRef.current.has(currentFocusedInput); if (shouldRemoveCurrentTarget && !shouldIgnoreBlurEvent) { bottomSheetContext.animatedKeyboardState.set( (state: Record) => ({ ...state, target: undefined, }) ); } } }, [isActive, bottomSheetContext] ); return { onFocus, onBlur }; }