react-native-keyboard-controller 1.9.5 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +1 -1
  2. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +4 -0
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputTextChangedEvent.kt +20 -0
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +36 -0
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/WindowInsetsAnimationCompat.kt +7 -0
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +17 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +12 -0
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +2 -0
  9. package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +13 -0
  10. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +5 -0
  11. package/ios/.clang-format +30 -30
  12. package/ios/.swiftlint.yml +1 -1
  13. package/ios/KeyboardController.xcodeproj/project.pbxproj +10 -0
  14. package/ios/KeyboardControllerModule.mm +14 -0
  15. package/ios/events/FocusedInputTextChangedEvent.h +16 -0
  16. package/ios/events/FocusedInputTextChangedEvent.m +72 -0
  17. package/ios/observers/FocusedInputObserver.swift +29 -14
  18. package/ios/observers/TextChangeObserver.swift +41 -0
  19. package/ios/views/KeyboardControllerView.mm +53 -31
  20. package/ios/views/KeyboardControllerViewManager.mm +1 -0
  21. package/ios/views/KeyboardControllerViewManager.swift +21 -10
  22. package/jest/index.js +6 -4
  23. package/lib/commonjs/animated.js +33 -27
  24. package/lib/commonjs/animated.js.map +1 -1
  25. package/lib/commonjs/bindings.js +1 -0
  26. package/lib/commonjs/bindings.js.map +1 -1
  27. package/lib/commonjs/bindings.native.js +6 -6
  28. package/lib/commonjs/bindings.native.js.map +1 -1
  29. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js +5 -3
  30. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js.map +1 -1
  31. package/lib/commonjs/components/KeyboardAvoidingView/index.js +17 -9
  32. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
  33. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +199 -0
  34. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -0
  35. package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js +100 -0
  36. package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -0
  37. package/lib/commonjs/components/KeyboardAwareScrollView/utils.js +28 -0
  38. package/lib/commonjs/components/KeyboardAwareScrollView/utils.js.map +1 -0
  39. package/lib/commonjs/components/KeyboardStickyView/index.js +7 -4
  40. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  41. package/lib/commonjs/components/hooks/useKeyboardInterpolation.js +81 -0
  42. package/lib/commonjs/components/hooks/useKeyboardInterpolation.js.map +1 -0
  43. package/lib/commonjs/components/index.js +7 -0
  44. package/lib/commonjs/components/index.js.map +1 -1
  45. package/lib/commonjs/constants.js.map +1 -1
  46. package/lib/commonjs/context.js +2 -1
  47. package/lib/commonjs/context.js.map +1 -1
  48. package/lib/commonjs/hooks.js +17 -2
  49. package/lib/commonjs/hooks.js.map +1 -1
  50. package/lib/commonjs/index.js +8 -1
  51. package/lib/commonjs/index.js.map +1 -1
  52. package/lib/commonjs/internal.js +3 -6
  53. package/lib/commonjs/internal.js.map +1 -1
  54. package/lib/commonjs/monkey-patch.android.js +1 -1
  55. package/lib/commonjs/monkey-patch.android.js.map +1 -1
  56. package/lib/commonjs/monkey-patch.js.map +1 -1
  57. package/lib/commonjs/reanimated.js +5 -3
  58. package/lib/commonjs/reanimated.js.map +1 -1
  59. package/lib/commonjs/reanimated.native.js +29 -12
  60. package/lib/commonjs/reanimated.native.js.map +1 -1
  61. package/lib/commonjs/replicas.js +7 -5
  62. package/lib/commonjs/replicas.js.map +1 -1
  63. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js +1 -1
  64. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  65. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js +2 -2
  66. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
  67. package/lib/commonjs/specs/NativeKeyboardController.js +1 -1
  68. package/lib/commonjs/specs/NativeKeyboardController.js.map +1 -1
  69. package/lib/commonjs/specs/NativeStatusBarManagerCompat.js +1 -1
  70. package/lib/commonjs/specs/NativeStatusBarManagerCompat.js.map +1 -1
  71. package/lib/commonjs/types.js.map +1 -1
  72. package/lib/commonjs/utils.js.map +1 -1
  73. package/lib/module/animated.js +41 -35
  74. package/lib/module/animated.js.map +1 -1
  75. package/lib/module/bindings.js +2 -1
  76. package/lib/module/bindings.js.map +1 -1
  77. package/lib/module/bindings.native.js +7 -7
  78. package/lib/module/bindings.native.js.map +1 -1
  79. package/lib/module/components/KeyboardAvoidingView/hooks.js +7 -5
  80. package/lib/module/components/KeyboardAvoidingView/hooks.js.map +1 -1
  81. package/lib/module/components/KeyboardAvoidingView/index.js +20 -13
  82. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
  83. package/lib/module/components/KeyboardAwareScrollView/index.js +190 -0
  84. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -0
  85. package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js +93 -0
  86. package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -0
  87. package/lib/module/components/KeyboardAwareScrollView/utils.js +21 -0
  88. package/lib/module/components/KeyboardAwareScrollView/utils.js.map +1 -0
  89. package/lib/module/components/KeyboardStickyView/index.js +9 -7
  90. package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
  91. package/lib/module/components/hooks/useKeyboardInterpolation.js +74 -0
  92. package/lib/module/components/hooks/useKeyboardInterpolation.js.map +1 -0
  93. package/lib/module/components/index.js +3 -2
  94. package/lib/module/components/index.js.map +1 -1
  95. package/lib/module/context.js +4 -3
  96. package/lib/module/context.js.map +1 -1
  97. package/lib/module/hooks.js +21 -7
  98. package/lib/module/hooks.js.map +1 -1
  99. package/lib/module/index.js +8 -8
  100. package/lib/module/index.js.map +1 -1
  101. package/lib/module/internal.js +6 -9
  102. package/lib/module/internal.js.map +1 -1
  103. package/lib/module/monkey-patch.android.js +2 -2
  104. package/lib/module/monkey-patch.android.js.map +1 -1
  105. package/lib/module/monkey-patch.js.map +1 -1
  106. package/lib/module/reanimated.js +2 -1
  107. package/lib/module/reanimated.js.map +1 -1
  108. package/lib/module/reanimated.native.js +27 -11
  109. package/lib/module/reanimated.native.js.map +1 -1
  110. package/lib/module/replicas.js +13 -11
  111. package/lib/module/replicas.js.map +1 -1
  112. package/lib/module/specs/KeyboardControllerViewNativeComponent.js +2 -2
  113. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  114. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js +3 -3
  115. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
  116. package/lib/module/specs/NativeKeyboardController.js +2 -2
  117. package/lib/module/specs/NativeKeyboardController.js.map +1 -1
  118. package/lib/module/specs/NativeStatusBarManagerCompat.js +2 -2
  119. package/lib/module/specs/NativeStatusBarManagerCompat.js.map +1 -1
  120. package/lib/module/types.js.map +1 -1
  121. package/lib/module/utils.js.map +1 -1
  122. package/lib/typescript/animated.d.ts +1 -1
  123. package/lib/typescript/bindings.d.ts +1 -1
  124. package/lib/typescript/bindings.native.d.ts +1 -1
  125. package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +4 -4
  126. package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +45 -0
  127. package/lib/typescript/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.d.ts +6 -0
  128. package/lib/typescript/components/KeyboardAwareScrollView/utils.d.ts +1 -0
  129. package/lib/typescript/components/KeyboardStickyView/index.d.ts +2 -2
  130. package/lib/typescript/components/hooks/useKeyboardInterpolation.d.ts +20 -0
  131. package/lib/typescript/components/index.d.ts +3 -2
  132. package/lib/typescript/context.d.ts +6 -5
  133. package/lib/typescript/hooks.d.ts +4 -3
  134. package/lib/typescript/index.d.ts +8 -8
  135. package/lib/typescript/internal.d.ts +9 -6
  136. package/lib/typescript/reanimated.d.ts +3 -2
  137. package/lib/typescript/reanimated.native.d.ts +3 -2
  138. package/lib/typescript/replicas.d.ts +1 -1
  139. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +7 -3
  140. package/lib/typescript/specs/KeyboardGestureAreaNativeComponent.d.ts +4 -4
  141. package/lib/typescript/specs/NativeKeyboardController.d.ts +2 -1
  142. package/lib/typescript/specs/NativeStatusBarManagerCompat.d.ts +1 -1
  143. package/lib/typescript/types.d.ts +18 -5
  144. package/package.json +12 -11
  145. package/react-native-keyboard-controller.podspec +1 -1
  146. package/src/animated.tsx +59 -42
  147. package/src/bindings.native.ts +11 -11
  148. package/src/bindings.ts +4 -3
  149. package/src/components/KeyboardAvoidingView/hooks.ts +9 -6
  150. package/src/components/KeyboardAvoidingView/index.tsx +30 -27
  151. package/src/components/KeyboardAwareScrollView/index.tsx +262 -0
  152. package/src/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.ts +123 -0
  153. package/src/components/KeyboardAwareScrollView/utils.ts +26 -0
  154. package/src/components/KeyboardStickyView/index.tsx +12 -18
  155. package/src/components/hooks/useKeyboardInterpolation.ts +96 -0
  156. package/src/components/index.ts +3 -2
  157. package/src/context.ts +15 -9
  158. package/src/hooks.ts +30 -13
  159. package/src/index.ts +12 -8
  160. package/src/internal.ts +22 -13
  161. package/src/monkey-patch.android.ts +2 -2
  162. package/src/reanimated.native.ts +43 -18
  163. package/src/reanimated.ts +9 -3
  164. package/src/replicas.ts +18 -17
  165. package/src/specs/KeyboardControllerViewNativeComponent.ts +12 -5
  166. package/src/specs/KeyboardGestureAreaNativeComponent.ts +7 -7
  167. package/src/specs/NativeKeyboardController.ts +4 -3
  168. package/src/specs/NativeStatusBarManagerCompat.ts +3 -3
  169. package/src/types.ts +45 -19
@@ -0,0 +1,20 @@
1
+ type KeyboardInterpolationOutput = [number, number];
2
+ /**
3
+ * Hook that can be used for interpolation keyboard movement. The main concern is the thing
4
+ * when keyboard is opened and gets resized on Android. Let's say we are interpolating from
5
+ * closed to open [0, 200] and we want to interpolate it to [0, 230] (to achieve nice parallax effect).
6
+ * Then let's say keyboard changes its height to 220 (and we want to interpolate the value to 250, +30
7
+ * to keyboard height). If we interpolate based on `progress` value, then we will have a jump on first frame:
8
+ * the last interpolated position was 230, now we will interpolate to 250, but first frame will be calculated
9
+ * as 200 / 220 * 250 = 227 (and last interpolated position was 230) so we will have a jump.
10
+ *
11
+ * This hook handles it, and when keyboard changes its size it does an interpolation as:
12
+ * [200, 220] -> [230, 250], i. e. we preserve last interpolated value and use it as initial value for interpolation
13
+ * and because of that we will not have a jump and animation will start from the last frame and will be smooth.
14
+ *
15
+ * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/315
16
+ */
17
+ declare const useKeyboardInterpolation: () => {
18
+ interpolate: (keyboardPosition: number, output: KeyboardInterpolationOutput) => number;
19
+ };
20
+ export default useKeyboardInterpolation;
@@ -1,2 +1,3 @@
1
- export { default as KeyboardAvoidingView } from './KeyboardAvoidingView';
2
- export { default as KeyboardStickyView } from './KeyboardStickyView';
1
+ export { default as KeyboardAvoidingView } from "./KeyboardAvoidingView";
2
+ export { default as KeyboardStickyView } from "./KeyboardStickyView";
3
+ export { default as KeyboardAwareScrollView } from "./KeyboardAwareScrollView";
@@ -1,7 +1,7 @@
1
- import { Animated } from 'react-native';
2
- import type { FocusedInputLayoutChangedEvent, KeyboardHandlers } from './types';
3
- import type React from 'react';
4
- import type { SharedValue } from 'react-native-reanimated';
1
+ import { Animated } from "react-native";
2
+ import type { FocusedInputHandlers, FocusedInputLayoutChangedEvent, KeyboardHandlers } from "./types";
3
+ import type React from "react";
4
+ import type { SharedValue } from "react-native-reanimated";
5
5
  export type AnimatedContext = {
6
6
  progress: Animated.Value;
7
7
  height: Animated.AnimatedMultiplication<number>;
@@ -15,7 +15,8 @@ export type KeyboardAnimationContext = {
15
15
  animated: AnimatedContext;
16
16
  reanimated: ReanimatedContext;
17
17
  layout: SharedValue<FocusedInputLayoutChangedEvent | null>;
18
- setHandlers: (handlers: KeyboardHandlers) => void;
18
+ setKeyboardHandlers: (handlers: KeyboardHandlers) => void;
19
+ setInputHandlers: (handlers: FocusedInputHandlers) => void;
19
20
  setEnabled: React.Dispatch<React.SetStateAction<boolean>>;
20
21
  };
21
22
  export declare const KeyboardContext: React.Context<KeyboardAnimationContext>;
@@ -1,6 +1,6 @@
1
- import type { AnimatedContext, ReanimatedContext } from './context';
2
- import type { KeyboardHandler } from './types';
3
- import type { DependencyList } from 'react';
1
+ import type { AnimatedContext, ReanimatedContext } from "./context";
2
+ import type { FocusedInputHandler, KeyboardHandler } from "./types";
3
+ import type { DependencyList } from "react";
4
4
  export declare const useResizeMode: () => void;
5
5
  export declare const useKeyboardAnimation: () => AnimatedContext;
6
6
  export declare const useReanimatedKeyboardAnimation: () => ReanimatedContext;
@@ -13,3 +13,4 @@ export declare function useKeyboardController(): {
13
13
  export declare function useReanimatedFocusedInput(): {
14
14
  input: import("react-native-reanimated").SharedValue<import("./types").FocusedInputLayoutChangedEvent | null>;
15
15
  };
16
+ export declare function useFocusedInputHandler(handler?: FocusedInputHandler, deps?: DependencyList): void;
@@ -1,8 +1,8 @@
1
- export * from './bindings';
2
- export * from './animated';
3
- export * from './replicas';
4
- export * from './context';
5
- export * from './hooks';
6
- export * from './constants';
7
- export * from './types';
8
- export { KeyboardAvoidingView, KeyboardStickyView } from './components';
1
+ export * from "./bindings";
2
+ export * from "./animated";
3
+ export * from "./replicas";
4
+ export * from "./context";
5
+ export * from "./hooks";
6
+ export * from "./constants";
7
+ export * from "./types";
8
+ export { KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView, } from "./components";
@@ -1,5 +1,10 @@
1
- import { Animated } from 'react-native';
2
- import type { Handlers, NativeEvent } from './types';
1
+ import { Animated } from "react-native";
2
+ import type { Handlers } from "./types";
3
+ type UntypedHandler = Record<string, (event: never) => void>;
4
+ type SharedHandlersReturnType<T extends UntypedHandler> = [
5
+ (handler: Handlers<T>) => void,
6
+ <K extends keyof T>(type: K, event: Parameters<T[K]>[0]) => void
7
+ ];
3
8
  /**
4
9
  * Hook for storing worklet handlers (objects with keys, where values are worklets).
5
10
  * Returns methods for setting handlers and broadcasting events in them.
@@ -11,10 +16,7 @@ import type { Handlers, NativeEvent } from './types';
11
16
  * onEvent2: () => {},
12
17
  * }
13
18
  */
14
- export declare function useSharedHandlers<T extends Record<string, (event: NativeEvent) => void>>(): {
15
- setHandlers: (handler: Handlers<T>) => void;
16
- broadcast: (type: keyof T, event: NativeEvent) => void;
17
- };
19
+ export declare function useSharedHandlers<T extends UntypedHandler>(): SharedHandlersReturnType<T>;
18
20
  /**
19
21
  * TS variant of `useAnimatedValue` hook which is added in RN 0.71
20
22
  * A better alternative of storing animated values in refs, since
@@ -25,3 +27,4 @@ export declare function useSharedHandlers<T extends Record<string, (event: Nativ
25
27
  * @see https://github.com/facebook/react-native/commit/e22217fe8b9455e32695f88ca835e11442b0a937
26
28
  */
27
29
  export declare function useAnimatedValue(initialValue: number, config?: Animated.AnimatedConfig): Animated.Value;
30
+ export {};
@@ -1,3 +1,4 @@
1
- import type { EventWithName, FocusedInputHandlerHook, FocusedInputLayoutChangedEvent, KeyboardHandlerHook, NativeEvent } from './types';
1
+ import type { EventWithName, FocusedInputLayoutChangedEvent, FocusedInputLayoutHandlerHook, FocusedInputTextChangedEvent, FocusedInputTextHandlerHook, KeyboardHandlerHook, NativeEvent } from "./types";
2
2
  export declare const useAnimatedKeyboardHandler: KeyboardHandlerHook<Record<string, unknown>, EventWithName<NativeEvent>>;
3
- export declare const useFocusedInputHandler: FocusedInputHandlerHook<Record<string, unknown>, EventWithName<FocusedInputLayoutChangedEvent>>;
3
+ export declare const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<Record<string, unknown>, EventWithName<FocusedInputLayoutChangedEvent>>;
4
+ export declare const useFocusedInputTextHandler: FocusedInputTextHandlerHook<Record<string, unknown>, EventWithName<FocusedInputTextChangedEvent>>;
@@ -1,3 +1,4 @@
1
- import type { EventWithName, FocusedInputHandlerHook, FocusedInputLayoutChangedEvent, KeyboardHandlerHook, NativeEvent } from './types';
1
+ import type { EventWithName, FocusedInputLayoutChangedEvent, FocusedInputLayoutHandlerHook, FocusedInputTextChangedEvent, FocusedInputTextHandlerHook, KeyboardHandlerHook, NativeEvent } from "./types";
2
2
  export declare const useAnimatedKeyboardHandler: KeyboardHandlerHook<Record<string, unknown>, EventWithName<NativeEvent>>;
3
- export declare const useFocusedInputHandler: FocusedInputHandlerHook<Record<string, unknown>, EventWithName<FocusedInputLayoutChangedEvent>>;
3
+ export declare const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<Record<string, unknown>, EventWithName<FocusedInputLayoutChangedEvent>>;
4
+ export declare const useFocusedInputTextHandler: FocusedInputTextHandlerHook<Record<string, unknown>, EventWithName<FocusedInputTextChangedEvent>>;
@@ -1,4 +1,4 @@
1
- import { Animated } from 'react-native';
1
+ import { Animated } from "react-native";
2
2
  export declare const defaultAndroidEasing: import("react-native").EasingFunction;
3
3
  type KeyboardAnimation = {
4
4
  progress: Animated.Value;
@@ -1,6 +1,6 @@
1
- import type { HostComponent } from 'react-native';
2
- import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes';
3
- import type { DirectEventHandler, Double, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
1
+ import type { HostComponent } from "react-native";
2
+ import type { ViewProps } from "react-native/Libraries/Components/View/ViewPropTypes";
3
+ import type { DirectEventHandler, Double, Int32 } from "react-native/Libraries/Types/CodegenTypes";
4
4
  type KeyboardMoveEvent = Readonly<{
5
5
  height: Double;
6
6
  progress: Double;
@@ -18,6 +18,9 @@ type FocusedInputLayoutChangedEvent = Readonly<{
18
18
  absoluteY: Double;
19
19
  };
20
20
  }>;
21
+ type FocusedInputTextChangedEvent = Readonly<{
22
+ text: string;
23
+ }>;
21
24
  export interface NativeProps extends ViewProps {
22
25
  enabled?: boolean;
23
26
  statusBarTranslucent?: boolean;
@@ -27,6 +30,7 @@ export interface NativeProps extends ViewProps {
27
30
  onKeyboardMoveEnd?: DirectEventHandler<KeyboardMoveEvent>;
28
31
  onKeyboardMoveInteractive?: DirectEventHandler<KeyboardMoveEvent>;
29
32
  onFocusedInputLayoutChanged?: DirectEventHandler<FocusedInputLayoutChangedEvent>;
33
+ onFocusedInputTextChanged?: DirectEventHandler<FocusedInputTextChangedEvent>;
30
34
  }
31
35
  declare const _default: HostComponent<NativeProps>;
32
36
  export default _default;
@@ -1,8 +1,8 @@
1
- import type { HostComponent } from 'react-native';
2
- import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes';
3
- import type { WithDefault } from 'react-native/Libraries/Types/CodegenTypes';
1
+ import type { HostComponent } from "react-native";
2
+ import type { ViewProps } from "react-native/Libraries/Components/View/ViewPropTypes";
3
+ import type { WithDefault } from "react-native/Libraries/Types/CodegenTypes";
4
4
  export interface NativeProps extends ViewProps {
5
- interpolator?: WithDefault<'linear' | 'ios', 'linear'>;
5
+ interpolator?: WithDefault<"linear" | "ios", "linear">;
6
6
  showOnSwipeUp?: boolean;
7
7
  enableSwipeToDismiss?: boolean;
8
8
  }
@@ -1,8 +1,9 @@
1
- import type { TurboModule } from 'react-native';
1
+ import type { TurboModule } from "react-native";
2
2
  export interface Spec extends TurboModule {
3
3
  readonly getConstants: () => {};
4
4
  setInputMode(mode: number): void;
5
5
  setDefaultMode(): void;
6
+ dismiss(): void;
6
7
  addListener: (eventName: string) => void;
7
8
  removeListeners: (count: number) => void;
8
9
  }
@@ -1,4 +1,4 @@
1
- import type { TurboModule } from 'react-native';
1
+ import type { TurboModule } from "react-native";
2
2
  export interface Spec extends TurboModule {
3
3
  readonly getConstants: () => {};
4
4
  setHidden(hidden: boolean): void;
@@ -1,4 +1,4 @@
1
- import type { EmitterSubscription, NativeSyntheticEvent, ViewProps } from 'react-native';
1
+ import type { EmitterSubscription, NativeSyntheticEvent, ViewProps } from "react-native";
2
2
  export type NativeEvent = {
3
3
  progress: number;
4
4
  height: number;
@@ -16,23 +16,28 @@ export type FocusedInputLayoutChangedEvent = {
16
16
  absoluteY: number;
17
17
  };
18
18
  };
19
+ export type FocusedInputTextChangedEvent = {
20
+ text: string;
21
+ };
19
22
  export type EventWithName<T> = {
20
23
  eventName: string;
21
24
  } & T;
22
25
  export type KeyboardControllerProps = {
23
- enabled?: boolean;
24
26
  onKeyboardMoveStart?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
25
27
  onKeyboardMove?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
26
28
  onKeyboardMoveEnd?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
27
29
  onKeyboardMoveInteractive?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
28
30
  onFocusedInputLayoutChanged?: (e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>) => void;
31
+ onFocusedInputTextChanged?: (e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>) => void;
29
32
  onKeyboardMoveReanimated?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
30
33
  onFocusedInputLayoutChangedReanimated?: (e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>) => void;
34
+ onFocusedInputTextChangedReanimated?: (e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>) => void;
31
35
  statusBarTranslucent?: boolean;
32
36
  navigationBarTranslucent?: boolean;
37
+ enabled?: boolean;
33
38
  } & ViewProps;
34
39
  export type KeyboardGestureAreaProps = {
35
- interpolator: 'ios' | 'linear';
40
+ interpolator: "ios" | "linear";
36
41
  /**
37
42
  * Whether to allow to show a keyboard from dismissed state by swipe up.
38
43
  * Default to `false`.
@@ -48,10 +53,11 @@ export type KeyboardGestureAreaProps = {
48
53
  export type KeyboardControllerModule = {
49
54
  setDefaultMode: () => void;
50
55
  setInputMode: (mode: number) => void;
56
+ dismiss: () => void;
51
57
  addListener: (eventName: string) => void;
52
58
  removeListeners: (count: number) => void;
53
59
  };
54
- export type KeyboardControllerEvents = 'keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide';
60
+ export type KeyboardControllerEvents = "keyboardWillShow" | "keyboardDidShow" | "keyboardWillHide" | "keyboardDidHide";
55
61
  export type KeyboardEventData = {
56
62
  height: number;
57
63
  duration: number;
@@ -67,9 +73,12 @@ export type KeyboardHandlerHook<TContext, Event> = (handlers: {
67
73
  onKeyboardMoveEnd?: (e: NativeEvent, context: TContext) => void;
68
74
  onKeyboardMoveInteractive?: (e: NativeEvent, context: TContext) => void;
69
75
  }, dependencies?: unknown[]) => (e: NativeSyntheticEvent<Event>) => void;
70
- export type FocusedInputHandlerHook<TContext, Event> = (handlers: {
76
+ export type FocusedInputLayoutHandlerHook<TContext, Event> = (handlers: {
71
77
  onFocusedInputLayoutChanged?: (e: FocusedInputLayoutChangedEvent, context: TContext) => void;
72
78
  }, dependencies?: unknown[]) => (e: NativeSyntheticEvent<Event>) => void;
79
+ export type FocusedInputTextHandlerHook<TContext, Event> = (handlers: {
80
+ onFocusedInputTextChanged?: (e: FocusedInputTextChangedEvent, context: TContext) => void;
81
+ }, dependencies?: unknown[]) => (e: NativeSyntheticEvent<Event>) => void;
73
82
  export type Handlers<T> = Record<string, T | undefined>;
74
83
  export type KeyboardHandler = Partial<{
75
84
  onStart: (e: NativeEvent) => void;
@@ -78,3 +87,7 @@ export type KeyboardHandler = Partial<{
78
87
  onInteractive: (e: NativeEvent) => void;
79
88
  }>;
80
89
  export type KeyboardHandlers = Handlers<KeyboardHandler>;
90
+ export type FocusedInputHandler = Partial<{
91
+ onChangeText: (e: FocusedInputTextChangedEvent) => void;
92
+ }>;
93
+ export type FocusedInputHandlers = Handlers<FocusedInputHandler>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-keyboard-controller",
3
- "version": "1.9.5",
3
+ "version": "1.10.1",
4
4
  "description": "Keyboard manager which works in identical way on both iOS and Android",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -27,6 +27,7 @@
27
27
  "!**/__mocks__"
28
28
  ],
29
29
  "scripts": {
30
+ "format": "prettier '**/*' --ignore-unknown --write",
30
31
  "test": "jest",
31
32
  "typescript": "tsc --noEmit --project tsconfig.build.json",
32
33
  "lint": "eslint --quiet \"**/*.{js,ts,tsx}\"",
@@ -41,9 +42,12 @@
41
42
  "react-native",
42
43
  "keyboard",
43
44
  "animation",
45
+ "dismiss",
44
46
  "focused input",
47
+ "text changed",
45
48
  "avoiding view",
46
49
  "sticky view",
50
+ "keyboard aware scroll view",
47
51
  "ios",
48
52
  "android"
49
53
  ],
@@ -59,7 +63,7 @@
59
63
  },
60
64
  "devDependencies": {
61
65
  "@commitlint/config-conventional": "^11.0.0",
62
- "@react-native/eslint-config": "^0.72.2",
66
+ "@react-native/eslint-config": "^0.74.0",
63
67
  "@release-it/conventional-changelog": "^2.0.0",
64
68
  "@types/jest": "^29.2.1",
65
69
  "@types/react": "^18.0.24",
@@ -68,19 +72,19 @@
68
72
  "clang-format": "^1.8.0",
69
73
  "commitlint": "^11.0.0",
70
74
  "eslint": "^8.19.0",
71
- "eslint-config-prettier": "^7.0.0",
75
+ "eslint-config-prettier": "^8.5.0",
72
76
  "eslint-import-resolver-typescript": "^3.6.1",
73
77
  "eslint-plugin-import": "^2.28.1",
74
- "eslint-plugin-jest": "^27.4.2",
75
- "eslint-plugin-prettier": "^3.1.3",
78
+ "eslint-plugin-jest": "^26.5.3",
79
+ "eslint-plugin-prettier": "^4.2.1",
76
80
  "husky": "^6.0.0",
77
81
  "jest": "^29.2.1",
78
82
  "pod-install": "^0.1.0",
79
- "prettier": "^2.4.1",
83
+ "prettier": "^2.8.8",
80
84
  "react": "18.2.0",
81
85
  "react-native": "0.72.4",
82
86
  "react-native-builder-bob": "^0.18.0",
83
- "react-native-reanimated": "3.4.2",
87
+ "react-native-reanimated": "3.6.1",
84
88
  "release-it": "^14.2.2",
85
89
  "typescript": "^4.8.4"
86
90
  },
@@ -120,10 +124,7 @@
120
124
  },
121
125
  "prettier": {
122
126
  "quoteProps": "consistent",
123
- "singleQuote": true,
124
- "tabWidth": 2,
125
- "trailingComma": "es5",
126
- "useTabs": false
127
+ "trailingComma": "all"
127
128
  },
128
129
  "react-native-builder-bob": {
129
130
  "source": "src",
@@ -24,7 +24,7 @@ Pod::Spec.new do |s|
24
24
  if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
25
25
  s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
26
26
  s.pod_target_xcconfig = {
27
- "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
27
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"${PODS_ROOT}/Headers/Private/Yoga\"",
28
28
  "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
29
29
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
30
30
  # This is handy when we want to detect if new arch is enabled in Swift code
package/src/animated.tsx CHANGED
@@ -1,29 +1,31 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
2
- import { Animated, Platform, StyleSheet } from 'react-native';
3
- import Reanimated, { useSharedValue } from 'react-native-reanimated';
1
+ import React, { useEffect, useMemo, useState } from "react";
2
+ import { Animated, Platform, StyleSheet } from "react-native";
3
+ import Reanimated, { useSharedValue } from "react-native-reanimated";
4
4
 
5
- import { KeyboardControllerView } from './bindings';
6
- import { KeyboardContext } from './context';
7
- import { useAnimatedValue, useSharedHandlers } from './internal';
8
- import { applyMonkeyPatch, revertMonkeyPatch } from './monkey-patch';
5
+ import { KeyboardControllerView } from "./bindings";
6
+ import { KeyboardContext } from "./context";
7
+ import { useAnimatedValue, useSharedHandlers } from "./internal";
8
+ import { applyMonkeyPatch, revertMonkeyPatch } from "./monkey-patch";
9
9
  import {
10
10
  useAnimatedKeyboardHandler,
11
- useFocusedInputHandler,
12
- } from './reanimated';
11
+ useFocusedInputLayoutHandler,
12
+ useFocusedInputTextHandler,
13
+ } from "./reanimated";
13
14
 
14
- import type { KeyboardAnimationContext } from './context';
15
+ import type { KeyboardAnimationContext } from "./context";
15
16
  import type {
17
+ FocusedInputHandler,
16
18
  FocusedInputLayoutChangedEvent,
17
19
  KeyboardControllerProps,
18
20
  KeyboardHandler,
19
21
  NativeEvent,
20
- } from './types';
21
- import type { ViewStyle } from 'react-native';
22
+ } from "./types";
23
+ import type { ViewStyle } from "react-native";
22
24
 
23
25
  const KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(
24
26
  Animated.createAnimatedComponent(
25
- KeyboardControllerView
26
- ) as React.FC<KeyboardControllerProps>
27
+ KeyboardControllerView,
28
+ ) as React.FC<KeyboardControllerProps>,
27
29
  );
28
30
 
29
31
  type Styles = {
@@ -36,8 +38,8 @@ const styles = StyleSheet.create<Styles>({
36
38
  flex: 1,
37
39
  },
38
40
  hidden: {
39
- display: 'none',
40
- position: 'absolute',
41
+ display: "none",
42
+ position: "absolute",
41
43
  },
42
44
  });
43
45
 
@@ -76,6 +78,7 @@ export const KeyboardProvider = ({
76
78
  navigationBarTranslucent,
77
79
  enabled: initiallyEnabled = true,
78
80
  }: KeyboardProviderProps) => {
81
+ // state
79
82
  const [enabled, setEnabled] = useState(initiallyEnabled);
80
83
  // animated values
81
84
  const progress = useAnimatedValue(0);
@@ -84,7 +87,10 @@ export const KeyboardProvider = ({
84
87
  const progressSV = useSharedValue(0);
85
88
  const heightSV = useSharedValue(0);
86
89
  const layout = useSharedValue<FocusedInputLayoutChangedEvent | null>(null);
87
- const { setHandlers, broadcast } = useSharedHandlers<KeyboardHandler>();
90
+ const [setKeyboardHandlers, broadcastKeyboardEvents] =
91
+ useSharedHandlers<KeyboardHandler>();
92
+ const [setInputHandlers, broadcastInputEvents] =
93
+ useSharedHandlers<FocusedInputHandler>();
88
94
  // memo
89
95
  const context = useMemo<KeyboardAnimationContext>(
90
96
  () => ({
@@ -92,17 +98,18 @@ export const KeyboardProvider = ({
92
98
  animated: { progress: progress, height: Animated.multiply(height, -1) },
93
99
  reanimated: { progress: progressSV, height: heightSV },
94
100
  layout,
95
- setHandlers,
101
+ setKeyboardHandlers,
102
+ setInputHandlers,
96
103
  setEnabled,
97
104
  }),
98
- [enabled]
105
+ [enabled],
99
106
  );
100
107
  const style = useMemo(
101
108
  () => [
102
109
  styles.hidden,
103
110
  { transform: [{ translateX: height }, { translateY: progress }] },
104
111
  ],
105
- []
112
+ [],
106
113
  );
107
114
  const onKeyboardMove = useMemo(
108
115
  () =>
@@ -115,13 +122,13 @@ export const KeyboardProvider = ({
115
122
  },
116
123
  },
117
124
  ],
118
- { useNativeDriver: true }
125
+ { useNativeDriver: true },
119
126
  ),
120
- []
127
+ [],
121
128
  );
122
129
  // handlers
123
130
  const updateSharedValues = (event: NativeEvent, platforms: string[]) => {
124
- 'worklet';
131
+ "worklet";
125
132
 
126
133
  if (platforms.includes(Platform.OS)) {
127
134
  progressSV.value = event.progress;
@@ -131,35 +138,35 @@ export const KeyboardProvider = ({
131
138
  const keyboardHandler = useAnimatedKeyboardHandler(
132
139
  {
133
140
  onKeyboardMoveStart: (event: NativeEvent) => {
134
- 'worklet';
141
+ "worklet";
135
142
 
136
- broadcast('onStart', event);
137
- updateSharedValues(event, ['ios']);
143
+ broadcastKeyboardEvents("onStart", event);
144
+ updateSharedValues(event, ["ios"]);
138
145
  },
139
146
  onKeyboardMove: (event: NativeEvent) => {
140
- 'worklet';
147
+ "worklet";
141
148
 
142
- broadcast('onMove', event);
143
- updateSharedValues(event, ['android']);
149
+ broadcastKeyboardEvents("onMove", event);
150
+ updateSharedValues(event, ["android"]);
144
151
  },
145
152
  onKeyboardMoveEnd: (event: NativeEvent) => {
146
- 'worklet';
153
+ "worklet";
147
154
 
148
- broadcast('onEnd', event);
155
+ broadcastKeyboardEvents("onEnd", event);
149
156
  },
150
157
  onKeyboardMoveInteractive: (event: NativeEvent) => {
151
- 'worklet';
158
+ "worklet";
152
159
 
153
- updateSharedValues(event, ['android', 'ios']);
154
- broadcast('onInteractive', event);
160
+ updateSharedValues(event, ["android", "ios"]);
161
+ broadcastKeyboardEvents("onInteractive", event);
155
162
  },
156
163
  },
157
- []
164
+ [],
158
165
  );
159
- const inputHandler = useFocusedInputHandler(
166
+ const inputLayoutHandler = useFocusedInputLayoutHandler(
160
167
  {
161
168
  onFocusedInputLayoutChanged: (e) => {
162
- 'worklet';
169
+ "worklet";
163
170
 
164
171
  if (e.target !== -1) {
165
172
  layout.value = e;
@@ -168,7 +175,17 @@ export const KeyboardProvider = ({
168
175
  }
169
176
  },
170
177
  },
171
- []
178
+ [],
179
+ );
180
+ const inputTextHandler = useFocusedInputTextHandler(
181
+ {
182
+ onFocusedInputTextChanged: (e) => {
183
+ "worklet";
184
+
185
+ broadcastInputEvents("onChangeText", e);
186
+ },
187
+ },
188
+ [],
172
189
  );
173
190
  // effects
174
191
  useEffect(() => {
@@ -184,13 +201,13 @@ export const KeyboardProvider = ({
184
201
  <KeyboardControllerViewAnimated
185
202
  enabled={enabled}
186
203
  onKeyboardMoveReanimated={keyboardHandler}
187
- onKeyboardMoveStart={Platform.OS === 'ios' ? onKeyboardMove : undefined}
188
- onKeyboardMove={Platform.OS === 'android' ? onKeyboardMove : undefined}
204
+ onKeyboardMoveStart={Platform.OS === "ios" ? onKeyboardMove : undefined}
205
+ onKeyboardMove={Platform.OS === "android" ? onKeyboardMove : undefined}
189
206
  onKeyboardMoveInteractive={onKeyboardMove}
190
- onFocusedInputLayoutChangedReanimated={inputHandler}
207
+ onFocusedInputLayoutChangedReanimated={inputLayoutHandler}
208
+ onFocusedInputTextChangedReanimated={inputTextHandler}
191
209
  navigationBarTranslucent={navigationBarTranslucent}
192
210
  statusBarTranslucent={statusBarTranslucent}
193
- // @ts-expect-error https://github.com/software-mansion/react-native-reanimated/pull/4923
194
211
  style={styles.container}
195
212
  >
196
213
  {children}
@@ -1,20 +1,20 @@
1
- import { NativeEventEmitter, Platform } from 'react-native';
1
+ import { NativeEventEmitter, Platform } from "react-native";
2
2
 
3
3
  import type {
4
4
  KeyboardControllerModule,
5
5
  KeyboardControllerProps,
6
6
  KeyboardEventsModule,
7
7
  KeyboardGestureAreaProps,
8
- } from './types';
8
+ } from "./types";
9
9
 
10
10
  const LINKING_ERROR =
11
11
  `The package 'react-native-keyboard-controller' doesn't seem to be linked. Make sure: \n\n` +
12
- Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
13
- '- You rebuilt the app after installing the package\n' +
14
- '- You are not using Expo Go\n';
12
+ Platform.select({ ios: "- You have run 'pod install'\n", default: "" }) +
13
+ "- You rebuilt the app after installing the package\n" +
14
+ "- You are not using Expo Go\n";
15
15
 
16
16
  const RCTKeyboardController =
17
- require('./specs/NativeKeyboardController').default;
17
+ require("./specs/NativeKeyboardController").default;
18
18
  export const KeyboardController = (
19
19
  RCTKeyboardController
20
20
  ? RCTKeyboardController
@@ -24,7 +24,7 @@ export const KeyboardController = (
24
24
  get() {
25
25
  throw new Error(LINKING_ERROR);
26
26
  },
27
- }
27
+ },
28
28
  )
29
29
  ) as KeyboardControllerModule;
30
30
 
@@ -32,11 +32,11 @@ const eventEmitter = new NativeEventEmitter(KeyboardController);
32
32
 
33
33
  export const KeyboardEvents: KeyboardEventsModule = {
34
34
  addListener: (name, cb) =>
35
- eventEmitter.addListener('KeyboardController::' + name, cb),
35
+ eventEmitter.addListener("KeyboardController::" + name, cb),
36
36
  };
37
37
  export const KeyboardControllerView: React.FC<KeyboardControllerProps> =
38
- require('./specs/KeyboardControllerViewNativeComponent').default;
38
+ require("./specs/KeyboardControllerViewNativeComponent").default;
39
39
  export const KeyboardGestureArea: React.FC<KeyboardGestureAreaProps> =
40
- Platform.OS === 'android' && Platform.Version >= 30
41
- ? require('./specs/KeyboardGestureAreaNativeComponent').default
40
+ Platform.OS === "android" && Platform.Version >= 30
41
+ ? require("./specs/KeyboardGestureAreaNativeComponent").default
42
42
  : ({ children }: KeyboardGestureAreaProps) => children;
package/src/bindings.ts CHANGED
@@ -1,17 +1,18 @@
1
- import { View } from 'react-native';
1
+ import { View } from "react-native";
2
2
 
3
3
  import type {
4
4
  KeyboardControllerModule,
5
5
  KeyboardControllerProps,
6
6
  KeyboardEventsModule,
7
7
  KeyboardGestureAreaProps,
8
- } from './types';
9
- import type { EmitterSubscription } from 'react-native';
8
+ } from "./types";
9
+ import type { EmitterSubscription } from "react-native";
10
10
 
11
11
  const NOOP = () => {};
12
12
  export const KeyboardController: KeyboardControllerModule = {
13
13
  setDefaultMode: NOOP,
14
14
  setInputMode: NOOP,
15
+ dismiss: NOOP,
15
16
  addListener: NOOP,
16
17
  removeListeners: NOOP,
17
18
  };