From 11596e2b6f699d3e4f68ca65ea483a6df48d4931 Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Mon, 24 Nov 2025 20:46:29 +0300 Subject: [PATCH 1/4] feat: `useAnimatedKeyboard` compat layer --- src/compat.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 1 + 2 files changed, 46 insertions(+) create mode 100644 src/compat.ts diff --git a/src/compat.ts b/src/compat.ts new file mode 100644 index 0000000000..3f0eeb2f03 --- /dev/null +++ b/src/compat.ts @@ -0,0 +1,45 @@ +import { useSharedValue } from "react-native-reanimated"; + +import { useKeyboardHandler } from "./hooks"; + +export const KeyboardState = { + UNKNOWN: 0, + OPENING: 1, + OPEN: 2, + CLOSING: 3, + CLOSED: 4, +}; + +export const useAnimatedKeyboard = () => { + const height = useSharedValue(0); + const state = useSharedValue(KeyboardState.UNKNOWN); + + useKeyboardHandler( + { + onStart: (e) => { + "worklet"; + + state.set(e.height > 0 ? KeyboardState.OPENING : KeyboardState.CLOSING); + }, + onMove: (e) => { + "worklet"; + + height.set(e.height); + }, + onInteractive: (e) => { + "worklet"; + + height.set(e.height); + }, + onEnd: (e) => { + "worklet"; + + state.set(e.height > 0 ? KeyboardState.OPEN : KeyboardState.CLOSED); + height.set(e.height); + }, + }, + [], + ); + + return { height, state }; +}; diff --git a/src/index.ts b/src/index.ts index 9093708b5e..427d4fdbaa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ export * from "./hooks"; export * from "./constants"; export * from "./module"; export * from "./types"; +export * from "./compat"; export { KeyboardAvoidingView, From a2fbeb9cb4175c13d4867088643f9e5a7b55fd2e Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Mon, 24 Nov 2025 20:50:23 +0300 Subject: [PATCH 2/4] fix: name conflict --- src/hooks/useKeyboardState/index.ts | 8 ++++---- src/types/module.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hooks/useKeyboardState/index.ts b/src/hooks/useKeyboardState/index.ts index f0b39bcf2e..c9d6107629 100644 --- a/src/hooks/useKeyboardState/index.ts +++ b/src/hooks/useKeyboardState/index.ts @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { KeyboardEvents } from "../../bindings"; import { KeyboardController } from "../../module"; -import type { KeyboardState } from "../../types"; +import type { IKeyboardState } from "../../types"; const EVENTS = ["keyboardDidShow", "keyboardDidHide"] as const; @@ -12,9 +12,9 @@ const getLatestState = () => ({ isVisible: KeyboardController.isVisible(), }); -type KeyboardStateSelector = (state: KeyboardState) => T; +type KeyboardStateSelector = (state: IKeyboardState) => T; -const defaultSelector: KeyboardStateSelector = (state) => state; +const defaultSelector: KeyboardStateSelector = (state) => state; /** * React Hook that represents the current keyboard state on iOS and Android. @@ -40,7 +40,7 @@ const defaultSelector: KeyboardStateSelector = (state) => state; * } * ``` */ -function useKeyboardState( +function useKeyboardState( selector: KeyboardStateSelector = defaultSelector as KeyboardStateSelector, ): T { const [state, setState] = useState(() => selector(getLatestState())); diff --git a/src/types/module.ts b/src/types/module.ts index 09a5840c8a..e9991a6b56 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -23,7 +23,7 @@ export type KeyboardEventData = { /** * An object that represent current keyboard state. */ -export type KeyboardState = { +export type IKeyboardState = { /** Whether the keyboard is currently visible. */ isVisible: boolean; } & KeyboardEventData; From aa811b4c4d3618fe262b63ff3897e73960f1c72d Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Mon, 24 Nov 2025 20:55:16 +0300 Subject: [PATCH 3/4] docs: added jsdoc --- src/compat.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/compat.ts b/src/compat.ts index 3f0eeb2f03..0202ed8605 100644 --- a/src/compat.ts +++ b/src/compat.ts @@ -10,6 +10,22 @@ export const KeyboardState = { CLOSED: 4, }; +/** + * A compatibility layer for migration from https://docs.swmansion.com/react-native-reanimated/docs/device/useAnimatedKeyboard. + * + * @returns An object containing `height` and `state` properties represented as `SharedValue`. + * @example + * ```ts + * import { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-reanimated'; + * + * export default function App() { + * const keyboard = useAnimatedKeyboard(); + * + * const animatedStyles = useAnimatedStyle(() => ({ + * transform: [{ translateY: -keyboard.height.value }], + * })); + * } + */ export const useAnimatedKeyboard = () => { const height = useSharedValue(0); const state = useSharedValue(KeyboardState.UNKNOWN); From aa48e2d60f33ae6e1fa9e587097cfcf3e27d8f48 Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Mon, 24 Nov 2025 22:31:44 +0300 Subject: [PATCH 4/4] fix: change import path --- src/compat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compat.ts b/src/compat.ts index 0202ed8605..36e638052e 100644 --- a/src/compat.ts +++ b/src/compat.ts @@ -16,7 +16,7 @@ export const KeyboardState = { * @returns An object containing `height` and `state` properties represented as `SharedValue`. * @example * ```ts - * import { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-reanimated'; + * import { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-keyboard-controller'; * * export default function App() { * const keyboard = useAnimatedKeyboard();