react-native-keyboard-controller 1.17.5 → 1.18.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 +4 -1
- package/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +3 -2
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardBackgroundViewManager.kt +19 -0
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +4 -0
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt +3 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/Context.kt +20 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +2 -12
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardBackgroundViewManagerImpl.kt +13 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +2 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +4 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/{StatusBarManagerCompatModuleImpl.kt → statusbar/StatusBarManagerCompatModuleImpl.kt} +31 -5
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/statusbar/StatusBarModuleProxy.kt +86 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +9 -11
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/background/KeyboardBackgroundViewGroup.kt +35 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/background/Skins.kt +91 -0
- package/android/src/main/jni/reactnativekeyboardcontroller.h +1 -0
- package/android/src/main/res/values/attrs.xml +7 -0
- package/android/src/main/res/values/colors.xml +35 -0
- package/android/src/main/res/values-v29/colors.xml +5 -0
- package/android/src/main/res/values-v30/colors.xml +17 -0
- package/android/src/main/res/values-v33/colors.xml +16 -0
- package/android/src/main/res/values-v34/colors.xml +18 -0
- package/android/src/main/res/values-v35/colors.xml +10 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardBackgroundViewManager.kt +15 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +5 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt +3 -1
- package/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +2 -2
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardBackgroundViewComponentDescriptor.h +27 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardBackgroundViewShadowNode.cpp +14 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardBackgroundViewShadowNode.h +30 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardBackgroundViewState.h +28 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardExtenderComponentDescriptor.h +27 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardExtenderShadowNode.cpp +14 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardExtenderShadowNode.h +30 -0
- package/common/cpp/react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardExtenderState.h +28 -0
- package/ios/KeyboardControllerModule.mm +9 -0
- package/ios/delegates/KCTextInputCompositeDelegate.swift +5 -5
- package/ios/events/KeyboardEventEmitterPayload.swift +1 -1
- package/ios/extensions/UIResponder.swift +27 -0
- package/ios/interactive/KeyboardAreaExtender.swift +5 -5
- package/ios/observers/FocusedInputObserver.swift +14 -5
- package/ios/observers/KeyboardMovementObserver.swift +7 -1
- package/ios/protocols/TextInput.swift +22 -0
- package/ios/swizzling/UIResponderSwizzle.swift +3 -0
- package/ios/views/KeyboardBackgroundViewManager.h +29 -0
- package/ios/views/KeyboardBackgroundViewManager.mm +175 -0
- package/ios/views/KeyboardExtenderContainerView.swift +59 -0
- package/ios/views/KeyboardExtenderManager.h +29 -0
- package/ios/views/KeyboardExtenderManager.mm +287 -0
- package/jest/index.js +6 -1
- package/lib/commonjs/animated.js +7 -10
- package/lib/commonjs/animated.js.map +1 -1
- package/lib/commonjs/bindings.js +15 -1
- package/lib/commonjs/bindings.js.map +1 -1
- package/lib/commonjs/bindings.native.js +5 -1
- package/lib/commonjs/bindings.native.js.map +1 -1
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +49 -29
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/Arrow.js +2 -3
- package/lib/commonjs/components/KeyboardToolbar/Arrow.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/Button.js +2 -3
- package/lib/commonjs/components/KeyboardToolbar/Button.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/index.js +2 -2
- package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/commonjs/hooks/useKeyboardState/index.js +18 -8
- package/lib/commonjs/hooks/useKeyboardState/index.js.map +1 -1
- package/lib/commonjs/index.js +8 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/module.js +2 -1
- package/lib/commonjs/module.js.map +1 -1
- package/lib/commonjs/specs/KeyboardBackgroundViewNativeComponent.js +12 -0
- package/lib/commonjs/specs/KeyboardBackgroundViewNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/KeyboardExtenderNativeComponent.js +13 -0
- package/lib/commonjs/specs/KeyboardExtenderNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/NativeKeyboardController.js.map +1 -1
- package/lib/commonjs/types/module.js.map +1 -1
- package/lib/commonjs/types/views.js.map +1 -1
- package/lib/commonjs/views/KeyboardExtender/index.ios.js +43 -0
- package/lib/commonjs/views/KeyboardExtender/index.ios.js.map +1 -0
- package/lib/commonjs/views/KeyboardExtender/index.js +46 -0
- package/lib/commonjs/views/KeyboardExtender/index.js.map +1 -0
- package/lib/commonjs/views/index.js +7 -0
- package/lib/commonjs/views/index.js.map +1 -1
- package/lib/module/animated.js +8 -11
- package/lib/module/animated.js.map +1 -1
- package/lib/module/bindings.js +14 -0
- package/lib/module/bindings.js.map +1 -1
- package/lib/module/bindings.native.js +4 -0
- package/lib/module/bindings.native.js.map +1 -1
- package/lib/module/components/KeyboardAwareScrollView/index.js +50 -30
- package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/Arrow.js +2 -2
- package/lib/module/components/KeyboardToolbar/Arrow.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/Button.js +2 -2
- package/lib/module/components/KeyboardToolbar/Button.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/index.js +2 -2
- package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/module/hooks/useKeyboardState/index.js +18 -6
- package/lib/module/hooks/useKeyboardState/index.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/module.js +2 -1
- package/lib/module/module.js.map +1 -1
- package/lib/module/specs/KeyboardBackgroundViewNativeComponent.js +5 -0
- package/lib/module/specs/KeyboardBackgroundViewNativeComponent.js.map +1 -0
- package/lib/module/specs/KeyboardExtenderNativeComponent.js +6 -0
- package/lib/module/specs/KeyboardExtenderNativeComponent.js.map +1 -0
- package/lib/module/specs/NativeKeyboardController.js.map +1 -1
- package/lib/module/types/module.js.map +1 -1
- package/lib/module/types/views.js.map +1 -1
- package/lib/module/views/KeyboardExtender/index.ios.js +36 -0
- package/lib/module/views/KeyboardExtender/index.ios.js.map +1 -0
- package/lib/module/views/KeyboardExtender/index.js +39 -0
- package/lib/module/views/KeyboardExtender/index.js.map +1 -0
- package/lib/module/views/index.js +1 -0
- package/lib/module/views/index.js.map +1 -1
- package/lib/typescript/animated.d.ts +7 -0
- package/lib/typescript/bindings.d.ts +14 -1
- package/lib/typescript/bindings.native.d.ts +3 -1
- package/lib/typescript/components/KeyboardAwareScrollView/index.d.ts +2 -2
- package/lib/typescript/hooks/useKeyboardState/index.d.ts +8 -2
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/specs/KeyboardBackgroundViewNativeComponent.d.ts +6 -0
- package/lib/typescript/specs/KeyboardExtenderNativeComponent.d.ts +7 -0
- package/lib/typescript/specs/NativeKeyboardController.d.ts +1 -0
- package/lib/typescript/types/module.d.ts +15 -3
- package/lib/typescript/types/views.d.ts +5 -0
- package/lib/typescript/views/KeyboardExtender/index.d.ts +19 -0
- package/lib/typescript/views/KeyboardExtender/index.ios.d.ts +19 -0
- package/lib/typescript/views/index.d.ts +1 -0
- package/package.json +7 -3
- package/react-native.config.js +1 -0
- package/src/animated.tsx +14 -9
- package/src/bindings.native.ts +8 -0
- package/src/bindings.ts +18 -0
- package/src/components/KeyboardAwareScrollView/index.tsx +72 -47
- package/src/components/KeyboardToolbar/Arrow.tsx +2 -2
- package/src/components/KeyboardToolbar/Button.tsx +2 -2
- package/src/components/KeyboardToolbar/index.tsx +2 -2
- package/src/hooks/useKeyboardState/index.ts +25 -6
- package/src/index.ts +1 -1
- package/src/module.ts +2 -1
- package/src/specs/KeyboardBackgroundViewNativeComponent.ts +10 -0
- package/src/specs/KeyboardExtenderNativeComponent.ts +13 -0
- package/src/specs/NativeKeyboardController.ts +1 -0
- package/src/types/module.ts +17 -3
- package/src/types/views.ts +5 -0
- package/src/views/KeyboardExtender/index.ios.tsx +35 -0
- package/src/views/KeyboardExtender/index.tsx +42 -0
- package/src/views/index.ts +1 -0
- package/ios/extensions/UIKeyboardAppearance.swift +0 -21
- package/lib/commonjs/components/hooks/useColorScheme.js +0 -10
- package/lib/commonjs/components/hooks/useColorScheme.js.map +0 -1
- package/lib/commonjs/monkey-patch.android.js +0 -53
- package/lib/commonjs/monkey-patch.android.js.map +0 -1
- package/lib/commonjs/monkey-patch.js +0 -11
- package/lib/commonjs/monkey-patch.js.map +0 -1
- package/lib/module/components/hooks/useColorScheme.js +0 -4
- package/lib/module/components/hooks/useColorScheme.js.map +0 -1
- package/lib/module/monkey-patch.android.js +0 -42
- package/lib/module/monkey-patch.android.js.map +0 -1
- package/lib/module/monkey-patch.js +0 -5
- package/lib/module/monkey-patch.js.map +0 -1
- package/lib/typescript/components/hooks/useColorScheme.d.ts +0 -2
- package/lib/typescript/monkey-patch.android.d.ts +0 -2
- package/lib/typescript/monkey-patch.d.ts +0 -2
- package/src/components/hooks/useColorScheme.ts +0 -5
- package/src/monkey-patch.android.ts +0 -41
- package/src/monkey-patch.ts +0 -5
package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardBackgroundViewManager.kt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.reactnativekeyboardcontroller
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
4
|
+
import com.facebook.react.views.view.ReactViewManager
|
|
5
|
+
import com.reactnativekeyboardcontroller.managers.KeyboardBackgroundViewManagerImpl
|
|
6
|
+
import com.reactnativekeyboardcontroller.views.background.KeyboardBackgroundViewGroup
|
|
7
|
+
|
|
8
|
+
class KeyboardBackgroundViewManager : ReactViewManager() {
|
|
9
|
+
private val manager = KeyboardBackgroundViewManagerImpl()
|
|
10
|
+
|
|
11
|
+
override fun getName(): String = KeyboardBackgroundViewManagerImpl.NAME
|
|
12
|
+
|
|
13
|
+
override fun createViewInstance(reactContext: ThemedReactContext): KeyboardBackgroundViewGroup =
|
|
14
|
+
manager.createViewInstance(reactContext)
|
|
15
|
+
}
|
package/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt
CHANGED
|
@@ -5,7 +5,7 @@ import androidx.annotation.RequiresApi
|
|
|
5
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
6
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
7
7
|
import com.facebook.react.bridge.ReactMethod
|
|
8
|
-
import com.reactnativekeyboardcontroller.modules.StatusBarManagerCompatModuleImpl
|
|
8
|
+
import com.reactnativekeyboardcontroller.modules.statusbar.StatusBarManagerCompatModuleImpl
|
|
9
9
|
|
|
10
10
|
class StatusBarManagerCompatModule(
|
|
11
11
|
mReactContext: ReactApplicationContext,
|
|
@@ -14,6 +14,8 @@ class StatusBarManagerCompatModule(
|
|
|
14
14
|
|
|
15
15
|
override fun getName(): String = StatusBarManagerCompatModuleImpl.NAME
|
|
16
16
|
|
|
17
|
+
override fun getConstants(): MutableMap<String, Any>? = module.getConstants()
|
|
18
|
+
|
|
17
19
|
@ReactMethod
|
|
18
20
|
private fun setHidden(hidden: Boolean) {
|
|
19
21
|
module.setHidden(hidden)
|
package/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt
CHANGED
|
@@ -7,7 +7,7 @@ import com.facebook.react.module.model.ReactModuleInfo
|
|
|
7
7
|
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
8
|
import com.facebook.react.uimanager.ViewManager
|
|
9
9
|
import com.reactnativekeyboardcontroller.modules.KeyboardControllerModuleImpl
|
|
10
|
-
import com.reactnativekeyboardcontroller.modules.StatusBarManagerCompatModuleImpl
|
|
10
|
+
import com.reactnativekeyboardcontroller.modules.statusbar.StatusBarManagerCompatModuleImpl
|
|
11
11
|
|
|
12
12
|
class KeyboardControllerPackage : TurboReactPackage() {
|
|
13
13
|
override fun getModule(
|
|
@@ -45,7 +45,7 @@ class KeyboardControllerPackage : TurboReactPackage() {
|
|
|
45
45
|
ReactModuleInfo(
|
|
46
46
|
StatusBarManagerCompatModuleImpl.NAME,
|
|
47
47
|
StatusBarManagerCompatModuleImpl.NAME,
|
|
48
|
-
|
|
48
|
+
true, // canOverrideExistingModule
|
|
49
49
|
false, // needsEagerInit
|
|
50
50
|
true, // hasConstants
|
|
51
51
|
false, // isCxxModule
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardBackgroundViewComponentDescriptor.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 18/05/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "RNKCKeyboardBackgroundViewShadowNode.h"
|
|
11
|
+
|
|
12
|
+
#include <react/debug/react_native_assert.h>
|
|
13
|
+
#include <react/renderer/components/reactnativekeyboardcontroller/Props.h>
|
|
14
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
15
|
+
|
|
16
|
+
namespace facebook::react {
|
|
17
|
+
class KeyboardBackgroundViewComponentDescriptor final
|
|
18
|
+
: public ConcreteComponentDescriptor<KeyboardBackgroundViewShadowNode> {
|
|
19
|
+
public:
|
|
20
|
+
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
21
|
+
void adopt(ShadowNode &shadowNode) const override {
|
|
22
|
+
react_native_assert(dynamic_cast<KeyboardBackgroundViewShadowNode *>(&shadowNode));
|
|
23
|
+
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardBackgroundViewShadowNode.cpp
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 18/05/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "RNKCKeyboardBackgroundViewShadowNode.h"
|
|
9
|
+
|
|
10
|
+
namespace facebook::react {
|
|
11
|
+
|
|
12
|
+
extern const char KeyboardBackgroundViewComponentName[] = "KeyboardBackgroundView";
|
|
13
|
+
|
|
14
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardBackgroundViewShadowNode.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 18/05/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "RNKCKeyboardBackgroundViewState.h"
|
|
11
|
+
|
|
12
|
+
#include <react/renderer/components/reactnativekeyboardcontroller/EventEmitters.h>
|
|
13
|
+
#include <react/renderer/components/reactnativekeyboardcontroller/Props.h>
|
|
14
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
15
|
+
#include <jsi/jsi.h>
|
|
16
|
+
|
|
17
|
+
namespace facebook::react {
|
|
18
|
+
|
|
19
|
+
JSI_EXPORT extern const char KeyboardBackgroundViewComponentName[];
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* `ShadowNode` for <KeyboardBackgroundView> component.
|
|
23
|
+
*/
|
|
24
|
+
using KeyboardBackgroundViewShadowNode = ConcreteViewShadowNode<
|
|
25
|
+
KeyboardBackgroundViewComponentName,
|
|
26
|
+
KeyboardBackgroundViewProps,
|
|
27
|
+
KeyboardBackgroundViewEventEmitter,
|
|
28
|
+
KeyboardBackgroundViewState>;
|
|
29
|
+
|
|
30
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardBackgroundViewState.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 18/05/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#ifdef ANDROID
|
|
11
|
+
#include <folly/dynamic.h>
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
namespace facebook::react {
|
|
15
|
+
|
|
16
|
+
class KeyboardBackgroundViewState {
|
|
17
|
+
public:
|
|
18
|
+
KeyboardBackgroundViewState() = default;
|
|
19
|
+
|
|
20
|
+
#ifdef ANDROID
|
|
21
|
+
KeyboardBackgroundViewState(KeyboardBackgroundViewState const &previousState, folly::dynamic data) {}
|
|
22
|
+
folly::dynamic getDynamic() const {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
#endif
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardExtenderComponentDescriptor.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 25/06/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "RNKCKeyboardExtenderShadowNode.h"
|
|
11
|
+
|
|
12
|
+
#include <react/debug/react_native_assert.h>
|
|
13
|
+
#include <react/renderer/components/reactnativekeyboardcontroller/Props.h>
|
|
14
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
15
|
+
|
|
16
|
+
namespace facebook::react {
|
|
17
|
+
class KeyboardExtenderComponentDescriptor final
|
|
18
|
+
: public ConcreteComponentDescriptor<KeyboardExtenderShadowNode> {
|
|
19
|
+
public:
|
|
20
|
+
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
21
|
+
void adopt(ShadowNode &shadowNode) const override {
|
|
22
|
+
react_native_assert(dynamic_cast<KeyboardExtenderShadowNode *>(&shadowNode));
|
|
23
|
+
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardExtenderShadowNode.cpp
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 25/06/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "RNKCKeyboardExtenderShadowNode.h"
|
|
9
|
+
|
|
10
|
+
namespace facebook::react {
|
|
11
|
+
|
|
12
|
+
extern const char KeyboardExtenderComponentName[] = "KeyboardExtender";
|
|
13
|
+
|
|
14
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardExtenderShadowNode.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 25/06/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "RNKCKeyboardExtenderState.h"
|
|
11
|
+
|
|
12
|
+
#include <react/renderer/components/reactnativekeyboardcontroller/EventEmitters.h>
|
|
13
|
+
#include <react/renderer/components/reactnativekeyboardcontroller/Props.h>
|
|
14
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
15
|
+
#include <jsi/jsi.h>
|
|
16
|
+
|
|
17
|
+
namespace facebook::react {
|
|
18
|
+
|
|
19
|
+
JSI_EXPORT extern const char KeyboardExtenderComponentName[];
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* `ShadowNode` for <KeyboardExtender> component.
|
|
23
|
+
*/
|
|
24
|
+
using KeyboardExtenderShadowNode = ConcreteViewShadowNode<
|
|
25
|
+
KeyboardExtenderComponentName,
|
|
26
|
+
KeyboardExtenderProps,
|
|
27
|
+
KeyboardExtenderEventEmitter,
|
|
28
|
+
KeyboardExtenderState>;
|
|
29
|
+
|
|
30
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNKCKeyboardExtenderState.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 25/06/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#ifdef ANDROID
|
|
11
|
+
#include <folly/dynamic.h>
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
namespace facebook::react {
|
|
15
|
+
|
|
16
|
+
class KeyboardExtenderState {
|
|
17
|
+
public:
|
|
18
|
+
KeyboardExtenderState() = default;
|
|
19
|
+
|
|
20
|
+
#ifdef ANDROID
|
|
21
|
+
KeyboardExtenderState(KeyboardExtenderState const &previousState, folly::dynamic data) {}
|
|
22
|
+
folly::dynamic getDynamic() const {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
#endif
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
} // namespace facebook::react
|
|
@@ -67,6 +67,15 @@ RCT_EXPORT_METHOD(setInputMode : (nonnull NSNumber *)mode)
|
|
|
67
67
|
{
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
71
|
+
- (void)preload
|
|
72
|
+
#else
|
|
73
|
+
RCT_EXPORT_METHOD(preload)
|
|
74
|
+
#endif
|
|
75
|
+
{
|
|
76
|
+
[UIResponder preloadKeyboardIfNeeded];
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
71
80
|
- (void)dismiss:(BOOL)keepFocus
|
|
72
81
|
#else
|
|
@@ -54,7 +54,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
54
54
|
// Keep track of which textField we’re observing (iOS < 13 only)
|
|
55
55
|
private weak var observedTextFieldForSelection: UITextField?
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
init(
|
|
58
58
|
onSelectionChange: @escaping (_ event: NSDictionary) -> Void,
|
|
59
59
|
onTextChange: @escaping (_ text: String?) -> Void
|
|
60
60
|
) {
|
|
@@ -64,7 +64,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
64
64
|
|
|
65
65
|
// MARK: setters/getters
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
func setTextViewDelegate(delegate: UITextViewDelegate?) {
|
|
68
68
|
// remove KVO from any old textView
|
|
69
69
|
if let oldTextField = observedTextFieldForSelection {
|
|
70
70
|
removeSelectionRangeObserver(from: oldTextField)
|
|
@@ -75,7 +75,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
75
75
|
observedTextFieldForSelection = nil
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
func setTextFieldDelegate(delegate: UITextFieldDelegate?, textField: UITextField?) {
|
|
79
79
|
// remove KVO from any old textField
|
|
80
80
|
if let oldTextField = observedTextFieldForSelection {
|
|
81
81
|
removeSelectionRangeObserver(from: oldTextField)
|
|
@@ -96,7 +96,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
func canSubstituteTextFieldDelegate(delegate: UITextFieldDelegate?) -> Bool {
|
|
100
100
|
let type = String(describing: delegate)
|
|
101
101
|
if type.range(of: "SQIPTextFieldInputModifier") != nil {
|
|
102
102
|
// SQIPTextFieldInputModifier is a private class used internally by Square.
|
|
@@ -112,7 +112,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
// Getter for the active delegate
|
|
115
|
-
|
|
115
|
+
var activeDelegate: AnyObject? {
|
|
116
116
|
return textViewDelegate ?? textFieldDelegate
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -17,7 +17,7 @@ public func buildEventParams(_ height: Double, _ duration: Int, _ tag: NSNumber)
|
|
|
17
17
|
data["timestamp"] = Date.currentTimeStamp
|
|
18
18
|
data["target"] = tag
|
|
19
19
|
data["type"] = input?.keyboardType.name ?? "default"
|
|
20
|
-
data["appearance"] = input?.
|
|
20
|
+
data["appearance"] = input?.keyboardAppearanceValue ?? "light"
|
|
21
21
|
|
|
22
22
|
return data
|
|
23
23
|
}
|
|
@@ -63,3 +63,30 @@ public extension Optional where Wrapped: UIResponder {
|
|
|
63
63
|
return -1
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
@objc
|
|
68
|
+
public extension UIResponder {
|
|
69
|
+
private static var hasPreloadedKeyboard = false
|
|
70
|
+
static var isKeyboardPreloading = false
|
|
71
|
+
|
|
72
|
+
/// Preloads the keyboard UI to reduce first-time lag when showing a keyboard.
|
|
73
|
+
/// https://stackoverflow.com/questions/9357026/super-slow-lag-delay-on-initial-keyboard-animation-of-uitextfield/20436797#20436797
|
|
74
|
+
static func preloadKeyboardIfNeeded() {
|
|
75
|
+
guard !hasPreloadedKeyboard else { return }
|
|
76
|
+
hasPreloadedKeyboard = true
|
|
77
|
+
isKeyboardPreloading = true
|
|
78
|
+
|
|
79
|
+
DispatchQueue.main.async {
|
|
80
|
+
defer { isKeyboardPreloading = false }
|
|
81
|
+
guard let window = UIApplication.shared.activeWindow else { return }
|
|
82
|
+
|
|
83
|
+
let lagFreeField = UITextField(frame: .zero)
|
|
84
|
+
lagFreeField.isHidden = true
|
|
85
|
+
window.addSubview(lagFreeField)
|
|
86
|
+
|
|
87
|
+
lagFreeField.becomeFirstResponder()
|
|
88
|
+
lagFreeField.resignFirstResponder()
|
|
89
|
+
lagFreeField.removeFromSuperview()
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
class KeyboardAreaExtender: NSObject {
|
|
9
9
|
private var currentInputAccessoryView: InvisibleInputAccessoryView?
|
|
10
10
|
|
|
11
|
-
@objc
|
|
11
|
+
@objc static let shared = KeyboardAreaExtender()
|
|
12
12
|
|
|
13
13
|
override private init() {
|
|
14
14
|
super.init()
|
|
@@ -24,11 +24,11 @@ class KeyboardAreaExtender: NSObject {
|
|
|
24
24
|
NotificationCenter.default.removeObserver(self)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
var offset: CGFloat {
|
|
28
28
|
return currentInputAccessoryView?.frame.height ?? 0
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
func hide() {
|
|
32
32
|
if isVisible {
|
|
33
33
|
NotificationCenter.default.post(
|
|
34
34
|
name: .shouldIgnoreKeyboardEvents, object: nil, userInfo: ["ignore": true]
|
|
@@ -37,11 +37,11 @@ class KeyboardAreaExtender: NSObject {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
func remove() {
|
|
41
41
|
currentInputAccessoryView = nil
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
func updateHeight(to newHeight: CGFloat, for nativeID: String) {
|
|
45
45
|
if UIResponder.current.nativeID == nativeID {
|
|
46
46
|
currentInputAccessoryView?.updateHeight(to: newHeight)
|
|
47
47
|
}
|
|
@@ -140,6 +140,11 @@ public class FocusedInputObserver: NSObject {
|
|
|
140
140
|
currentInput = currentResponder?.superview as UIView?
|
|
141
141
|
|
|
142
142
|
setupObservers()
|
|
143
|
+
// dispatch onSelectionChange on focus
|
|
144
|
+
if let textInput = responder as? UITextInput {
|
|
145
|
+
updateSelectionPosition(textInput: textInput, sendEvent: onSelectionChange)
|
|
146
|
+
}
|
|
147
|
+
|
|
143
148
|
syncUpLayout()
|
|
144
149
|
|
|
145
150
|
FocusedInputHolder.shared.set(currentResponder as? TextInput)
|
|
@@ -211,7 +216,15 @@ public class FocusedInputObserver: NSObject {
|
|
|
211
216
|
self.onLayoutChange(view: view, change: change)
|
|
212
217
|
}
|
|
213
218
|
|
|
214
|
-
|
|
219
|
+
// Substitute a delegate in the next frame.
|
|
220
|
+
// This is only applicable if the autoFocus prop is true.
|
|
221
|
+
// Other libraries (e.g., decorator views) might mount *after* the
|
|
222
|
+
// TextInput and inject their own delegates at that point.
|
|
223
|
+
// If we substitute our delegate too early (e.g., during autoFocus), and later restore it when the keyboard hides,
|
|
224
|
+
// we may accidentally overwrite a delegate injected by another library — breaking its logic.
|
|
225
|
+
DispatchQueue.main.async {
|
|
226
|
+
self.substituteDelegate(self.currentResponder)
|
|
227
|
+
}
|
|
215
228
|
}
|
|
216
229
|
}
|
|
217
230
|
|
|
@@ -240,10 +253,6 @@ public class FocusedInputObserver: NSObject {
|
|
|
240
253
|
textView.setForceDelegate(delegate)
|
|
241
254
|
}
|
|
242
255
|
}
|
|
243
|
-
// dispatch onSelectionChange on focus
|
|
244
|
-
if let textInput = input as? UITextInput {
|
|
245
|
-
updateSelectionPosition(textInput: textInput, sendEvent: onSelectionChange)
|
|
246
|
-
}
|
|
247
256
|
}
|
|
248
257
|
|
|
249
258
|
private func substituteDelegateBack(_ input: UIResponder?) {
|
|
@@ -120,6 +120,9 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
private func keyboardDidMoveInteractively(changeValue: CGPoint) {
|
|
123
|
+
if UIResponder.isKeyboardPreloading {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
123
126
|
// if we are currently animating keyboard -> we need to ignore values from KVO
|
|
124
127
|
if !displayLink.isPaused {
|
|
125
128
|
return
|
|
@@ -165,7 +168,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
@objc func keyboardWillAppear(_ notification: Notification) {
|
|
168
|
-
guard !KeyboardEventsIgnorer.shared.shouldIgnore else { return }
|
|
171
|
+
guard !KeyboardEventsIgnorer.shared.shouldIgnore, !UIResponder.isKeyboardPreloading else { return }
|
|
169
172
|
|
|
170
173
|
let (duration, frame) = notification.keyboardMetaData()
|
|
171
174
|
if let keyboardFrame = frame {
|
|
@@ -185,6 +188,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
185
188
|
}
|
|
186
189
|
|
|
187
190
|
@objc func keyboardWillDisappear(_ notification: Notification) {
|
|
191
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
188
192
|
let (duration, _) = notification.keyboardMetaData()
|
|
189
193
|
tag = UIResponder.current.reactViewTag
|
|
190
194
|
self.duration = duration
|
|
@@ -199,6 +203,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
@objc func keyboardDidAppear(_ notification: Notification) {
|
|
206
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
202
207
|
let timestamp = Date.currentTimeStamp
|
|
203
208
|
let (duration, frame) = notification.keyboardMetaData()
|
|
204
209
|
if let keyboardFrame = frame {
|
|
@@ -229,6 +234,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
229
234
|
}
|
|
230
235
|
|
|
231
236
|
@objc func keyboardDidDisappear(_ notification: Notification) {
|
|
237
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
232
238
|
let (duration, _) = notification.keyboardMetaData()
|
|
233
239
|
tag = UIResponder.current.reactViewTag
|
|
234
240
|
|
|
@@ -30,3 +30,25 @@ extension UITextView: TextInput {
|
|
|
30
30
|
becomeFirstResponder()
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
extension TextInput {
|
|
35
|
+
var keyboardAppearanceValue: String {
|
|
36
|
+
switch keyboardAppearance {
|
|
37
|
+
case .dark:
|
|
38
|
+
return "dark"
|
|
39
|
+
case .light:
|
|
40
|
+
return "light"
|
|
41
|
+
case .default:
|
|
42
|
+
switch traitCollection.userInterfaceStyle {
|
|
43
|
+
case .dark:
|
|
44
|
+
return "dark"
|
|
45
|
+
case .light, .unspecified:
|
|
46
|
+
return "light"
|
|
47
|
+
@unknown default:
|
|
48
|
+
return "light"
|
|
49
|
+
}
|
|
50
|
+
@unknown default:
|
|
51
|
+
return "light"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -72,6 +72,9 @@ extension UIResponder {
|
|
|
72
72
|
|
|
73
73
|
// Postpone execution of the original resignFirstResponder
|
|
74
74
|
DispatchQueue.main.asyncAfter(deadline: .now() + UIUtils.nextFrame) {
|
|
75
|
+
NotificationCenter.default.post(
|
|
76
|
+
name: .shouldIgnoreKeyboardEvents, object: nil, userInfo: ["ignore": false]
|
|
77
|
+
)
|
|
75
78
|
(self as? TextInput)?.inputAccessoryView = nil
|
|
76
79
|
KeyboardAreaExtender.shared.remove()
|
|
77
80
|
_ = self.callOriginalResignFirstResponder(originalResignSelector)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KeyboardBackgroundViewManager.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 21/04/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
9
|
+
#import <React/RCTViewComponentView.h>
|
|
10
|
+
#else
|
|
11
|
+
#import <React/RCTBridge.h>
|
|
12
|
+
#endif
|
|
13
|
+
#import <React/RCTViewManager.h>
|
|
14
|
+
#import <UIKit/UIKit.h>
|
|
15
|
+
|
|
16
|
+
@interface KeyboardBackgroundViewManager : RCTViewManager
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@interface KeyboardBackgroundView :
|
|
20
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
21
|
+
RCTViewComponentView
|
|
22
|
+
#else
|
|
23
|
+
UIView
|
|
24
|
+
|
|
25
|
+
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
|
26
|
+
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
@end
|