react-native-keyboard-controller 1.15.1 → 1.16.0

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 (53) hide show
  1. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +6 -0
  2. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardGestureAreaViewManager.kt +8 -0
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +77 -51
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +3 -3
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +2 -2
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +7 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +9 -1
  8. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +8 -0
  9. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardGestureAreaViewManager.kt +9 -0
  10. package/ios/animations/KeyboardAnimation.swift +4 -4
  11. package/ios/animations/SpringAnimation.swift +28 -5
  12. package/ios/animations/TimingAnimation.swift +77 -32
  13. package/ios/delegates/KCTextInputCompositeDelegate.swift +73 -1
  14. package/ios/extensions/Notification.swift +4 -0
  15. package/ios/extensions/UIResponder.swift +10 -0
  16. package/ios/interactive/InvisibleInputAccessoryView.swift +59 -0
  17. package/ios/interactive/KeyboardAreaExtender.swift +74 -0
  18. package/ios/interactive/KeyboardOffsetProvider.swift +39 -0
  19. package/ios/observers/FocusedInputObserver.swift +81 -25
  20. package/ios/observers/KeyboardEventsIgnorer.swift +39 -0
  21. package/ios/observers/KeyboardMovementObserver.swift +24 -10
  22. package/ios/protocols/TextInput.swift +2 -0
  23. package/ios/swizzling/UIResponderSwizzle.swift +60 -0
  24. package/ios/traversal/ViewHierarchyNavigator.swift +1 -1
  25. package/ios/views/KeyboardGestureAreaManager.h +31 -0
  26. package/ios/views/KeyboardGestureAreaManager.mm +174 -0
  27. package/lib/commonjs/animated.js +6 -3
  28. package/lib/commonjs/animated.js.map +1 -1
  29. package/lib/commonjs/bindings.native.js +1 -1
  30. package/lib/commonjs/bindings.native.js.map +1 -1
  31. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  32. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js +1 -3
  33. package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
  34. package/lib/commonjs/types.js.map +1 -1
  35. package/lib/module/animated.js +7 -4
  36. package/lib/module/animated.js.map +1 -1
  37. package/lib/module/bindings.native.js +1 -1
  38. package/lib/module/bindings.native.js.map +1 -1
  39. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  40. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js +1 -3
  41. package/lib/module/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
  42. package/lib/module/types.js.map +1 -1
  43. package/lib/typescript/animated.d.ts +9 -1
  44. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +1 -0
  45. package/lib/typescript/specs/KeyboardGestureAreaNativeComponent.d.ts +1 -0
  46. package/lib/typescript/types.d.ts +6 -1
  47. package/package.json +1 -1
  48. package/src/animated.tsx +18 -4
  49. package/src/bindings.native.ts +1 -1
  50. package/src/specs/KeyboardControllerViewNativeComponent.ts +1 -0
  51. package/src/specs/KeyboardGestureAreaNativeComponent.ts +4 -3
  52. package/src/types.ts +6 -1
  53. package/android/src/main/java/com/reactnativekeyboardcontroller/ui/FrameScheduler.kt +0 -43
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport type {\n EmitterSubscription,\n NativeSyntheticEvent,\n TextInputProps,\n ViewProps,\n} from \"react-native\";\n\n// DirectEventHandler events declaration\nexport type NativeEvent = {\n progress: number;\n height: number;\n duration: number;\n target: number;\n};\nexport type FocusedInputLayoutChangedEvent = {\n target: number;\n parentScrollViewTarget: number;\n layout: {\n x: number;\n y: number;\n width: number;\n height: number;\n absoluteX: number;\n absoluteY: number;\n };\n};\nexport type FocusedInputTextChangedEvent = {\n text: string;\n};\nexport type FocusedInputSelectionChangedEvent = {\n target: number;\n selection: {\n start: {\n x: number;\n y: number;\n position: number;\n };\n end: {\n x: number;\n y: number;\n position: number;\n };\n };\n};\nexport type EventWithName<T> = {\n eventName: string;\n} & T;\n\n// native View/Module declarations\nexport type KeyboardControllerProps = {\n //ref prop\n ref?: React.Ref<React.Component<KeyboardControllerProps>>;\n // callback props\n onKeyboardMoveStart?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onKeyboardMove?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onKeyboardMoveEnd?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onKeyboardMoveInteractive?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onFocusedInputLayoutChanged?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>,\n ) => void;\n onFocusedInputTextChanged?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>,\n ) => void;\n onFocusedInputSelectionChanged?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>,\n ) => void;\n // fake props used to activate reanimated bindings\n onKeyboardMoveReanimated?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onFocusedInputLayoutChangedReanimated?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>,\n ) => void;\n onFocusedInputTextChangedReanimated?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>,\n ) => void;\n onFocusedInputSelectionChangedReanimated?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>,\n ) => void;\n // props\n statusBarTranslucent?: boolean;\n navigationBarTranslucent?: boolean;\n enabled?: boolean;\n} & ViewProps;\n\nexport type KeyboardGestureAreaProps = {\n interpolator: \"ios\" | \"linear\";\n /**\n * Whether to allow to show a keyboard from dismissed state by swipe up.\n * Default to `false`.\n */\n showOnSwipeUp?: boolean;\n /**\n * Whether to allow to control a keyboard by gestures. The strategy how\n * it should be controlled is determined by `interpolator` property.\n * Defaults to `true`.\n */\n enableSwipeToDismiss?: boolean;\n /**\n * Extra distance to the keyboard.\n */\n offset?: number;\n} & ViewProps;\nexport type OverKeyboardViewProps = PropsWithChildren<{\n visible: boolean;\n}>;\n\nexport type Direction = \"next\" | \"prev\" | \"current\";\nexport type DismissOptions = {\n keepFocus: boolean;\n};\nexport type KeyboardControllerModule = {\n // android only\n setDefaultMode: () => void;\n setInputMode: (mode: number) => void;\n // all platforms\n dismiss: (options?: DismissOptions) => Promise<void>;\n setFocusTo: (direction: Direction) => void;\n isVisible: () => boolean;\n state: () => KeyboardEventData | null;\n};\nexport type KeyboardControllerNativeModule = {\n // android only\n setDefaultMode: () => void;\n setInputMode: (mode: number) => void;\n // all platforms\n dismiss: (keepFocus: boolean) => void;\n setFocusTo: (direction: Direction) => void;\n // native event module stuff\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\n// Event module declarations\nexport type KeyboardControllerEvents =\n | \"keyboardWillShow\"\n | \"keyboardDidShow\"\n | \"keyboardWillHide\"\n | \"keyboardDidHide\";\nexport type KeyboardEventData = {\n height: number;\n duration: number;\n timestamp: number;\n target: number;\n type: NonNullable<TextInputProps[\"keyboardType\"]>;\n appearance: NonNullable<TextInputProps[\"keyboardAppearance\"]>;\n};\nexport type KeyboardEventsModule = {\n addListener: (\n name: KeyboardControllerEvents,\n cb: (e: KeyboardEventData) => void,\n ) => EmitterSubscription;\n};\nexport type FocusedInputAvailableEvents = \"focusDidSet\";\nexport type FocusedInputEventData = {\n current: number;\n count: number;\n};\nexport type FocusedInputEventsModule = {\n addListener: (\n name: FocusedInputAvailableEvents,\n cb: (e: FocusedInputEventData) => void,\n ) => EmitterSubscription;\n};\nexport type WindowDimensionsAvailableEvents = \"windowDidResize\";\nexport type WindowDimensionsEventData = {\n width: number;\n height: number;\n};\nexport type WindowDimensionsEventsModule = {\n addListener: (\n name: WindowDimensionsAvailableEvents,\n cb: (e: WindowDimensionsEventData) => void,\n ) => EmitterSubscription;\n};\n\n// reanimated hook declaration\nexport type KeyboardHandlerHook<TContext, Event> = (\n handlers: {\n onKeyboardMoveStart?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMove?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMoveEnd?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMoveInteractive?: (e: NativeEvent, context: TContext) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\nexport type FocusedInputLayoutHandlerHook<TContext, Event> = (\n handlers: {\n onFocusedInputLayoutChanged?: (\n e: FocusedInputLayoutChangedEvent,\n context: TContext,\n ) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\nexport type FocusedInputTextHandlerHook<TContext, Event> = (\n handlers: {\n onFocusedInputTextChanged?: (\n e: FocusedInputTextChangedEvent,\n context: TContext,\n ) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\nexport type FocusedInputSelectionHandlerHook<TContext, Event> = (\n handlers: {\n onFocusedInputSelectionChanged?: (\n e: FocusedInputSelectionChangedEvent,\n context: TContext,\n ) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\n\n// package types\nexport type Handlers<T> = Record<string, T | undefined>;\nexport type KeyboardHandler = Partial<{\n onStart: (e: NativeEvent) => void;\n onMove: (e: NativeEvent) => void;\n onEnd: (e: NativeEvent) => void;\n onInteractive: (e: NativeEvent) => void;\n}>;\nexport type KeyboardHandlers = Handlers<KeyboardHandler>;\nexport type FocusedInputHandler = Partial<{\n onChangeText: (e: FocusedInputTextChangedEvent) => void;\n onSelectionChange: (e: FocusedInputSelectionChangedEvent) => void;\n}>;\nexport type FocusedInputHandlers = Handlers<FocusedInputHandler>;\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport type {\n EmitterSubscription,\n NativeSyntheticEvent,\n TextInputProps,\n ViewProps,\n} from \"react-native\";\n\n// DirectEventHandler events declaration\nexport type NativeEvent = {\n progress: number;\n height: number;\n duration: number;\n target: number;\n};\nexport type FocusedInputLayoutChangedEvent = {\n target: number;\n parentScrollViewTarget: number;\n layout: {\n x: number;\n y: number;\n width: number;\n height: number;\n absoluteX: number;\n absoluteY: number;\n };\n};\nexport type FocusedInputTextChangedEvent = {\n text: string;\n};\nexport type FocusedInputSelectionChangedEvent = {\n target: number;\n selection: {\n start: {\n x: number;\n y: number;\n position: number;\n };\n end: {\n x: number;\n y: number;\n position: number;\n };\n };\n};\nexport type EventWithName<T> = {\n eventName: string;\n} & T;\n\n// native View/Module declarations\nexport type KeyboardControllerProps = {\n //ref prop\n ref?: React.Ref<React.Component<KeyboardControllerProps>>;\n // callback props\n onKeyboardMoveStart?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onKeyboardMove?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onKeyboardMoveEnd?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onKeyboardMoveInteractive?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onFocusedInputLayoutChanged?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>,\n ) => void;\n onFocusedInputTextChanged?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>,\n ) => void;\n onFocusedInputSelectionChanged?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>,\n ) => void;\n // fake props used to activate reanimated bindings\n onKeyboardMoveReanimated?: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>,\n ) => void;\n onFocusedInputLayoutChangedReanimated?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputLayoutChangedEvent>>,\n ) => void;\n onFocusedInputTextChangedReanimated?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputTextChangedEvent>>,\n ) => void;\n onFocusedInputSelectionChangedReanimated?: (\n e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>,\n ) => void;\n // props\n statusBarTranslucent?: boolean;\n navigationBarTranslucent?: boolean;\n preserveEdgeToEdge?: boolean;\n enabled?: boolean;\n} & ViewProps;\n\nexport type KeyboardGestureAreaProps = {\n interpolator?: \"ios\" | \"linear\";\n /**\n * Whether to allow to show a keyboard from dismissed state by swipe up.\n * Default to `false`.\n */\n showOnSwipeUp?: boolean;\n /**\n * Whether to allow to control a keyboard by gestures. The strategy how\n * it should be controlled is determined by `interpolator` property.\n * Defaults to `true`.\n */\n enableSwipeToDismiss?: boolean;\n /**\n * Extra distance to the keyboard.\n */\n offset?: number;\n /**\n * A corresponding `nativeID` value from the corresponding `TextInput`.\n */\n textInputNativeID?: string;\n} & ViewProps;\nexport type OverKeyboardViewProps = PropsWithChildren<{\n visible: boolean;\n}>;\n\nexport type Direction = \"next\" | \"prev\" | \"current\";\nexport type DismissOptions = {\n keepFocus: boolean;\n};\nexport type KeyboardControllerModule = {\n // android only\n setDefaultMode: () => void;\n setInputMode: (mode: number) => void;\n // all platforms\n dismiss: (options?: DismissOptions) => Promise<void>;\n setFocusTo: (direction: Direction) => void;\n isVisible: () => boolean;\n state: () => KeyboardEventData | null;\n};\nexport type KeyboardControllerNativeModule = {\n // android only\n setDefaultMode: () => void;\n setInputMode: (mode: number) => void;\n // all platforms\n dismiss: (keepFocus: boolean) => void;\n setFocusTo: (direction: Direction) => void;\n // native event module stuff\n addListener: (eventName: string) => void;\n removeListeners: (count: number) => void;\n};\n\n// Event module declarations\nexport type KeyboardControllerEvents =\n | \"keyboardWillShow\"\n | \"keyboardDidShow\"\n | \"keyboardWillHide\"\n | \"keyboardDidHide\";\nexport type KeyboardEventData = {\n height: number;\n duration: number;\n timestamp: number;\n target: number;\n type: NonNullable<TextInputProps[\"keyboardType\"]>;\n appearance: NonNullable<TextInputProps[\"keyboardAppearance\"]>;\n};\nexport type KeyboardEventsModule = {\n addListener: (\n name: KeyboardControllerEvents,\n cb: (e: KeyboardEventData) => void,\n ) => EmitterSubscription;\n};\nexport type FocusedInputAvailableEvents = \"focusDidSet\";\nexport type FocusedInputEventData = {\n current: number;\n count: number;\n};\nexport type FocusedInputEventsModule = {\n addListener: (\n name: FocusedInputAvailableEvents,\n cb: (e: FocusedInputEventData) => void,\n ) => EmitterSubscription;\n};\nexport type WindowDimensionsAvailableEvents = \"windowDidResize\";\nexport type WindowDimensionsEventData = {\n width: number;\n height: number;\n};\nexport type WindowDimensionsEventsModule = {\n addListener: (\n name: WindowDimensionsAvailableEvents,\n cb: (e: WindowDimensionsEventData) => void,\n ) => EmitterSubscription;\n};\n\n// reanimated hook declaration\nexport type KeyboardHandlerHook<TContext, Event> = (\n handlers: {\n onKeyboardMoveStart?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMove?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMoveEnd?: (e: NativeEvent, context: TContext) => void;\n onKeyboardMoveInteractive?: (e: NativeEvent, context: TContext) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\nexport type FocusedInputLayoutHandlerHook<TContext, Event> = (\n handlers: {\n onFocusedInputLayoutChanged?: (\n e: FocusedInputLayoutChangedEvent,\n context: TContext,\n ) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\nexport type FocusedInputTextHandlerHook<TContext, Event> = (\n handlers: {\n onFocusedInputTextChanged?: (\n e: FocusedInputTextChangedEvent,\n context: TContext,\n ) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\nexport type FocusedInputSelectionHandlerHook<TContext, Event> = (\n handlers: {\n onFocusedInputSelectionChanged?: (\n e: FocusedInputSelectionChangedEvent,\n context: TContext,\n ) => void;\n },\n dependencies?: unknown[],\n) => (e: NativeSyntheticEvent<Event>) => void;\n\n// package types\nexport type Handlers<T> = Record<string, T | undefined>;\nexport type KeyboardHandler = Partial<{\n onStart: (e: NativeEvent) => void;\n onMove: (e: NativeEvent) => void;\n onEnd: (e: NativeEvent) => void;\n onInteractive: (e: NativeEvent) => void;\n}>;\nexport type KeyboardHandlers = Handlers<KeyboardHandler>;\nexport type FocusedInputHandler = Partial<{\n onChangeText: (e: FocusedInputTextChangedEvent) => void;\n onSelectionChange: (e: FocusedInputSelectionChangedEvent) => void;\n}>;\nexport type FocusedInputHandlers = Handlers<FocusedInputHandler>;\n"],"mappings":"","ignoreList":[]}
@@ -19,6 +19,14 @@ type KeyboardProviderProps = {
19
19
  * @platform android
20
20
  */
21
21
  navigationBarTranslucent?: boolean;
22
+ /**
23
+ * A boolean property indicating whether to keep edge-to-edge mode always enabled (even when you disable the module).
24
+ * Defaults to `false`.
25
+ *
26
+ * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/592
27
+ * @platform android
28
+ */
29
+ preserveEdgeToEdge?: boolean;
22
30
  /**
23
31
  * A boolean prop indicating whether the module is enabled. It indicate only initial state,
24
32
  * i. e. if you try to change this prop after component mount it will not have any effect.
@@ -27,5 +35,5 @@ type KeyboardProviderProps = {
27
35
  */
28
36
  enabled?: boolean;
29
37
  };
30
- export declare const KeyboardProvider: ({ children, statusBarTranslucent, navigationBarTranslucent, enabled: initiallyEnabled, }: KeyboardProviderProps) => React.JSX.Element;
38
+ export declare const KeyboardProvider: ({ children, statusBarTranslucent, navigationBarTranslucent, preserveEdgeToEdge, enabled: initiallyEnabled, }: KeyboardProviderProps) => React.JSX.Element;
31
39
  export {};
@@ -41,6 +41,7 @@ export interface NativeProps extends ViewProps {
41
41
  enabled?: boolean;
42
42
  statusBarTranslucent?: boolean;
43
43
  navigationBarTranslucent?: boolean;
44
+ preserveEdgeToEdge?: boolean;
44
45
  onKeyboardMoveStart?: DirectEventHandler<KeyboardMoveEvent>;
45
46
  onKeyboardMove?: DirectEventHandler<KeyboardMoveEvent>;
46
47
  onKeyboardMoveEnd?: DirectEventHandler<KeyboardMoveEvent>;
@@ -6,6 +6,7 @@ export interface NativeProps extends ViewProps {
6
6
  showOnSwipeUp?: boolean;
7
7
  enableSwipeToDismiss?: boolean;
8
8
  offset?: Double;
9
+ textInputNativeID?: string;
9
10
  }
10
11
  declare const _default: HostComponent<NativeProps>;
11
12
  export default _default;
@@ -54,10 +54,11 @@ export type KeyboardControllerProps = {
54
54
  onFocusedInputSelectionChangedReanimated?: (e: NativeSyntheticEvent<EventWithName<FocusedInputSelectionChangedEvent>>) => void;
55
55
  statusBarTranslucent?: boolean;
56
56
  navigationBarTranslucent?: boolean;
57
+ preserveEdgeToEdge?: boolean;
57
58
  enabled?: boolean;
58
59
  } & ViewProps;
59
60
  export type KeyboardGestureAreaProps = {
60
- interpolator: "ios" | "linear";
61
+ interpolator?: "ios" | "linear";
61
62
  /**
62
63
  * Whether to allow to show a keyboard from dismissed state by swipe up.
63
64
  * Default to `false`.
@@ -73,6 +74,10 @@ export type KeyboardGestureAreaProps = {
73
74
  * Extra distance to the keyboard.
74
75
  */
75
76
  offset?: number;
77
+ /**
78
+ * A corresponding `nativeID` value from the corresponding `TextInput`.
79
+ */
80
+ textInputNativeID?: string;
76
81
  } & ViewProps;
77
82
  export type OverKeyboardViewProps = PropsWithChildren<{
78
83
  visible: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-keyboard-controller",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
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",
package/src/animated.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  /* eslint react/jsx-sort-props: off */
2
- import React, { useEffect, useMemo, useRef, useState } from "react";
2
+ import React, { useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import { Animated, Platform, StyleSheet } from "react-native";
4
4
  import {
5
5
  controlEdgeToEdgeValues,
@@ -68,6 +68,14 @@ type KeyboardProviderProps = {
68
68
  * @platform android
69
69
  */
70
70
  navigationBarTranslucent?: boolean;
71
+ /**
72
+ * A boolean property indicating whether to keep edge-to-edge mode always enabled (even when you disable the module).
73
+ * Defaults to `false`.
74
+ *
75
+ * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/592
76
+ * @platform android
77
+ */
78
+ preserveEdgeToEdge?: boolean;
71
79
  /**
72
80
  * A boolean prop indicating whether the module is enabled. It indicate only initial state,
73
81
  * i. e. if you try to change this prop after component mount it will not have any effect.
@@ -85,6 +93,7 @@ export const KeyboardProvider = ({
85
93
  children,
86
94
  statusBarTranslucent,
87
95
  navigationBarTranslucent,
96
+ preserveEdgeToEdge,
88
97
  enabled: initiallyEnabled = true,
89
98
  }: KeyboardProviderProps) => {
90
99
  // ref
@@ -192,8 +201,8 @@ export const KeyboardProvider = ({
192
201
  [],
193
202
  );
194
203
 
195
- // effects
196
- useEffect(() => {
204
+ // layout effects
205
+ useLayoutEffect(() => {
197
206
  if (enabled) {
198
207
  applyMonkeyPatch();
199
208
  } else {
@@ -202,7 +211,11 @@ export const KeyboardProvider = ({
202
211
  }, [enabled]);
203
212
 
204
213
  if (__DEV__) {
205
- controlEdgeToEdgeValues({ statusBarTranslucent, navigationBarTranslucent });
214
+ controlEdgeToEdgeValues({
215
+ statusBarTranslucent,
216
+ navigationBarTranslucent,
217
+ preserveEdgeToEdge,
218
+ });
206
219
  }
207
220
 
208
221
  return (
@@ -212,6 +225,7 @@ export const KeyboardProvider = ({
212
225
  enabled={enabled}
213
226
  navigationBarTranslucent={IS_EDGE_TO_EDGE || navigationBarTranslucent}
214
227
  statusBarTranslucent={IS_EDGE_TO_EDGE || statusBarTranslucent}
228
+ preserveEdgeToEdge={IS_EDGE_TO_EDGE || preserveEdgeToEdge}
215
229
  style={styles.container}
216
230
  // on*Reanimated prop must precede animated handlers to work correctly
217
231
  onKeyboardMoveReanimated={keyboardHandler}
@@ -55,7 +55,7 @@ export const WindowDimensionsEvents: WindowDimensionsEventsModule = {
55
55
  export const KeyboardControllerView: React.FC<KeyboardControllerProps> =
56
56
  require("./specs/KeyboardControllerViewNativeComponent").default;
57
57
  export const KeyboardGestureArea: React.FC<KeyboardGestureAreaProps> =
58
- Platform.OS === "android" && Platform.Version >= 30
58
+ (Platform.OS === "android" && Platform.Version >= 30) || Platform.OS === "ios"
59
59
  ? require("./specs/KeyboardGestureAreaNativeComponent").default
60
60
  : ({ children }: KeyboardGestureAreaProps) => children;
61
61
  export const RCTOverKeyboardView: React.FC<OverKeyboardViewProps> =
@@ -53,6 +53,7 @@ export interface NativeProps extends ViewProps {
53
53
  enabled?: boolean;
54
54
  statusBarTranslucent?: boolean;
55
55
  navigationBarTranslucent?: boolean;
56
+ preserveEdgeToEdge?: boolean;
56
57
  // callbacks
57
58
  /// keyboard
58
59
  onKeyboardMoveStart?: DirectEventHandler<KeyboardMoveEvent>;
@@ -12,8 +12,9 @@ export interface NativeProps extends ViewProps {
12
12
  showOnSwipeUp?: boolean;
13
13
  enableSwipeToDismiss?: boolean;
14
14
  offset?: Double;
15
+ textInputNativeID?: string;
15
16
  }
16
17
 
17
- export default codegenNativeComponent<NativeProps>("KeyboardGestureArea", {
18
- excludedPlatforms: ["iOS"],
19
- }) as HostComponent<NativeProps>;
18
+ export default codegenNativeComponent<NativeProps>(
19
+ "KeyboardGestureArea",
20
+ ) as HostComponent<NativeProps>;
package/src/types.ts CHANGED
@@ -89,11 +89,12 @@ export type KeyboardControllerProps = {
89
89
  // props
90
90
  statusBarTranslucent?: boolean;
91
91
  navigationBarTranslucent?: boolean;
92
+ preserveEdgeToEdge?: boolean;
92
93
  enabled?: boolean;
93
94
  } & ViewProps;
94
95
 
95
96
  export type KeyboardGestureAreaProps = {
96
- interpolator: "ios" | "linear";
97
+ interpolator?: "ios" | "linear";
97
98
  /**
98
99
  * Whether to allow to show a keyboard from dismissed state by swipe up.
99
100
  * Default to `false`.
@@ -109,6 +110,10 @@ export type KeyboardGestureAreaProps = {
109
110
  * Extra distance to the keyboard.
110
111
  */
111
112
  offset?: number;
113
+ /**
114
+ * A corresponding `nativeID` value from the corresponding `TextInput`.
115
+ */
116
+ textInputNativeID?: string;
112
117
  } & ViewProps;
113
118
  export type OverKeyboardViewProps = PropsWithChildren<{
114
119
  visible: boolean;
@@ -1,43 +0,0 @@
1
- package com.reactnativekeyboardcontroller.ui
2
-
3
- import android.view.Choreographer
4
-
5
- /**
6
- * A class that schedules a callback to be executed on each frame using the Android Choreographer framework.
7
- *
8
- * @property callback The function to be executed on each frame.
9
- */
10
- class FrameScheduler(
11
- private val callback: () -> Unit,
12
- ) {
13
- /**
14
- * A FrameCallback instance responsible for running the provided callback
15
- * on each frame and rescheduling itself for the next frame.
16
- */
17
- private val frameCallback =
18
- object : Choreographer.FrameCallback {
19
- override fun doFrame(frameTimeNanoSeconds: Long) {
20
- // Execute the callback
21
- callback()
22
-
23
- // Re-post the callback to the next frame
24
- Choreographer.getInstance().postFrameCallback(this)
25
- }
26
- }
27
-
28
- /**
29
- * Starts the frame callback, which will continuously call the provided function
30
- * on every frame until `stop()` is called.
31
- */
32
- fun start() {
33
- Choreographer.getInstance().postFrameCallback(frameCallback)
34
- }
35
-
36
- /**
37
- * Stops the frame callback from being invoked further. The function will no longer
38
- * be called on each frame until `start()` is invoked again.
39
- */
40
- fun stop() {
41
- Choreographer.getInstance().removeFrameCallback(frameCallback)
42
- }
43
- }