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.
- package/README.md +1 -1
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +4 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputTextChangedEvent.kt +20 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/EditText.kt +36 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/WindowInsetsAnimationCompat.kt +7 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +17 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +12 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +2 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +13 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +5 -0
- package/ios/.clang-format +30 -30
- package/ios/.swiftlint.yml +1 -1
- package/ios/KeyboardController.xcodeproj/project.pbxproj +10 -0
- package/ios/KeyboardControllerModule.mm +14 -0
- package/ios/events/FocusedInputTextChangedEvent.h +16 -0
- package/ios/events/FocusedInputTextChangedEvent.m +72 -0
- package/ios/observers/FocusedInputObserver.swift +29 -14
- package/ios/observers/TextChangeObserver.swift +41 -0
- package/ios/views/KeyboardControllerView.mm +53 -31
- package/ios/views/KeyboardControllerViewManager.mm +1 -0
- package/ios/views/KeyboardControllerViewManager.swift +21 -10
- package/jest/index.js +6 -4
- package/lib/commonjs/animated.js +33 -27
- package/lib/commonjs/animated.js.map +1 -1
- package/lib/commonjs/bindings.js +1 -0
- package/lib/commonjs/bindings.js.map +1 -1
- package/lib/commonjs/bindings.native.js +6 -6
- package/lib/commonjs/bindings.native.js.map +1 -1
- package/lib/commonjs/components/KeyboardAvoidingView/hooks.js +5 -3
- package/lib/commonjs/components/KeyboardAvoidingView/hooks.js.map +1 -1
- package/lib/commonjs/components/KeyboardAvoidingView/index.js +17 -9
- package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +199 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js +100 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/utils.js +28 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/utils.js.map +1 -0
- package/lib/commonjs/components/KeyboardStickyView/index.js +7 -4
- package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
- package/lib/commonjs/components/hooks/useKeyboardInterpolation.js +81 -0
- package/lib/commonjs/components/hooks/useKeyboardInterpolation.js.map +1 -0
- package/lib/commonjs/components/index.js +7 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/context.js +2 -1
- package/lib/commonjs/context.js.map +1 -1
- package/lib/commonjs/hooks.js +17 -2
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/commonjs/index.js +8 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/internal.js +3 -6
- package/lib/commonjs/internal.js.map +1 -1
- package/lib/commonjs/monkey-patch.android.js +1 -1
- package/lib/commonjs/monkey-patch.android.js.map +1 -1
- package/lib/commonjs/monkey-patch.js.map +1 -1
- package/lib/commonjs/reanimated.js +5 -3
- package/lib/commonjs/reanimated.js.map +1 -1
- package/lib/commonjs/reanimated.native.js +29 -12
- package/lib/commonjs/reanimated.native.js.map +1 -1
- package/lib/commonjs/replicas.js +7 -5
- package/lib/commonjs/replicas.js.map +1 -1
- package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js +1 -1
- package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js +2 -2
- package/lib/commonjs/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/NativeKeyboardController.js +1 -1
- package/lib/commonjs/specs/NativeKeyboardController.js.map +1 -1
- package/lib/commonjs/specs/NativeStatusBarManagerCompat.js +1 -1
- package/lib/commonjs/specs/NativeStatusBarManagerCompat.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/module/animated.js +41 -35
- package/lib/module/animated.js.map +1 -1
- package/lib/module/bindings.js +2 -1
- package/lib/module/bindings.js.map +1 -1
- package/lib/module/bindings.native.js +7 -7
- package/lib/module/bindings.native.js.map +1 -1
- package/lib/module/components/KeyboardAvoidingView/hooks.js +7 -5
- package/lib/module/components/KeyboardAvoidingView/hooks.js.map +1 -1
- package/lib/module/components/KeyboardAvoidingView/index.js +20 -13
- package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/module/components/KeyboardAwareScrollView/index.js +190 -0
- package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -0
- package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js +93 -0
- package/lib/module/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.js.map +1 -0
- package/lib/module/components/KeyboardAwareScrollView/utils.js +21 -0
- package/lib/module/components/KeyboardAwareScrollView/utils.js.map +1 -0
- package/lib/module/components/KeyboardStickyView/index.js +9 -7
- package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
- package/lib/module/components/hooks/useKeyboardInterpolation.js +74 -0
- package/lib/module/components/hooks/useKeyboardInterpolation.js.map +1 -0
- package/lib/module/components/index.js +3 -2
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/context.js +4 -3
- package/lib/module/context.js.map +1 -1
- package/lib/module/hooks.js +21 -7
- package/lib/module/hooks.js.map +1 -1
- package/lib/module/index.js +8 -8
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal.js +6 -9
- package/lib/module/internal.js.map +1 -1
- package/lib/module/monkey-patch.android.js +2 -2
- package/lib/module/monkey-patch.android.js.map +1 -1
- package/lib/module/monkey-patch.js.map +1 -1
- package/lib/module/reanimated.js +2 -1
- package/lib/module/reanimated.js.map +1 -1
- package/lib/module/reanimated.native.js +27 -11
- package/lib/module/reanimated.native.js.map +1 -1
- package/lib/module/replicas.js +13 -11
- package/lib/module/replicas.js.map +1 -1
- package/lib/module/specs/KeyboardControllerViewNativeComponent.js +2 -2
- package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
- package/lib/module/specs/KeyboardGestureAreaNativeComponent.js +3 -3
- package/lib/module/specs/KeyboardGestureAreaNativeComponent.js.map +1 -1
- package/lib/module/specs/NativeKeyboardController.js +2 -2
- package/lib/module/specs/NativeKeyboardController.js.map +1 -1
- package/lib/module/specs/NativeStatusBarManagerCompat.js +2 -2
- package/lib/module/specs/NativeStatusBarManagerCompat.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/animated.d.ts +1 -1
- package/lib/typescript/bindings.d.ts +1 -1
- package/lib/typescript/bindings.native.d.ts +1 -1
- package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +4 -4
- package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +45 -0
- package/lib/typescript/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.d.ts +6 -0
- package/lib/typescript/components/KeyboardAwareScrollView/utils.d.ts +1 -0
- package/lib/typescript/components/KeyboardStickyView/index.d.ts +2 -2
- package/lib/typescript/components/hooks/useKeyboardInterpolation.d.ts +20 -0
- package/lib/typescript/components/index.d.ts +3 -2
- package/lib/typescript/context.d.ts +6 -5
- package/lib/typescript/hooks.d.ts +4 -3
- package/lib/typescript/index.d.ts +8 -8
- package/lib/typescript/internal.d.ts +9 -6
- package/lib/typescript/reanimated.d.ts +3 -2
- package/lib/typescript/reanimated.native.d.ts +3 -2
- package/lib/typescript/replicas.d.ts +1 -1
- package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +7 -3
- package/lib/typescript/specs/KeyboardGestureAreaNativeComponent.d.ts +4 -4
- package/lib/typescript/specs/NativeKeyboardController.d.ts +2 -1
- package/lib/typescript/specs/NativeStatusBarManagerCompat.d.ts +1 -1
- package/lib/typescript/types.d.ts +18 -5
- package/package.json +12 -11
- package/react-native-keyboard-controller.podspec +1 -1
- package/src/animated.tsx +59 -42
- package/src/bindings.native.ts +11 -11
- package/src/bindings.ts +4 -3
- package/src/components/KeyboardAvoidingView/hooks.ts +9 -6
- package/src/components/KeyboardAvoidingView/index.tsx +30 -27
- package/src/components/KeyboardAwareScrollView/index.tsx +262 -0
- package/src/components/KeyboardAwareScrollView/useSmoothKeyboardHandler.ts +123 -0
- package/src/components/KeyboardAwareScrollView/utils.ts +26 -0
- package/src/components/KeyboardStickyView/index.tsx +12 -18
- package/src/components/hooks/useKeyboardInterpolation.ts +96 -0
- package/src/components/index.ts +3 -2
- package/src/context.ts +15 -9
- package/src/hooks.ts +30 -13
- package/src/index.ts +12 -8
- package/src/internal.ts +22 -13
- package/src/monkey-patch.android.ts +2 -2
- package/src/reanimated.native.ts +43 -18
- package/src/reanimated.ts +9 -3
- package/src/replicas.ts +18 -17
- package/src/specs/KeyboardControllerViewNativeComponent.ts +12 -5
- package/src/specs/KeyboardGestureAreaNativeComponent.ts +7 -7
- package/src/specs/NativeKeyboardController.ts +4 -3
- package/src/specs/NativeStatusBarManagerCompat.ts +3 -3
- package/src/types.ts +45 -19
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
interpolate as interpolateREA,
|
|
3
|
+
useSharedValue,
|
|
4
|
+
} from "react-native-reanimated";
|
|
5
|
+
|
|
6
|
+
import { useKeyboardHandler } from "../../hooks";
|
|
7
|
+
|
|
8
|
+
type KeyboardInterpolationOutput = [number, number];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Hook that can be used for interpolation keyboard movement. The main concern is the thing
|
|
12
|
+
* when keyboard is opened and gets resized on Android. Let's say we are interpolating from
|
|
13
|
+
* closed to open [0, 200] and we want to interpolate it to [0, 230] (to achieve nice parallax effect).
|
|
14
|
+
* Then let's say keyboard changes its height to 220 (and we want to interpolate the value to 250, +30
|
|
15
|
+
* to keyboard height). If we interpolate based on `progress` value, then we will have a jump on first frame:
|
|
16
|
+
* the last interpolated position was 230, now we will interpolate to 250, but first frame will be calculated
|
|
17
|
+
* as 200 / 220 * 250 = 227 (and last interpolated position was 230) so we will have a jump.
|
|
18
|
+
*
|
|
19
|
+
* This hook handles it, and when keyboard changes its size it does an interpolation as:
|
|
20
|
+
* [200, 220] -> [230, 250], i. e. we preserve last interpolated value and use it as initial value for interpolation
|
|
21
|
+
* and because of that we will not have a jump and animation will start from the last frame and will be smooth.
|
|
22
|
+
*
|
|
23
|
+
* @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/315
|
|
24
|
+
*/
|
|
25
|
+
const useKeyboardInterpolation = () => {
|
|
26
|
+
// keyboard heights
|
|
27
|
+
const nextKeyboardHeight = useSharedValue(0);
|
|
28
|
+
const prevKeyboardHeight = useSharedValue(0);
|
|
29
|
+
// save latest interpolated position
|
|
30
|
+
const lastInterpolation = useSharedValue(0);
|
|
31
|
+
// boolean flag indicating which output range should be used
|
|
32
|
+
const shouldUseInternalInterpolation = useSharedValue(false);
|
|
33
|
+
|
|
34
|
+
const interpolate = (
|
|
35
|
+
keyboardPosition: number,
|
|
36
|
+
output: KeyboardInterpolationOutput,
|
|
37
|
+
) => {
|
|
38
|
+
"worklet";
|
|
39
|
+
|
|
40
|
+
lastInterpolation.value = interpolateREA(
|
|
41
|
+
keyboardPosition,
|
|
42
|
+
[prevKeyboardHeight.value, nextKeyboardHeight.value],
|
|
43
|
+
shouldUseInternalInterpolation.value
|
|
44
|
+
? [lastInterpolation.value, output[1]]
|
|
45
|
+
: output,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return lastInterpolation.value;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
useKeyboardHandler(
|
|
52
|
+
{
|
|
53
|
+
onStart: (e) => {
|
|
54
|
+
"worklet";
|
|
55
|
+
|
|
56
|
+
const keyboardWillBeHidden = e.height === 0;
|
|
57
|
+
|
|
58
|
+
// keyboard will be hidden
|
|
59
|
+
if (keyboardWillBeHidden) {
|
|
60
|
+
shouldUseInternalInterpolation.value = false;
|
|
61
|
+
prevKeyboardHeight.value = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// keyboard will change its size
|
|
65
|
+
if (
|
|
66
|
+
// keyboard is shown on screen
|
|
67
|
+
nextKeyboardHeight.value !== 0 &&
|
|
68
|
+
// it really changes size (handles iOS case when after interactive keyboard gets shown again)
|
|
69
|
+
nextKeyboardHeight.value !== e.height &&
|
|
70
|
+
// keyboard is not hiding
|
|
71
|
+
!keyboardWillBeHidden
|
|
72
|
+
) {
|
|
73
|
+
prevKeyboardHeight.value = nextKeyboardHeight.value;
|
|
74
|
+
shouldUseInternalInterpolation.value = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// keyboard will show or change size
|
|
78
|
+
if (!keyboardWillBeHidden) {
|
|
79
|
+
nextKeyboardHeight.value = e.height;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
onEnd: (e) => {
|
|
83
|
+
"worklet";
|
|
84
|
+
|
|
85
|
+
// handles case show -> resize -> hide -> show
|
|
86
|
+
// here we reset value to 0 when keyboard is hidden
|
|
87
|
+
nextKeyboardHeight.value = e.height;
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
[],
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
return { interpolate };
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export default useKeyboardInterpolation;
|
package/src/components/index.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { default as KeyboardAvoidingView } from
|
|
2
|
-
export { default as KeyboardStickyView } from
|
|
1
|
+
export { default as KeyboardAvoidingView } from "./KeyboardAvoidingView";
|
|
2
|
+
export { default as KeyboardStickyView } from "./KeyboardStickyView";
|
|
3
|
+
export { default as KeyboardAwareScrollView } from "./KeyboardAwareScrollView";
|
package/src/context.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { createContext, useContext } from
|
|
2
|
-
import { Animated } from
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { Animated } from "react-native";
|
|
3
3
|
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import type {
|
|
5
|
+
FocusedInputHandlers,
|
|
6
|
+
FocusedInputLayoutChangedEvent,
|
|
7
|
+
KeyboardHandlers,
|
|
8
|
+
} from "./types";
|
|
9
|
+
import type React from "react";
|
|
10
|
+
import type { SharedValue } from "react-native-reanimated";
|
|
7
11
|
|
|
8
12
|
export type AnimatedContext = {
|
|
9
13
|
progress: Animated.Value;
|
|
@@ -18,7 +22,8 @@ export type KeyboardAnimationContext = {
|
|
|
18
22
|
animated: AnimatedContext;
|
|
19
23
|
reanimated: ReanimatedContext;
|
|
20
24
|
layout: SharedValue<FocusedInputLayoutChangedEvent | null>;
|
|
21
|
-
|
|
25
|
+
setKeyboardHandlers: (handlers: KeyboardHandlers) => void;
|
|
26
|
+
setInputHandlers: (handlers: FocusedInputHandlers) => void;
|
|
22
27
|
setEnabled: React.Dispatch<React.SetStateAction<boolean>>;
|
|
23
28
|
};
|
|
24
29
|
const NOOP = () => {};
|
|
@@ -30,7 +35,7 @@ const withSharedValue = <T>(value: T): SharedValue<T> => ({
|
|
|
30
35
|
});
|
|
31
36
|
const DEFAULT_SHARED_VALUE = withSharedValue(0);
|
|
32
37
|
const DEFAULT_LAYOUT = withSharedValue<FocusedInputLayoutChangedEvent | null>(
|
|
33
|
-
null
|
|
38
|
+
null,
|
|
34
39
|
);
|
|
35
40
|
const defaultContext: KeyboardAnimationContext = {
|
|
36
41
|
enabled: true,
|
|
@@ -43,7 +48,8 @@ const defaultContext: KeyboardAnimationContext = {
|
|
|
43
48
|
height: DEFAULT_SHARED_VALUE,
|
|
44
49
|
},
|
|
45
50
|
layout: DEFAULT_LAYOUT,
|
|
46
|
-
|
|
51
|
+
setKeyboardHandlers: NOOP,
|
|
52
|
+
setInputHandlers: NOOP,
|
|
47
53
|
setEnabled: NOOP,
|
|
48
54
|
};
|
|
49
55
|
export const KeyboardContext = createContext(defaultContext);
|
|
@@ -52,7 +58,7 @@ export const useKeyboardContext = () => {
|
|
|
52
58
|
|
|
53
59
|
if (__DEV__ && context === defaultContext) {
|
|
54
60
|
console.warn(
|
|
55
|
-
"Couldn't find real values for `KeyboardContext`. Please make sure you're inside of `KeyboardProvider` - otherwise functionality of `react-native-keyboard-controller` will not work."
|
|
61
|
+
"Couldn't find real values for `KeyboardContext`. Please make sure you're inside of `KeyboardProvider` - otherwise functionality of `react-native-keyboard-controller` will not work.",
|
|
56
62
|
);
|
|
57
63
|
}
|
|
58
64
|
|
package/src/hooks.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { useEffect } from
|
|
1
|
+
import { useEffect } from "react";
|
|
2
2
|
|
|
3
|
-
import { KeyboardController } from
|
|
4
|
-
import { AndroidSoftInputModes } from
|
|
5
|
-
import { useKeyboardContext } from
|
|
6
|
-
import { uuid } from
|
|
3
|
+
import { KeyboardController } from "./bindings";
|
|
4
|
+
import { AndroidSoftInputModes } from "./constants";
|
|
5
|
+
import { useKeyboardContext } from "./context";
|
|
6
|
+
import { uuid } from "./utils";
|
|
7
7
|
|
|
8
|
-
import type { AnimatedContext, ReanimatedContext } from
|
|
9
|
-
import type { KeyboardHandler } from
|
|
10
|
-
import type { DependencyList } from
|
|
8
|
+
import type { AnimatedContext, ReanimatedContext } from "./context";
|
|
9
|
+
import type { FocusedInputHandler, KeyboardHandler } from "./types";
|
|
10
|
+
import type { DependencyList } from "react";
|
|
11
11
|
|
|
12
12
|
export const useResizeMode = () => {
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
KeyboardController.setInputMode(
|
|
15
|
-
AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE
|
|
15
|
+
AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE,
|
|
16
16
|
);
|
|
17
17
|
|
|
18
18
|
return () => KeyboardController.setDefaultMode();
|
|
@@ -35,24 +35,24 @@ export const useReanimatedKeyboardAnimation = (): ReanimatedContext => {
|
|
|
35
35
|
|
|
36
36
|
export function useGenericKeyboardHandler(
|
|
37
37
|
handler: KeyboardHandler,
|
|
38
|
-
deps?: DependencyList
|
|
38
|
+
deps?: DependencyList,
|
|
39
39
|
) {
|
|
40
40
|
const context = useKeyboardContext();
|
|
41
41
|
|
|
42
42
|
useEffect(() => {
|
|
43
43
|
const key = uuid();
|
|
44
44
|
|
|
45
|
-
context.
|
|
45
|
+
context.setKeyboardHandlers({ [key]: handler });
|
|
46
46
|
|
|
47
47
|
return () => {
|
|
48
|
-
context.
|
|
48
|
+
context.setKeyboardHandlers({ [key]: undefined });
|
|
49
49
|
};
|
|
50
50
|
}, deps);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function useKeyboardHandler(
|
|
54
54
|
handler: KeyboardHandler,
|
|
55
|
-
deps?: DependencyList
|
|
55
|
+
deps?: DependencyList,
|
|
56
56
|
) {
|
|
57
57
|
useResizeMode();
|
|
58
58
|
useGenericKeyboardHandler(handler, deps);
|
|
@@ -69,3 +69,20 @@ export function useReanimatedFocusedInput() {
|
|
|
69
69
|
|
|
70
70
|
return { input: context.layout };
|
|
71
71
|
}
|
|
72
|
+
|
|
73
|
+
export function useFocusedInputHandler(
|
|
74
|
+
handler?: FocusedInputHandler,
|
|
75
|
+
deps?: DependencyList,
|
|
76
|
+
) {
|
|
77
|
+
const context = useKeyboardContext();
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const key = uuid();
|
|
81
|
+
|
|
82
|
+
context.setInputHandlers({ [key]: handler });
|
|
83
|
+
|
|
84
|
+
return () => {
|
|
85
|
+
context.setInputHandlers({ [key]: undefined });
|
|
86
|
+
};
|
|
87
|
+
}, deps);
|
|
88
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
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
8
|
|
|
9
|
-
export {
|
|
9
|
+
export {
|
|
10
|
+
KeyboardAvoidingView,
|
|
11
|
+
KeyboardStickyView,
|
|
12
|
+
KeyboardAwareScrollView,
|
|
13
|
+
} from "./components";
|
package/src/internal.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { useCallback, useRef } from
|
|
2
|
-
import { Animated } from
|
|
3
|
-
import { useSharedValue } from
|
|
1
|
+
import { useCallback, useRef } from "react";
|
|
2
|
+
import { Animated } from "react-native";
|
|
3
|
+
import { useSharedValue } from "react-native-reanimated";
|
|
4
4
|
|
|
5
|
-
import type { Handlers
|
|
5
|
+
import type { Handlers } from "./types";
|
|
6
|
+
|
|
7
|
+
type UntypedHandler = Record<string, (event: never) => void>;
|
|
8
|
+
type SharedHandlersReturnType<T extends UntypedHandler> = [
|
|
9
|
+
(handler: Handlers<T>) => void,
|
|
10
|
+
<K extends keyof T>(type: K, event: Parameters<T[K]>[0]) => void,
|
|
11
|
+
];
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* Hook for storing worklet handlers (objects with keys, where values are worklets).
|
|
@@ -16,8 +22,8 @@ import type { Handlers, NativeEvent } from './types';
|
|
|
16
22
|
* }
|
|
17
23
|
*/
|
|
18
24
|
export function useSharedHandlers<
|
|
19
|
-
T extends
|
|
20
|
-
>() {
|
|
25
|
+
T extends UntypedHandler,
|
|
26
|
+
>(): SharedHandlersReturnType<T> {
|
|
21
27
|
const handlers = useSharedValue<Handlers<T>>({});
|
|
22
28
|
const jsHandlers = useRef<Handlers<T>>({});
|
|
23
29
|
|
|
@@ -40,15 +46,18 @@ export function useSharedHandlers<
|
|
|
40
46
|
};
|
|
41
47
|
updateSharedHandlers();
|
|
42
48
|
}, []);
|
|
43
|
-
const broadcast =
|
|
44
|
-
|
|
49
|
+
const broadcast = <K extends keyof T>(
|
|
50
|
+
type: K,
|
|
51
|
+
event: Parameters<T[K]>[0],
|
|
52
|
+
) => {
|
|
53
|
+
"worklet";
|
|
45
54
|
|
|
46
|
-
Object.keys(handlers.value).forEach((key) =>
|
|
47
|
-
handlers.value[key]?.[type]?.(event)
|
|
48
|
-
);
|
|
55
|
+
Object.keys(handlers.value).forEach((key) => {
|
|
56
|
+
handlers.value[key]?.[type]?.(event);
|
|
57
|
+
});
|
|
49
58
|
};
|
|
50
59
|
|
|
51
|
-
return
|
|
60
|
+
return [setHandlers, broadcast];
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
/**
|
|
@@ -62,7 +71,7 @@ export function useSharedHandlers<
|
|
|
62
71
|
*/
|
|
63
72
|
export function useAnimatedValue(
|
|
64
73
|
initialValue: number,
|
|
65
|
-
config?: Animated.AnimatedConfig
|
|
74
|
+
config?: Animated.AnimatedConfig,
|
|
66
75
|
): Animated.Value {
|
|
67
76
|
const ref = useRef<Animated.Value | null>(null);
|
|
68
77
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @ts-expect-error because there is no corresponding type definition
|
|
2
|
-
import * as NativeAndroidManager from
|
|
2
|
+
import * as NativeAndroidManager from "react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid";
|
|
3
3
|
|
|
4
4
|
const DefaultNativeAndroidManager = NativeAndroidManager.default;
|
|
5
5
|
const getConstants = NativeAndroidManager.default.getConstants;
|
|
6
6
|
const RCTStatusBarManagerCompat =
|
|
7
|
-
require(
|
|
7
|
+
require("./specs/NativeStatusBarManagerCompat").default;
|
|
8
8
|
|
|
9
9
|
// On Android < 11 RN uses legacy API which breaks EdgeToEdge mode in RN, so
|
|
10
10
|
// in order to use library on all available platforms we have to monkey patch
|
package/src/reanimated.native.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { useEvent, useHandler } from
|
|
1
|
+
import { useEvent, useHandler } from "react-native-reanimated";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
4
|
EventWithName,
|
|
5
|
-
FocusedInputHandlerHook,
|
|
6
5
|
FocusedInputLayoutChangedEvent,
|
|
6
|
+
FocusedInputLayoutHandlerHook,
|
|
7
|
+
FocusedInputTextChangedEvent,
|
|
8
|
+
FocusedInputTextHandlerHook,
|
|
7
9
|
KeyboardHandlerHook,
|
|
8
10
|
NativeEvent,
|
|
9
|
-
} from
|
|
11
|
+
} from "./types";
|
|
10
12
|
|
|
11
13
|
export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
|
|
12
14
|
Record<string, unknown>,
|
|
@@ -16,7 +18,7 @@ export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
|
|
|
16
18
|
|
|
17
19
|
return useEvent(
|
|
18
20
|
(event) => {
|
|
19
|
-
|
|
21
|
+
"worklet";
|
|
20
22
|
const {
|
|
21
23
|
onKeyboardMoveStart,
|
|
22
24
|
onKeyboardMove,
|
|
@@ -26,37 +28,37 @@ export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
|
|
|
26
28
|
|
|
27
29
|
if (
|
|
28
30
|
onKeyboardMoveStart &&
|
|
29
|
-
event.eventName.endsWith(
|
|
31
|
+
event.eventName.endsWith("onKeyboardMoveStart")
|
|
30
32
|
) {
|
|
31
33
|
onKeyboardMoveStart(event, context);
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
if (onKeyboardMove && event.eventName.endsWith(
|
|
36
|
+
if (onKeyboardMove && event.eventName.endsWith("onKeyboardMove")) {
|
|
35
37
|
onKeyboardMove(event, context);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
if (onKeyboardMoveEnd && event.eventName.endsWith(
|
|
40
|
+
if (onKeyboardMoveEnd && event.eventName.endsWith("onKeyboardMoveEnd")) {
|
|
39
41
|
onKeyboardMoveEnd(event, context);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
if (
|
|
43
45
|
onKeyboardMoveInteractive &&
|
|
44
|
-
event.eventName.endsWith(
|
|
46
|
+
event.eventName.endsWith("onKeyboardMoveInteractive")
|
|
45
47
|
) {
|
|
46
48
|
onKeyboardMoveInteractive(event, context);
|
|
47
49
|
}
|
|
48
50
|
},
|
|
49
51
|
[
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
"onKeyboardMoveStart",
|
|
53
|
+
"onKeyboardMove",
|
|
54
|
+
"onKeyboardMoveEnd",
|
|
55
|
+
"onKeyboardMoveInteractive",
|
|
54
56
|
],
|
|
55
|
-
doDependenciesDiffer
|
|
57
|
+
doDependenciesDiffer,
|
|
56
58
|
);
|
|
57
59
|
};
|
|
58
60
|
|
|
59
|
-
export const
|
|
61
|
+
export const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<
|
|
60
62
|
Record<string, unknown>,
|
|
61
63
|
EventWithName<FocusedInputLayoutChangedEvent>
|
|
62
64
|
> = (handlers, dependencies) => {
|
|
@@ -64,17 +66,40 @@ export const useFocusedInputHandler: FocusedInputHandlerHook<
|
|
|
64
66
|
|
|
65
67
|
return useEvent(
|
|
66
68
|
(event) => {
|
|
67
|
-
|
|
69
|
+
"worklet";
|
|
68
70
|
const { onFocusedInputLayoutChanged } = handlers;
|
|
69
71
|
|
|
70
72
|
if (
|
|
71
73
|
onFocusedInputLayoutChanged &&
|
|
72
|
-
event.eventName.endsWith(
|
|
74
|
+
event.eventName.endsWith("onFocusedInputLayoutChanged")
|
|
73
75
|
) {
|
|
74
76
|
onFocusedInputLayoutChanged(event, context);
|
|
75
77
|
}
|
|
76
78
|
},
|
|
77
|
-
[
|
|
78
|
-
doDependenciesDiffer
|
|
79
|
+
["onFocusedInputLayoutChanged"],
|
|
80
|
+
doDependenciesDiffer,
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
|
|
85
|
+
Record<string, unknown>,
|
|
86
|
+
EventWithName<FocusedInputTextChangedEvent>
|
|
87
|
+
> = (handlers, dependencies) => {
|
|
88
|
+
const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
|
|
89
|
+
|
|
90
|
+
return useEvent(
|
|
91
|
+
(event) => {
|
|
92
|
+
"worklet";
|
|
93
|
+
const { onFocusedInputTextChanged } = handlers;
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
onFocusedInputTextChanged &&
|
|
97
|
+
event.eventName.endsWith("onFocusedInputTextChanged")
|
|
98
|
+
) {
|
|
99
|
+
onFocusedInputTextChanged(event, context);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
["onFocusedInputTextChanged"],
|
|
103
|
+
doDependenciesDiffer,
|
|
79
104
|
);
|
|
80
105
|
};
|
package/src/reanimated.ts
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
EventWithName,
|
|
3
|
-
FocusedInputHandlerHook,
|
|
4
3
|
FocusedInputLayoutChangedEvent,
|
|
4
|
+
FocusedInputLayoutHandlerHook,
|
|
5
|
+
FocusedInputTextChangedEvent,
|
|
6
|
+
FocusedInputTextHandlerHook,
|
|
5
7
|
KeyboardHandlerHook,
|
|
6
8
|
NativeEvent,
|
|
7
|
-
} from
|
|
9
|
+
} from "./types";
|
|
8
10
|
|
|
9
11
|
const NOOP = () => () => {};
|
|
10
12
|
export const useAnimatedKeyboardHandler: KeyboardHandlerHook<
|
|
11
13
|
Record<string, unknown>,
|
|
12
14
|
EventWithName<NativeEvent>
|
|
13
15
|
> = NOOP;
|
|
14
|
-
export const
|
|
16
|
+
export const useFocusedInputLayoutHandler: FocusedInputLayoutHandlerHook<
|
|
15
17
|
Record<string, unknown>,
|
|
16
18
|
EventWithName<FocusedInputLayoutChangedEvent>
|
|
17
19
|
> = NOOP;
|
|
20
|
+
export const useFocusedInputTextHandler: FocusedInputTextHandlerHook<
|
|
21
|
+
Record<string, unknown>,
|
|
22
|
+
EventWithName<FocusedInputTextChangedEvent>
|
|
23
|
+
> = NOOP;
|
package/src/replicas.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef } from
|
|
2
|
-
import { Animated, Easing, Keyboard, Platform } from
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { Animated, Easing, Keyboard, Platform } from "react-native";
|
|
3
3
|
import {
|
|
4
4
|
runOnUI,
|
|
5
5
|
useAnimatedReaction,
|
|
6
6
|
useDerivedValue,
|
|
7
7
|
useSharedValue,
|
|
8
|
-
useWorkletCallback,
|
|
9
8
|
withSpring,
|
|
10
|
-
} from
|
|
9
|
+
} from "react-native-reanimated";
|
|
11
10
|
|
|
12
|
-
import { KeyboardController } from
|
|
13
|
-
import { AndroidSoftInputModes } from
|
|
14
|
-
import { useReanimatedKeyboardAnimation } from
|
|
11
|
+
import { KeyboardController } from "./bindings";
|
|
12
|
+
import { AndroidSoftInputModes } from "./constants";
|
|
13
|
+
import { useReanimatedKeyboardAnimation } from "./hooks";
|
|
15
14
|
|
|
16
|
-
const availableOSEventType = Platform.OS ===
|
|
15
|
+
const availableOSEventType = Platform.OS === "ios" ? "Will" : "Did";
|
|
17
16
|
|
|
18
17
|
// cubic-bezier(.17,.67,.34,.94)
|
|
19
18
|
export const defaultAndroidEasing = Easing.bezier(0.4, 0.0, 0.2, 1);
|
|
@@ -38,12 +37,12 @@ export const useKeyboardAnimationReplica = (): KeyboardAnimation => {
|
|
|
38
37
|
height: height.current,
|
|
39
38
|
progress: progress.current,
|
|
40
39
|
}),
|
|
41
|
-
[]
|
|
40
|
+
[],
|
|
42
41
|
);
|
|
43
42
|
|
|
44
43
|
useEffect(() => {
|
|
45
44
|
KeyboardController.setInputMode(
|
|
46
|
-
AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE
|
|
45
|
+
AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE,
|
|
47
46
|
);
|
|
48
47
|
|
|
49
48
|
return () => KeyboardController.setDefaultMode();
|
|
@@ -60,7 +59,7 @@ export const useKeyboardAnimationReplica = (): KeyboardAnimation => {
|
|
|
60
59
|
}).start();
|
|
61
60
|
|
|
62
61
|
return () => listener.remove();
|
|
63
|
-
}
|
|
62
|
+
},
|
|
64
63
|
);
|
|
65
64
|
}, []);
|
|
66
65
|
useEffect(() => {
|
|
@@ -75,7 +74,7 @@ export const useKeyboardAnimationReplica = (): KeyboardAnimation => {
|
|
|
75
74
|
}).start();
|
|
76
75
|
|
|
77
76
|
return () => listener.remove();
|
|
78
|
-
}
|
|
77
|
+
},
|
|
79
78
|
);
|
|
80
79
|
}, []);
|
|
81
80
|
|
|
@@ -111,7 +110,9 @@ export const useReanimatedKeyboardAnimationReplica = () => {
|
|
|
111
110
|
|
|
112
111
|
const progress = useDerivedValue(() => height.value / heightEvent.value);
|
|
113
112
|
|
|
114
|
-
const handler =
|
|
113
|
+
const handler = useCallback((_height: number) => {
|
|
114
|
+
"worklet";
|
|
115
|
+
|
|
115
116
|
heightEvent.value = _height;
|
|
116
117
|
}, []);
|
|
117
118
|
|
|
@@ -127,14 +128,14 @@ export const useReanimatedKeyboardAnimationReplica = () => {
|
|
|
127
128
|
height.value = withSpring(_keyboardHeight, IOS_SPRING_CONFIG);
|
|
128
129
|
}
|
|
129
130
|
},
|
|
130
|
-
[]
|
|
131
|
+
[],
|
|
131
132
|
);
|
|
132
133
|
|
|
133
134
|
useEffect(() => {
|
|
134
|
-
const show = Keyboard.addListener(
|
|
135
|
+
const show = Keyboard.addListener("keyboardWillShow", (e) => {
|
|
135
136
|
runOnUI(handler)(-e.endCoordinates.height);
|
|
136
137
|
});
|
|
137
|
-
const hide = Keyboard.addListener(
|
|
138
|
+
const hide = Keyboard.addListener("keyboardWillHide", () => {
|
|
138
139
|
runOnUI(handler)(0);
|
|
139
140
|
});
|
|
140
141
|
|
|
@@ -148,6 +149,6 @@ export const useReanimatedKeyboardAnimationReplica = () => {
|
|
|
148
149
|
};
|
|
149
150
|
|
|
150
151
|
export const useGradualKeyboardAnimation =
|
|
151
|
-
Platform.OS ===
|
|
152
|
+
Platform.OS === "ios"
|
|
152
153
|
? useReanimatedKeyboardAnimationReplica
|
|
153
154
|
: useReanimatedKeyboardAnimation;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import codegenNativeComponent from
|
|
1
|
+
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
|
|
2
2
|
|
|
3
|
-
import type { HostComponent } from
|
|
4
|
-
import type { ViewProps } from
|
|
3
|
+
import type { HostComponent } from "react-native";
|
|
4
|
+
import type { ViewProps } from "react-native/Libraries/Components/View/ViewPropTypes";
|
|
5
5
|
import type {
|
|
6
6
|
DirectEventHandler,
|
|
7
7
|
Double,
|
|
8
8
|
Int32,
|
|
9
|
-
} from
|
|
9
|
+
} from "react-native/Libraries/Types/CodegenTypes";
|
|
10
10
|
|
|
11
11
|
type KeyboardMoveEvent = Readonly<{
|
|
12
12
|
height: Double;
|
|
@@ -27,19 +27,26 @@ type FocusedInputLayoutChangedEvent = Readonly<{
|
|
|
27
27
|
};
|
|
28
28
|
}>;
|
|
29
29
|
|
|
30
|
+
type FocusedInputTextChangedEvent = Readonly<{
|
|
31
|
+
text: string;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
30
34
|
export interface NativeProps extends ViewProps {
|
|
31
35
|
// props
|
|
32
36
|
enabled?: boolean;
|
|
33
37
|
statusBarTranslucent?: boolean;
|
|
34
38
|
navigationBarTranslucent?: boolean;
|
|
35
39
|
// callbacks
|
|
40
|
+
/// keyboard
|
|
36
41
|
onKeyboardMoveStart?: DirectEventHandler<KeyboardMoveEvent>;
|
|
37
42
|
onKeyboardMove?: DirectEventHandler<KeyboardMoveEvent>;
|
|
38
43
|
onKeyboardMoveEnd?: DirectEventHandler<KeyboardMoveEvent>;
|
|
39
44
|
onKeyboardMoveInteractive?: DirectEventHandler<KeyboardMoveEvent>;
|
|
45
|
+
/// focused input
|
|
40
46
|
onFocusedInputLayoutChanged?: DirectEventHandler<FocusedInputLayoutChangedEvent>;
|
|
47
|
+
onFocusedInputTextChanged?: DirectEventHandler<FocusedInputTextChangedEvent>;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
export default codegenNativeComponent<NativeProps>(
|
|
44
|
-
|
|
51
|
+
"KeyboardControllerView",
|
|
45
52
|
) as HostComponent<NativeProps>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import codegenNativeComponent from
|
|
1
|
+
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
|
|
2
2
|
|
|
3
|
-
import type { HostComponent } from
|
|
4
|
-
import type { ViewProps } from
|
|
5
|
-
import type { WithDefault } from
|
|
3
|
+
import type { HostComponent } from "react-native";
|
|
4
|
+
import type { ViewProps } from "react-native/Libraries/Components/View/ViewPropTypes";
|
|
5
|
+
import type { WithDefault } from "react-native/Libraries/Types/CodegenTypes";
|
|
6
6
|
|
|
7
7
|
export interface NativeProps extends ViewProps {
|
|
8
|
-
interpolator?: WithDefault<
|
|
8
|
+
interpolator?: WithDefault<"linear" | "ios", "linear">;
|
|
9
9
|
showOnSwipeUp?: boolean;
|
|
10
10
|
enableSwipeToDismiss?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export default codegenNativeComponent<NativeProps>(
|
|
14
|
-
excludedPlatforms: [
|
|
13
|
+
export default codegenNativeComponent<NativeProps>("KeyboardGestureArea", {
|
|
14
|
+
excludedPlatforms: ["iOS"],
|
|
15
15
|
}) as HostComponent<NativeProps>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { TurboModuleRegistry } from
|
|
1
|
+
import { TurboModuleRegistry } from "react-native";
|
|
2
2
|
|
|
3
|
-
import type { TurboModule } from
|
|
3
|
+
import type { TurboModule } from "react-native";
|
|
4
4
|
|
|
5
5
|
export interface Spec extends TurboModule {
|
|
6
6
|
readonly getConstants: () => {};
|
|
@@ -8,10 +8,11 @@ export interface Spec extends TurboModule {
|
|
|
8
8
|
// methods
|
|
9
9
|
setInputMode(mode: number): void;
|
|
10
10
|
setDefaultMode(): void;
|
|
11
|
+
dismiss(): void;
|
|
11
12
|
|
|
12
13
|
// event emitter
|
|
13
14
|
addListener: (eventName: string) => void;
|
|
14
15
|
removeListeners: (count: number) => void;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export default TurboModuleRegistry.get<Spec>(
|
|
18
|
+
export default TurboModuleRegistry.get<Spec>("KeyboardController");
|