react-native-keyboard-controller 1.2.0 → 1.4.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.
- package/android/build.gradle +0 -40
- package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardAnimationCallback.kt +8 -4
- package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +44 -8
- package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManagerImpl.kt +6 -3
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/KeyboardTransitionEvent.kt +2 -6
- package/ios/.swiftlint.yml +4 -0
- package/ios/KeyboardController.xcodeproj/project.pbxproj +2 -2
- package/ios/KeyboardControllerModule.mm +1 -1
- package/ios/KeyboardControllerView.mm +28 -10
- package/ios/KeyboardControllerViewManager.mm +2 -0
- package/ios/KeyboardControllerViewManager.swift +4 -1
- package/ios/KeyboardMoveEvent.h +1 -0
- package/ios/KeyboardMoveEvent.m +2 -1
- package/ios/KeyboardMovementObserver.swift +89 -4
- package/lib/commonjs/animated.js +44 -63
- package/lib/commonjs/animated.js.map +1 -1
- package/lib/commonjs/context.js +29 -0
- package/lib/commonjs/context.js.map +1 -0
- package/lib/commonjs/hooks.js +64 -0
- package/lib/commonjs/hooks.js.map +1 -0
- package/lib/commonjs/index.js +39 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/internal.js +91 -0
- package/lib/commonjs/internal.js.map +1 -0
- package/lib/commonjs/monkey-patch.js +3 -3
- package/lib/commonjs/monkey-patch.js.map +1 -1
- package/lib/commonjs/native.js +24 -21
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/replicas.js +2 -2
- package/lib/commonjs/replicas.js.map +1 -1
- package/lib/commonjs/{KeyboardControllerViewNativeComponent.js → specs/KeyboardControllerViewNativeComponent.js} +0 -0
- package/lib/commonjs/{KeyboardControllerViewNativeComponent.js.map → specs/KeyboardControllerViewNativeComponent.js.map} +1 -1
- package/lib/commonjs/{NativeKeyboardController.js → specs/NativeKeyboardController.js} +0 -0
- package/lib/commonjs/{NativeKeyboardController.js.map → specs/NativeKeyboardController.js.map} +0 -0
- package/lib/commonjs/{NativeStatusBarManagerCompat.js → specs/NativeStatusBarManagerCompat.js} +0 -0
- package/lib/commonjs/{NativeStatusBarManagerCompat.js.map → specs/NativeStatusBarManagerCompat.js.map} +0 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils.js +11 -0
- package/lib/commonjs/utils.js.map +1 -0
- package/lib/module/animated.js +43 -55
- package/lib/module/animated.js.map +1 -1
- package/lib/module/context.js +19 -0
- package/lib/module/context.js.map +1 -0
- package/lib/module/hooks.js +39 -0
- package/lib/module/hooks.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal.js +80 -0
- package/lib/module/internal.js.map +1 -0
- package/lib/module/monkey-patch.js +4 -3
- package/lib/module/monkey-patch.js.map +1 -1
- package/lib/module/native.js +23 -17
- package/lib/module/native.js.map +1 -1
- package/lib/module/replicas.js +1 -1
- package/lib/module/replicas.js.map +1 -1
- package/lib/module/{KeyboardControllerViewNativeComponent.js → specs/KeyboardControllerViewNativeComponent.js} +0 -0
- package/lib/module/{KeyboardControllerViewNativeComponent.js.map → specs/KeyboardControllerViewNativeComponent.js.map} +1 -1
- package/lib/module/{NativeKeyboardController.js → specs/NativeKeyboardController.js} +0 -0
- package/lib/module/{NativeKeyboardController.js.map → specs/NativeKeyboardController.js.map} +0 -0
- package/lib/module/{NativeStatusBarManagerCompat.js → specs/NativeStatusBarManagerCompat.js} +0 -0
- package/lib/module/{NativeStatusBarManagerCompat.js.map → specs/NativeStatusBarManagerCompat.js.map} +0 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils.js +2 -0
- package/lib/module/utils.js.map +1 -0
- package/lib/typescript/animated.d.ts +1 -17
- package/lib/typescript/context.d.ts +18 -0
- package/lib/typescript/hooks.d.ts +8 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/internal.d.ts +21 -0
- package/lib/typescript/native.d.ts +14 -26
- package/lib/typescript/{KeyboardControllerViewNativeComponent.d.ts → specs/KeyboardControllerViewNativeComponent.d.ts} +2 -0
- package/lib/typescript/{NativeKeyboardController.d.ts → specs/NativeKeyboardController.d.ts} +0 -0
- package/lib/typescript/{NativeStatusBarManagerCompat.d.ts → specs/NativeStatusBarManagerCompat.d.ts} +0 -0
- package/lib/typescript/types.d.ts +32 -0
- package/lib/typescript/utils.d.ts +1 -0
- package/package.json +17 -20
- package/react-native-keyboard-controller.podspec +2 -1
- package/src/animated.tsx +42 -78
- package/src/context.ts +31 -0
- package/src/hooks.ts +56 -0
- package/src/index.ts +3 -0
- package/src/internal.ts +87 -0
- package/src/{monkey-patch.tsx → monkey-patch.ts} +3 -6
- package/src/native.ts +37 -66
- package/src/replicas.ts +1 -1
- package/src/{KeyboardControllerViewNativeComponent.ts → specs/KeyboardControllerViewNativeComponent.ts} +4 -0
- package/src/{NativeKeyboardController.ts → specs/NativeKeyboardController.ts} +0 -0
- package/src/{NativeStatusBarManagerCompat.ts → specs/NativeStatusBarManagerCompat.ts} +0 -0
- package/src/types.ts +60 -0
- package/src/utils.ts +1 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -5
- package/android/gradlew +0 -185
- package/android/gradlew.bat +0 -89
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerComponentsRegistry.kt +0 -31
- package/android/src/main/jni/Android.mk +0 -42
- package/android/src/main/jni/KeyboardControllerComponentsRegistry.cpp +0 -71
- package/android/src/main/jni/KeyboardControllerComponentsRegistry.h +0 -35
- package/android/src/main/jni/OnLoad.cpp +0 -9
- package/lib/commonjs/architecture.js +0 -13
- package/lib/commonjs/architecture.js.map +0 -1
- package/lib/module/architecture.js +0 -5
- package/lib/module/architecture.js.map +0 -1
- package/lib/typescript/architecture.d.ts +0 -2
- package/src/architecture.ts +0 -4
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
4
|
+
import type { KeyboardHandlers } from './types';
|
|
5
|
+
export declare type AnimatedContext = {
|
|
6
|
+
progress: Animated.Value;
|
|
7
|
+
height: Animated.AnimatedMultiplication<number>;
|
|
8
|
+
};
|
|
9
|
+
export declare type ReanimatedContext = {
|
|
10
|
+
progress: SharedValue<number>;
|
|
11
|
+
height: SharedValue<number>;
|
|
12
|
+
};
|
|
13
|
+
export declare type KeyboardAnimationContext = {
|
|
14
|
+
animated: AnimatedContext;
|
|
15
|
+
reanimated: ReanimatedContext;
|
|
16
|
+
setHandlers: (handlers: KeyboardHandlers) => void;
|
|
17
|
+
};
|
|
18
|
+
export declare const KeyboardContext: import("react").Context<KeyboardAnimationContext>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DependencyList } from 'react';
|
|
2
|
+
import { AnimatedContext, ReanimatedContext } from './context';
|
|
3
|
+
import type { KeyboardHandler } from './types';
|
|
4
|
+
export declare const useResizeMode: () => void;
|
|
5
|
+
export declare const useKeyboardAnimation: () => AnimatedContext;
|
|
6
|
+
export declare const useReanimatedKeyboardAnimation: () => ReanimatedContext;
|
|
7
|
+
export declare function useGenericKeyboardHandler(handler: KeyboardHandler, deps?: DependencyList): void;
|
|
8
|
+
export declare function useKeyboardHandler(handler: KeyboardHandler, deps?: DependencyList): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { EventWithName, Handlers, NativeEvent } from './types';
|
|
2
|
+
export declare function useAnimatedKeyboardHandler<TContext extends Record<string, unknown>>(handlers: {
|
|
3
|
+
onKeyboardMoveStart?: (e: NativeEvent, context: TContext) => void;
|
|
4
|
+
onKeyboardMove?: (e: NativeEvent, context: TContext) => void;
|
|
5
|
+
onKeyboardMoveEnd?: (e: NativeEvent, context: TContext) => void;
|
|
6
|
+
}, dependencies?: ReadonlyArray<unknown>): (e: import("react-native").NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Hook for storing worklet handlers (objects with keys, where values are worklets).
|
|
9
|
+
* Returns methods for setting handlers and broadcasting events in them.
|
|
10
|
+
*
|
|
11
|
+
* T is a generic that looks like:
|
|
12
|
+
* @example
|
|
13
|
+
* {
|
|
14
|
+
* onEvent: () => {},
|
|
15
|
+
* onEvent2: () => {},
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
export declare function useSharedHandlers<T extends Record<string, Function>>(): {
|
|
19
|
+
setHandlers: (handler: Handlers<T>) => void;
|
|
20
|
+
broadcast: (type: keyof T, event: NativeEvent) => void;
|
|
21
|
+
};
|
|
@@ -1,34 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { KeyboardControllerEvents, KeyboardControllerModule, KeyboardEventData } from './types';
|
|
2
2
|
export declare enum AndroidSoftInputModes {
|
|
3
3
|
SOFT_INPUT_ADJUST_NOTHING = 48,
|
|
4
4
|
SOFT_INPUT_ADJUST_PAN = 32,
|
|
5
5
|
SOFT_INPUT_ADJUST_RESIZE = 16,
|
|
6
|
-
SOFT_INPUT_ADJUST_UNSPECIFIED = 0
|
|
6
|
+
SOFT_INPUT_ADJUST_UNSPECIFIED = 0,
|
|
7
|
+
SOFT_INPUT_IS_FORWARD_NAVIGATION = 256,
|
|
8
|
+
SOFT_INPUT_MASK_ADJUST = 240,
|
|
9
|
+
SOFT_INPUT_MASK_STATE = 15,
|
|
10
|
+
SOFT_INPUT_MODE_CHANGED = 512,
|
|
11
|
+
SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3,
|
|
12
|
+
SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5,
|
|
13
|
+
SOFT_INPUT_STATE_HIDDEN = 2,
|
|
14
|
+
SOFT_INPUT_STATE_UNCHANGED = 1,
|
|
15
|
+
SOFT_INPUT_STATE_UNSPECIFIED = 0,
|
|
16
|
+
SOFT_INPUT_STATE_VISIBLE = 4
|
|
7
17
|
}
|
|
8
|
-
export declare
|
|
9
|
-
progress: number;
|
|
10
|
-
height: number;
|
|
11
|
-
};
|
|
12
|
-
export declare type EventWithName<T> = {
|
|
13
|
-
eventName: string;
|
|
14
|
-
} & T;
|
|
15
|
-
export declare type KeyboardControllerProps = {
|
|
16
|
-
onKeyboardMove: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
17
|
-
onKeyboardMoveReanimated: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
18
|
-
statusBarTranslucent?: boolean;
|
|
19
|
-
} & ViewProps;
|
|
20
|
-
declare type KeyboardController = {
|
|
21
|
-
setDefaultMode: () => void;
|
|
22
|
-
setInputMode: (mode: AndroidSoftInputModes) => void;
|
|
23
|
-
};
|
|
24
|
-
export declare const KeyboardController: KeyboardController;
|
|
25
|
-
declare type KeyboardControllerEvents = 'keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide';
|
|
26
|
-
declare type KeyboardEvent = {
|
|
27
|
-
height: number;
|
|
28
|
-
};
|
|
18
|
+
export declare const KeyboardController: KeyboardControllerModule;
|
|
29
19
|
export declare const KeyboardEvents: {
|
|
30
|
-
addListener: (name: KeyboardControllerEvents, cb: (e:
|
|
20
|
+
addListener: (name: KeyboardControllerEvents, cb: (e: KeyboardEventData) => void) => import("react-native").EmitterSubscription;
|
|
31
21
|
};
|
|
32
22
|
export declare const KeyboardControllerView: any;
|
|
33
|
-
export declare const useResizeMode: () => void;
|
|
34
|
-
export {};
|
|
@@ -8,6 +8,8 @@ declare type KeyboardMoveEvent = Readonly<{
|
|
|
8
8
|
export interface NativeProps extends ViewProps {
|
|
9
9
|
statusBarTranslucent?: boolean;
|
|
10
10
|
onKeyboardMove?: DirectEventHandler<KeyboardMoveEvent>;
|
|
11
|
+
onKeyboardMoveStart?: DirectEventHandler<KeyboardMoveEvent>;
|
|
12
|
+
onKeyboardMoveEnd?: DirectEventHandler<KeyboardMoveEvent>;
|
|
11
13
|
}
|
|
12
14
|
declare const _default: HostComponent<NativeProps>;
|
|
13
15
|
export default _default;
|
package/lib/typescript/{NativeKeyboardController.d.ts → specs/NativeKeyboardController.d.ts}
RENAMED
|
File without changes
|
package/lib/typescript/{NativeStatusBarManagerCompat.d.ts → specs/NativeStatusBarManagerCompat.d.ts}
RENAMED
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { NativeSyntheticEvent, ViewProps } from 'react-native';
|
|
2
|
+
export declare type NativeEvent = {
|
|
3
|
+
progress: number;
|
|
4
|
+
height: number;
|
|
5
|
+
};
|
|
6
|
+
export declare type EventWithName<T> = {
|
|
7
|
+
eventName: string;
|
|
8
|
+
} & T;
|
|
9
|
+
export declare type KeyboardControllerProps = {
|
|
10
|
+
onKeyboardMoveStart?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
11
|
+
onKeyboardMove?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
12
|
+
onKeyboardMoveEnd?: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
13
|
+
onKeyboardMoveReanimated: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;
|
|
14
|
+
statusBarTranslucent?: boolean;
|
|
15
|
+
} & ViewProps;
|
|
16
|
+
export declare type KeyboardControllerModule = {
|
|
17
|
+
setDefaultMode: () => void;
|
|
18
|
+
setInputMode: (mode: number) => void;
|
|
19
|
+
addListener: (eventName: string) => void;
|
|
20
|
+
removeListeners: (count: number) => void;
|
|
21
|
+
};
|
|
22
|
+
export declare type KeyboardControllerEvents = 'keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide';
|
|
23
|
+
export declare type KeyboardEventData = {
|
|
24
|
+
height: number;
|
|
25
|
+
};
|
|
26
|
+
export declare type Handlers<T> = Record<string, T | undefined>;
|
|
27
|
+
export declare type KeyboardHandler = {
|
|
28
|
+
onStart?: (e: NativeEvent) => void;
|
|
29
|
+
onMove?: (e: NativeEvent) => void;
|
|
30
|
+
onEnd?: (e: NativeEvent) => void;
|
|
31
|
+
};
|
|
32
|
+
export declare type KeyboardHandlers = Handlers<KeyboardHandler>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const uuid: () => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-keyboard-controller",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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",
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
"!lib/typescript/example",
|
|
18
18
|
"!android/build",
|
|
19
19
|
"!android/.gradle",
|
|
20
|
+
"!android/gradle",
|
|
21
|
+
"!android/gradlew",
|
|
22
|
+
"!android/gradlew.bat",
|
|
20
23
|
"!ios/build",
|
|
21
24
|
"!**/__tests__",
|
|
22
25
|
"!**/__fixtures__",
|
|
@@ -55,8 +58,8 @@
|
|
|
55
58
|
"@react-native-community/eslint-config": "^2.0.0",
|
|
56
59
|
"@release-it/conventional-changelog": "^2.0.0",
|
|
57
60
|
"@types/jest": "^27.4.1",
|
|
58
|
-
"@types/react": "^18.0.
|
|
59
|
-
"@types/react-native": "0.
|
|
61
|
+
"@types/react": "^18.0.21",
|
|
62
|
+
"@types/react-native": "0.70.4",
|
|
60
63
|
"commitlint": "^11.0.0",
|
|
61
64
|
"clang-format": "^1.8.0",
|
|
62
65
|
"eslint": "^7.2.0",
|
|
@@ -66,17 +69,17 @@
|
|
|
66
69
|
"jest": "^27.5.1",
|
|
67
70
|
"pod-install": "^0.1.0",
|
|
68
71
|
"prettier": "^2.6.2",
|
|
69
|
-
"react": "18.
|
|
70
|
-
"react-native": "0.
|
|
72
|
+
"react": "18.1.0",
|
|
73
|
+
"react-native": "0.70.2",
|
|
71
74
|
"react-native-builder-bob": "^0.18.0",
|
|
72
|
-
"react-native-reanimated": "2.
|
|
75
|
+
"react-native-reanimated": "2.10.0",
|
|
73
76
|
"release-it": "^14.2.2",
|
|
74
|
-
"typescript": "^4.
|
|
77
|
+
"typescript": "^4.8.4"
|
|
75
78
|
},
|
|
76
79
|
"peerDependencies": {
|
|
77
80
|
"react": "*",
|
|
78
81
|
"react-native": "*",
|
|
79
|
-
"react-native-reanimated": "
|
|
82
|
+
"react-native-reanimated": ">=2.3.0"
|
|
80
83
|
},
|
|
81
84
|
"jest": {
|
|
82
85
|
"preset": "react-native",
|
|
@@ -153,17 +156,11 @@
|
|
|
153
156
|
]
|
|
154
157
|
},
|
|
155
158
|
"codegenConfig": {
|
|
156
|
-
"
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
{
|
|
163
|
-
"name": "RNKeyboardControllerViewSpec",
|
|
164
|
-
"type": "components",
|
|
165
|
-
"jsSrcsDir": "src"
|
|
166
|
-
}
|
|
167
|
-
]
|
|
159
|
+
"name": "reactnativekeyboardcontroller",
|
|
160
|
+
"type": "all",
|
|
161
|
+
"jsSrcsDir": "./src/specs",
|
|
162
|
+
"android": {
|
|
163
|
+
"javaPackageName": "com.reactnativekeyboardcontroller"
|
|
164
|
+
}
|
|
168
165
|
}
|
|
169
166
|
}
|
|
@@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
|
|
12
12
|
s.license = package["license"]
|
|
13
13
|
s.authors = package["author"]
|
|
14
14
|
|
|
15
|
-
s.platforms = { :ios => "
|
|
15
|
+
s.platforms = { :ios => "11.0" }
|
|
16
16
|
s.source = { :git => "https://github.com/kirillzyusko/react-native-keyboard-controller.git", :tag => "#{s.version}" }
|
|
17
17
|
|
|
18
18
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
@@ -25,6 +25,7 @@ Pod::Spec.new do |s|
|
|
|
25
25
|
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
26
26
|
s.pod_target_xcconfig = {
|
|
27
27
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
28
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
28
29
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
29
30
|
}
|
|
30
31
|
|
package/src/animated.tsx
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { Animated, StyleSheet, ViewStyle } from 'react-native';
|
|
3
|
-
import Reanimated, {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from '
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import React, { useMemo, useRef } from 'react';
|
|
2
|
+
import { Animated, Platform, StyleSheet, ViewStyle } from 'react-native';
|
|
3
|
+
import Reanimated, { useSharedValue } from 'react-native-reanimated';
|
|
4
|
+
|
|
5
|
+
import { KeyboardContext } from './context';
|
|
6
|
+
import { useAnimatedKeyboardHandler, useSharedHandlers } from './internal';
|
|
7
|
+
import { KeyboardControllerView } from './native';
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
10
|
KeyboardControllerProps,
|
|
11
|
-
|
|
11
|
+
KeyboardHandler,
|
|
12
12
|
NativeEvent,
|
|
13
|
-
|
|
14
|
-
} from './native';
|
|
13
|
+
} from './types';
|
|
15
14
|
|
|
16
15
|
const KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(
|
|
17
16
|
Animated.createAnimatedComponent(
|
|
@@ -19,66 +18,6 @@ const KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(
|
|
|
19
18
|
) as React.FC<KeyboardControllerProps>
|
|
20
19
|
);
|
|
21
20
|
|
|
22
|
-
type AnimatedContext = {
|
|
23
|
-
progress: Animated.Value;
|
|
24
|
-
height: Animated.Value;
|
|
25
|
-
};
|
|
26
|
-
type ReanimatedContext = {
|
|
27
|
-
progress: Reanimated.SharedValue<number>;
|
|
28
|
-
height: Reanimated.SharedValue<number>;
|
|
29
|
-
};
|
|
30
|
-
type KeyboardAnimationContext = {
|
|
31
|
-
animated: AnimatedContext;
|
|
32
|
-
reanimated: ReanimatedContext;
|
|
33
|
-
};
|
|
34
|
-
const defaultContext: KeyboardAnimationContext = {
|
|
35
|
-
animated: {
|
|
36
|
-
progress: new Animated.Value(0),
|
|
37
|
-
height: new Animated.Value(0),
|
|
38
|
-
},
|
|
39
|
-
reanimated: {
|
|
40
|
-
progress: { value: 0 },
|
|
41
|
-
height: { value: 0 },
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
export const KeyboardContext = React.createContext(defaultContext);
|
|
45
|
-
|
|
46
|
-
export const useKeyboardAnimation = (): AnimatedContext => {
|
|
47
|
-
useResizeMode();
|
|
48
|
-
const context = useContext(KeyboardContext);
|
|
49
|
-
|
|
50
|
-
return context.animated;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const useReanimatedKeyboardAnimation = (): ReanimatedContext => {
|
|
54
|
-
useResizeMode();
|
|
55
|
-
const context = useContext(KeyboardContext);
|
|
56
|
-
|
|
57
|
-
return context.reanimated;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
function useAnimatedKeyboardHandler<TContext extends Record<string, unknown>>(
|
|
61
|
-
handlers: {
|
|
62
|
-
onKeyboardMove?: (e: NativeEvent, context: TContext) => void;
|
|
63
|
-
},
|
|
64
|
-
dependencies?: ReadonlyArray<unknown>
|
|
65
|
-
) {
|
|
66
|
-
const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
|
|
67
|
-
|
|
68
|
-
return useEvent(
|
|
69
|
-
(event: EventWithName<NativeEvent>) => {
|
|
70
|
-
'worklet';
|
|
71
|
-
const { onKeyboardMove } = handlers;
|
|
72
|
-
|
|
73
|
-
if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {
|
|
74
|
-
onKeyboardMove(event, context);
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
['onKeyboardMove'],
|
|
78
|
-
doDependenciesDiffer
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
21
|
type Styles = {
|
|
83
22
|
container: ViewStyle;
|
|
84
23
|
hidden: ViewStyle;
|
|
@@ -112,14 +51,19 @@ export const KeyboardProvider = ({
|
|
|
112
51
|
children,
|
|
113
52
|
statusBarTranslucent,
|
|
114
53
|
}: KeyboardProviderProps) => {
|
|
54
|
+
// animated values
|
|
115
55
|
const progress = useRef(new Animated.Value(0)).current;
|
|
116
56
|
const height = useRef(new Animated.Value(0)).current;
|
|
57
|
+
// shared values
|
|
117
58
|
const progressSV = useSharedValue(0);
|
|
118
59
|
const heightSV = useSharedValue(0);
|
|
60
|
+
const { setHandlers, broadcast } = useSharedHandlers<KeyboardHandler>();
|
|
61
|
+
// memo
|
|
119
62
|
const context = useMemo(
|
|
120
63
|
() => ({
|
|
121
|
-
animated: { progress: progress, height: height },
|
|
64
|
+
animated: { progress: progress, height: Animated.multiply(height, -1) },
|
|
122
65
|
reanimated: { progress: progressSV, height: heightSV },
|
|
66
|
+
setHandlers,
|
|
123
67
|
}),
|
|
124
68
|
[]
|
|
125
69
|
);
|
|
@@ -130,7 +74,6 @@ export const KeyboardProvider = ({
|
|
|
130
74
|
],
|
|
131
75
|
[]
|
|
132
76
|
);
|
|
133
|
-
|
|
134
77
|
const onKeyboardMove = useMemo(
|
|
135
78
|
() =>
|
|
136
79
|
Animated.event(
|
|
@@ -146,13 +89,33 @@ export const KeyboardProvider = ({
|
|
|
146
89
|
),
|
|
147
90
|
[]
|
|
148
91
|
);
|
|
149
|
-
|
|
92
|
+
// handlers
|
|
93
|
+
const updateSharedValues = (event: NativeEvent, platforms: string[]) => {
|
|
94
|
+
'worklet';
|
|
95
|
+
|
|
96
|
+
if (platforms.includes(Platform.OS)) {
|
|
97
|
+
progressSV.value = event.progress;
|
|
98
|
+
heightSV.value = -event.height;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
150
101
|
const handler = useAnimatedKeyboardHandler(
|
|
151
102
|
{
|
|
103
|
+
onKeyboardMoveStart: (event: NativeEvent) => {
|
|
104
|
+
'worklet';
|
|
105
|
+
|
|
106
|
+
broadcast('onStart', event);
|
|
107
|
+
updateSharedValues(event, ['ios']);
|
|
108
|
+
},
|
|
152
109
|
onKeyboardMove: (event: NativeEvent) => {
|
|
153
110
|
'worklet';
|
|
154
|
-
|
|
155
|
-
|
|
111
|
+
|
|
112
|
+
broadcast('onMove', event);
|
|
113
|
+
updateSharedValues(event, ['android']);
|
|
114
|
+
},
|
|
115
|
+
onKeyboardMoveEnd: (event: NativeEvent) => {
|
|
116
|
+
'worklet';
|
|
117
|
+
|
|
118
|
+
broadcast('onEnd', event);
|
|
156
119
|
},
|
|
157
120
|
},
|
|
158
121
|
[]
|
|
@@ -162,7 +125,8 @@ export const KeyboardProvider = ({
|
|
|
162
125
|
<KeyboardContext.Provider value={context}>
|
|
163
126
|
<KeyboardControllerViewAnimated
|
|
164
127
|
onKeyboardMoveReanimated={handler}
|
|
165
|
-
|
|
128
|
+
onKeyboardMoveStart={Platform.OS === 'ios' ? onKeyboardMove : undefined}
|
|
129
|
+
onKeyboardMove={Platform.OS === 'android' ? onKeyboardMove : undefined}
|
|
166
130
|
statusBarTranslucent={statusBarTranslucent}
|
|
167
131
|
style={styles.container}
|
|
168
132
|
>
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
5
|
+
import type { KeyboardHandlers } from './types';
|
|
6
|
+
|
|
7
|
+
export type AnimatedContext = {
|
|
8
|
+
progress: Animated.Value;
|
|
9
|
+
height: Animated.AnimatedMultiplication<number>;
|
|
10
|
+
};
|
|
11
|
+
export type ReanimatedContext = {
|
|
12
|
+
progress: SharedValue<number>;
|
|
13
|
+
height: SharedValue<number>;
|
|
14
|
+
};
|
|
15
|
+
export type KeyboardAnimationContext = {
|
|
16
|
+
animated: AnimatedContext;
|
|
17
|
+
reanimated: ReanimatedContext;
|
|
18
|
+
setHandlers: (handlers: KeyboardHandlers) => void;
|
|
19
|
+
};
|
|
20
|
+
const defaultContext: KeyboardAnimationContext = {
|
|
21
|
+
animated: {
|
|
22
|
+
progress: new Animated.Value(0),
|
|
23
|
+
height: new Animated.Value(0),
|
|
24
|
+
},
|
|
25
|
+
reanimated: {
|
|
26
|
+
progress: { value: 0 },
|
|
27
|
+
height: { value: 0 },
|
|
28
|
+
},
|
|
29
|
+
setHandlers: () => {},
|
|
30
|
+
};
|
|
31
|
+
export const KeyboardContext = createContext(defaultContext);
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { DependencyList, useContext, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { AnimatedContext, KeyboardContext, ReanimatedContext } from './context';
|
|
4
|
+
import { AndroidSoftInputModes, KeyboardController } from './native';
|
|
5
|
+
import { uuid } from './utils';
|
|
6
|
+
|
|
7
|
+
import type { KeyboardHandler } from './types';
|
|
8
|
+
|
|
9
|
+
export const useResizeMode = () => {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
KeyboardController.setInputMode(
|
|
12
|
+
AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return () => KeyboardController.setDefaultMode();
|
|
16
|
+
}, []);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const useKeyboardAnimation = (): AnimatedContext => {
|
|
20
|
+
useResizeMode();
|
|
21
|
+
const context = useContext(KeyboardContext);
|
|
22
|
+
|
|
23
|
+
return context.animated;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const useReanimatedKeyboardAnimation = (): ReanimatedContext => {
|
|
27
|
+
useResizeMode();
|
|
28
|
+
const context = useContext(KeyboardContext);
|
|
29
|
+
|
|
30
|
+
return context.reanimated;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function useGenericKeyboardHandler(
|
|
34
|
+
handler: KeyboardHandler,
|
|
35
|
+
deps?: DependencyList
|
|
36
|
+
) {
|
|
37
|
+
const context = useContext(KeyboardContext);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const key = uuid();
|
|
41
|
+
|
|
42
|
+
context.setHandlers({ [key]: handler });
|
|
43
|
+
|
|
44
|
+
return () => {
|
|
45
|
+
context.setHandlers({ [key]: undefined });
|
|
46
|
+
};
|
|
47
|
+
}, deps);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function useKeyboardHandler(
|
|
51
|
+
handler: KeyboardHandler,
|
|
52
|
+
deps?: DependencyList
|
|
53
|
+
) {
|
|
54
|
+
useResizeMode();
|
|
55
|
+
useGenericKeyboardHandler(handler, deps);
|
|
56
|
+
}
|
package/src/index.ts
CHANGED
package/src/internal.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { useEvent, useHandler, useSharedValue } from 'react-native-reanimated';
|
|
3
|
+
|
|
4
|
+
import type { EventWithName, Handlers, NativeEvent } from './types';
|
|
5
|
+
|
|
6
|
+
export function useAnimatedKeyboardHandler<
|
|
7
|
+
TContext extends Record<string, unknown>
|
|
8
|
+
>(
|
|
9
|
+
handlers: {
|
|
10
|
+
onKeyboardMoveStart?: (e: NativeEvent, context: TContext) => void;
|
|
11
|
+
onKeyboardMove?: (e: NativeEvent, context: TContext) => void;
|
|
12
|
+
onKeyboardMoveEnd?: (e: NativeEvent, context: TContext) => void;
|
|
13
|
+
},
|
|
14
|
+
dependencies?: ReadonlyArray<unknown>
|
|
15
|
+
) {
|
|
16
|
+
const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
|
|
17
|
+
|
|
18
|
+
return useEvent(
|
|
19
|
+
(event: EventWithName<NativeEvent>) => {
|
|
20
|
+
'worklet';
|
|
21
|
+
const { onKeyboardMoveStart, onKeyboardMove, onKeyboardMoveEnd } =
|
|
22
|
+
handlers;
|
|
23
|
+
|
|
24
|
+
if (
|
|
25
|
+
onKeyboardMoveStart &&
|
|
26
|
+
event.eventName.endsWith('onKeyboardMoveStart')
|
|
27
|
+
) {
|
|
28
|
+
onKeyboardMoveStart(event, context);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {
|
|
32
|
+
onKeyboardMove(event, context);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (onKeyboardMoveEnd && event.eventName.endsWith('onKeyboardMoveEnd')) {
|
|
36
|
+
onKeyboardMoveEnd(event, context);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
['onKeyboardMoveStart', 'onKeyboardMove', 'onKeyboardMoveEnd'],
|
|
40
|
+
doDependenciesDiffer
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Hook for storing worklet handlers (objects with keys, where values are worklets).
|
|
46
|
+
* Returns methods for setting handlers and broadcasting events in them.
|
|
47
|
+
*
|
|
48
|
+
* T is a generic that looks like:
|
|
49
|
+
* @example
|
|
50
|
+
* {
|
|
51
|
+
* onEvent: () => {},
|
|
52
|
+
* onEvent2: () => {},
|
|
53
|
+
* }
|
|
54
|
+
*/
|
|
55
|
+
export function useSharedHandlers<T extends Record<string, Function>>() {
|
|
56
|
+
const handlers = useSharedValue<Handlers<T>>({});
|
|
57
|
+
const jsHandlers = useRef<Handlers<T>>({});
|
|
58
|
+
|
|
59
|
+
// since js -> worklet -> js call is asynchronous, we can not write handlers
|
|
60
|
+
// straight into shared variable (using current shared value as a previous result),
|
|
61
|
+
// since there may be a race condition in a call, and closure may have out-of-dated
|
|
62
|
+
// values. As a result, some of handlers may be not written to "all handlers" object.
|
|
63
|
+
// Below we are writing all handlers to `ref` and afterwards synchronize them with
|
|
64
|
+
// shared value (since `refs` are not referring to actual value in worklets).
|
|
65
|
+
// This approach allow us to update synchronously handlers in js thread (and it assures,
|
|
66
|
+
// that it will have all of them) and then update them in worklet thread (calls are
|
|
67
|
+
// happening in FIFO order, so we will always have actual value).
|
|
68
|
+
const updateSharedHandlers = () => {
|
|
69
|
+
handlers.value = jsHandlers.current;
|
|
70
|
+
};
|
|
71
|
+
const setHandlers = useCallback((handler: Handlers<T>) => {
|
|
72
|
+
jsHandlers.current = {
|
|
73
|
+
...jsHandlers.current,
|
|
74
|
+
...handler,
|
|
75
|
+
};
|
|
76
|
+
updateSharedHandlers();
|
|
77
|
+
}, []);
|
|
78
|
+
const broadcast = (type: keyof T, event: NativeEvent) => {
|
|
79
|
+
'worklet';
|
|
80
|
+
|
|
81
|
+
Object.keys(handlers.value).forEach((key) =>
|
|
82
|
+
handlers.value[key]?.[type]?.(event)
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return { setHandlers, broadcast };
|
|
87
|
+
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
2
|
// @ts-expect-error because there is no corresponding type definition
|
|
3
3
|
import * as NativeAndroidManager from 'react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid';
|
|
4
4
|
|
|
5
|
-
import { isTurboModuleEnabled } from './architecture';
|
|
6
|
-
|
|
7
5
|
const getConstants = NativeAndroidManager.default.getConstants;
|
|
8
6
|
|
|
9
|
-
const RCTStatusBarManagerCompat =
|
|
10
|
-
|
|
11
|
-
: NativeModules.StatusBarManagerCompat;
|
|
7
|
+
const RCTStatusBarManagerCompat =
|
|
8
|
+
require('./specs/NativeStatusBarManagerCompat').default;
|
|
12
9
|
|
|
13
10
|
// On Android < 11 RN uses legacy API which breaks EdgeToEdge mode in RN, so
|
|
14
11
|
// in order to use library on all available platforms we have to monkey patch
|