import { useEffect, useLayoutEffect } from "react"; import { useEvent, useHandler } from "react-native-reanimated"; import { AndroidSoftInputModes } from "../constants"; import { useKeyboardContext } from "../context"; import { KeyboardController } from "../module"; import type { AnimatedContext, ReanimatedContext } from "../context"; import type { FocusedInputHandler, FocusedInputSelectionChangedEvent, FocusedInputTextChangedEvent, KeyboardHandler, NativeEvent, } from "../types"; /** * Hook that sets the Android soft input mode to adjust resize on mount and * restores default mode on unmount. This ensures the keyboard behavior is consistent * on all Android versions. * * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/keyboard-controller#setinputmode-|Documentation} page for more details. * @example * ```tsx * function MyComponent() { * useResizeMode(); * return ; * } * ``` */ export const useResizeMode = () => { useEffect(() => { KeyboardController.setInputMode( AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE, ); return () => KeyboardController.setDefaultMode(); }, []); }; /** * Hook that provides animated (`height`/`progress`) values for tracking keyboard movement. * Automatically sets the resize mode for Android. * * @returns Object {@link AnimatedContext|containing} animated values for keyboard movement. * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/hooks/keyboard/use-keyboard-animation|Documentation} page for more details. * @example * ```tsx * function MyComponent() { * const { height, progress } = useKeyboardAnimation(); * return ; * } * ``` */ export const useKeyboardAnimation = (): AnimatedContext => { useResizeMode(); const context = useKeyboardContext(); return context.animated; }; /** * Hook that provides reanimated (`height`/`progress`) values for tracking keyboard movement. * Automatically sets the resize mode for Android. * * @returns Object {@link ReanimatedContext|containing} reanimated values for keyboard movement. * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/hooks/keyboard/use-reanimated-keyboard-animation|Documentation} page for more details. * @example * ```tsx * function MyComponent() { * const { height, progress } = useReanimatedKeyboardAnimation(); * return ; * } * ``` */ export const useReanimatedKeyboardAnimation = (): ReanimatedContext => { useResizeMode(); const context = useKeyboardContext(); return context.reanimated; }; /** * An alternative to {@link useKeyboardHandler} that doesn't set resize mode on mount. If your * app already uses `adjustResize`, then you can use this hook instead of `useKeyboardHandler`. * * @param handler - Object containing keyboard event handlers. * @param [deps] - Dependencies array for the effect. * @example * ```tsx * function MyComponent() { * const height = useSharedValue(0); * const progress = useSharedValue(0); * * useGenericKeyboardHandler({ * onMove: (e) => { * "worklet"; * * height.value = e.height; * progress.value = e.progress; * }, * onEnd: (e) => { * "worklet"; * * height.value = e.height; * progress.value = e.progress; * }, * }, []); * * return ; * } * ``` */ export function useGenericKeyboardHandler( handler: KeyboardHandler, deps?: unknown[], ) { const context = useKeyboardContext(); const { doDependenciesDiffer } = useHandler(handler, deps); const eventHandler = useEvent( (event) => { "worklet"; if (event.eventName.endsWith("onKeyboardMoveStart")) { handler.onStart?.(event); } if (event.eventName.endsWith("onKeyboardMove")) { handler.onMove?.(event); } if (event.eventName.endsWith("onKeyboardMoveEnd")) { handler.onEnd?.(event); } if (event.eventName.endsWith("onKeyboardMoveInteractive")) { handler.onInteractive?.(event); } }, [ "onKeyboardMoveStart", "onKeyboardMove", "onKeyboardMoveEnd", "onKeyboardMoveInteractive", ], doDependenciesDiffer, ); useLayoutEffect(() => { const cleanup = context.setKeyboardHandlers(eventHandler); return () => cleanup(); }, deps); } /** * Hook that gives an access to each aspect of keyboard movement with workletized `onStart`/`onMove`/`onInteractive`/`onEnd` handlers. * * @param handler - Object containing keyboard event handlers. * @param [deps] - Dependencies array for the effect. * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/hooks/keyboard/use-keyboard-handler|Documentation} page for more details. * @example * ```tsx * function MyComponent() { * const height = useSharedValue(0); * const progress = useSharedValue(0); * * useKeyboardHandler({ * onMove: (e) => { * "worklet"; * * height.value = e.height; * progress.value = e.progress; * }, * onEnd: (e) => { * "worklet"; * * height.value = e.height; * progress.value = e.progress; * }, * }, []); * * return ; * } * ``` */ export function useKeyboardHandler(handler: KeyboardHandler, deps?: unknown[]) { useResizeMode(); useGenericKeyboardHandler(handler, deps); } /** * Hook for controlling keyboard controller module. * Allows to disable/enable it and check the actual state (whether it's enabled or not). * When disabled it fallbacks to default android keyboard handling and stops tracking all * the events that are exposed from this library. * * @property {Function} setEnabled - Function to enable/disable keyboard handling. * @property {boolean} enabled - Current enabled state. * @returns Object containing keyboard control functions and state. * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/hooks/module/use-keyboard-controller|Documentation} page for more details. * @example * ```tsx * function MyComponent() { * const { setEnabled, enabled } = useKeyboardController(); * return ( *