react-native-keyboard-controller
Version:
Keyboard manager which works in identical way on both iOS and Android
240 lines (219 loc) • 7.56 kB
text/typescript
import { useEffect, useLayoutEffect } from "react";
import { AndroidSoftInputModes } from "../constants";
import { useKeyboardContext } from "../context";
import { KeyboardController } from "../module";
import type { AnimatedContext, ReanimatedContext } from "../context";
import type { FocusedInputHandler, KeyboardHandler } from "../types";
import type { DependencyList } from "react";
/**
* 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 <View />;
* }
* ```
*/
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 <Animated.View style={{ transform: [{ translateY: height }] }} />;
* }
* ```
*/
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 <Reanimated.View style={{ transform: [{ translateY: height }] }} />;
* }
* ```
*/
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 <Reanimated.View style={{ height: height }] }} />;
* }
* ```
*/
export function useGenericKeyboardHandler(
handler: KeyboardHandler,
deps?: DependencyList,
) {
const context = useKeyboardContext();
useLayoutEffect(() => {
const cleanup = context.setKeyboardHandlers(handler);
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 <Reanimated.View style={{ height: height }] }} />;
* }
* ```
*/
export function useKeyboardHandler(
handler: KeyboardHandler,
deps?: DependencyList,
) {
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 (
* <Button
* title={enabled ? 'Disable' : 'Enable'}
* onPress={() => setEnabled(!enabled)}
* />
* );
* }
* ```
*/
export function useKeyboardController() {
const context = useKeyboardContext();
return { setEnabled: context.setEnabled, enabled: context.enabled };
}
/**
* Hook that provides access to the layout of the currently focused input.
*
* @returns Object containing reanimated values for focused input.
* @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/hooks/input/use-reanimated-focused-input|Documentation} page for more details.
* @example
* ```tsx
* function MyComponent() {
* const { input } = useReanimatedFocusedInput();
* return <Reanimated.View style={{ height: input.value?.layout.height }} />;
* }
* ```
*/
export function useReanimatedFocusedInput() {
const context = useKeyboardContext();
return { input: context.layout };
}
/**
* Hook for handling focused input events, such as changes of selection, text etc.
*
* @param handler - Object containing focused input event handlers.
* @param [deps] - Dependencies array for the effect.
* @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/hooks/input/use-focused-input-handler|Documentation} page for more details.
* @example
* ```tsx
* function MyComponent() {
* useFocusedInputHandler({
* onChangeText: (e) => console.log('Text changed:', e.text),
* onSelectionChange: (e) => console.log('Selection changed:', e.selection)
* });
* return <View />;
* }
* ```
*/
export function useFocusedInputHandler(
handler: FocusedInputHandler,
deps?: DependencyList,
) {
const context = useKeyboardContext();
useLayoutEffect(() => {
const cleanup = context.setInputHandlers(handler);
return () => cleanup();
}, deps);
}
export * from "./useWindowDimensions";
export * from "./useKeyboardState";