react-native-keyboard-controller 1.17.4 → 1.18.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/README.md +4 -1
- package/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +6 -5
- 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/KeyboardControllerViewManager.kt +3 -5
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardGestureAreaViewManager.kt +3 -5
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/OverKeyboardViewManager.kt +3 -5
- 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 -6
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardGestureAreaViewManagerImpl.kt +1 -5
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/OverKeyboardViewManagerImpl.kt +1 -5
- 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/KeyboardControllerViewManager.kt +2 -5
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardGestureAreaViewManager.kt +2 -5
- package/android/src/paper/java/com/reactnativekeyboardcontroller/OverKeyboardViewManager.kt +2 -5
- package/android/src/paper/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt +3 -1
- package/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +5 -5
- 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/String.swift +12 -0
- 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 +24 -9
- package/ios/protocols/TextInput.swift +22 -0
- package/ios/swizzling/UIResponderSwizzle.swift +3 -0
- package/ios/traversal/KeyboardView.swift +6 -3
- package/ios/views/KeyboardBackgroundViewManager.h +29 -0
- package/ios/views/KeyboardBackgroundViewManager.mm +168 -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/constants.js +17 -0
- package/lib/commonjs/components/KeyboardToolbar/constants.js.map +1 -0
- package/lib/commonjs/components/KeyboardToolbar/index.js +25 -22
- 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/constants.js +11 -0
- package/lib/module/components/KeyboardToolbar/constants.js.map +1 -0
- package/lib/module/components/KeyboardToolbar/index.js +17 -14
- 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/components/KeyboardToolbar/constants.d.ts +10 -0
- 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/constants.ts +15 -0
- package/src/components/KeyboardToolbar/index.tsx +45 -17
- 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
|
@@ -32,7 +32,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
32
32
|
|
|
33
33
|
private var _windowsCount: Int = 0
|
|
34
34
|
private var prevKeyboardPosition = 0.0
|
|
35
|
-
private var displayLink: CADisplayLink
|
|
35
|
+
private var displayLink: CADisplayLink!
|
|
36
36
|
private var interactiveKeyboardObserver: NSKeyValueObservation?
|
|
37
37
|
private var isMounted = false
|
|
38
38
|
// state variables
|
|
@@ -57,6 +57,18 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
57
57
|
self.onNotify = onNotify
|
|
58
58
|
self.onRequestAnimation = onRequestAnimation
|
|
59
59
|
self.onCancelAnimation = onCancelAnimation
|
|
60
|
+
|
|
61
|
+
super.init()
|
|
62
|
+
|
|
63
|
+
displayLink = CADisplayLink(target: self, selector: #selector(updateKeyboardFrame))
|
|
64
|
+
displayLink.preferredFramesPerSecond = 120 // will fallback to 60 fps for devices without Pro Motion display
|
|
65
|
+
displayLink.add(to: .main, forMode: .common)
|
|
66
|
+
displayLink.isPaused = true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
deinit {
|
|
70
|
+
displayLink.invalidate()
|
|
71
|
+
displayLink = nil
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
@objc public func mount() {
|
|
@@ -108,8 +120,11 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
108
120
|
}
|
|
109
121
|
|
|
110
122
|
private func keyboardDidMoveInteractively(changeValue: CGPoint) {
|
|
123
|
+
if UIResponder.isKeyboardPreloading {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
111
126
|
// if we are currently animating keyboard -> we need to ignore values from KVO
|
|
112
|
-
if displayLink
|
|
127
|
+
if !displayLink.isPaused {
|
|
113
128
|
return
|
|
114
129
|
}
|
|
115
130
|
// if keyboard height is not equal to its bounds - we can ignore
|
|
@@ -153,7 +168,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
153
168
|
}
|
|
154
169
|
|
|
155
170
|
@objc func keyboardWillAppear(_ notification: Notification) {
|
|
156
|
-
guard !KeyboardEventsIgnorer.shared.shouldIgnore else { return }
|
|
171
|
+
guard !KeyboardEventsIgnorer.shared.shouldIgnore, !UIResponder.isKeyboardPreloading else { return }
|
|
157
172
|
|
|
158
173
|
let (duration, frame) = notification.keyboardMetaData()
|
|
159
174
|
if let keyboardFrame = frame {
|
|
@@ -173,6 +188,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
173
188
|
}
|
|
174
189
|
|
|
175
190
|
@objc func keyboardWillDisappear(_ notification: Notification) {
|
|
191
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
176
192
|
let (duration, _) = notification.keyboardMetaData()
|
|
177
193
|
tag = UIResponder.current.reactViewTag
|
|
178
194
|
self.duration = duration
|
|
@@ -187,6 +203,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
187
203
|
}
|
|
188
204
|
|
|
189
205
|
@objc func keyboardDidAppear(_ notification: Notification) {
|
|
206
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
190
207
|
let timestamp = Date.currentTimeStamp
|
|
191
208
|
let (duration, frame) = notification.keyboardMetaData()
|
|
192
209
|
if let keyboardFrame = frame {
|
|
@@ -217,6 +234,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
217
234
|
}
|
|
218
235
|
|
|
219
236
|
@objc func keyboardDidDisappear(_ notification: Notification) {
|
|
237
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
220
238
|
let (duration, _) = notification.keyboardMetaData()
|
|
221
239
|
tag = UIResponder.current.reactViewTag
|
|
222
240
|
|
|
@@ -232,18 +250,15 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
232
250
|
// sometimes `will` events can be called multiple times.
|
|
233
251
|
// To avoid double re-creation of listener we are adding this condition
|
|
234
252
|
// (if active link is present, then no need to re-setup a listener)
|
|
235
|
-
if displayLink
|
|
253
|
+
if !displayLink.isPaused {
|
|
236
254
|
return
|
|
237
255
|
}
|
|
238
256
|
|
|
239
|
-
displayLink =
|
|
240
|
-
displayLink?.preferredFramesPerSecond = 120 // will fallback to 60 fps for devices without Pro Motion display
|
|
241
|
-
displayLink?.add(to: .main, forMode: .common)
|
|
257
|
+
displayLink.isPaused = false
|
|
242
258
|
}
|
|
243
259
|
|
|
244
260
|
@objc func removeKeyboardWatcher() {
|
|
245
|
-
displayLink
|
|
246
|
-
displayLink = nil
|
|
261
|
+
displayLink.isPaused = true
|
|
247
262
|
}
|
|
248
263
|
|
|
249
264
|
func initializeAnimation(fromValue: Double, toValue: Double) {
|
|
@@ -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)
|
|
@@ -10,15 +10,18 @@ import Foundation
|
|
|
10
10
|
import UIKit
|
|
11
11
|
|
|
12
12
|
enum KeyboardView {
|
|
13
|
+
private static let windowPrefix = "<UITextEffectsWindow"
|
|
14
|
+
private static let containerPrefixes = ["<UIInputSetContainerView", "<UITrackingWindowView"]
|
|
15
|
+
private static let hostPrefixes = ["<UIInputSetHostView", "<UIKeyboardItemContainerView"]
|
|
13
16
|
// inspired by https://stackoverflow.com/questions/32598490/show-uiview-with-buttons-over-keyboard-like-in-skype-viber-messengers-swift-i
|
|
14
17
|
static func find() -> UIView? {
|
|
15
18
|
let windows = UIApplication.shared.windows
|
|
16
19
|
for window in windows {
|
|
17
|
-
if window.description.hasPrefix(
|
|
20
|
+
if window.description.hasPrefix(windowPrefix) {
|
|
18
21
|
for subview in window.subviews {
|
|
19
|
-
if subview.description.
|
|
22
|
+
if subview.description.hasAnyPrefix(containerPrefixes) {
|
|
20
23
|
for hostView in subview.subviews {
|
|
21
|
-
if hostView.description.
|
|
24
|
+
if hostView.description.hasAnyPrefix(hostPrefixes), hostView.frame.height != 0 {
|
|
22
25
|
return hostView
|
|
23
26
|
}
|
|
24
27
|
}
|
|
@@ -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
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KeyboardBackgroundViewManager.mm
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 21/04/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "KeyboardBackgroundViewManager.h"
|
|
9
|
+
|
|
10
|
+
#if __has_include("react_native_keyboard_controller-Swift.h")
|
|
11
|
+
#import "react_native_keyboard_controller-Swift.h"
|
|
12
|
+
#else
|
|
13
|
+
#import <react_native_keyboard_controller/react_native_keyboard_controller-Swift.h>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
17
|
+
#import <react/renderer/components/reactnativekeyboardcontroller/EventEmitters.h>
|
|
18
|
+
#import <react/renderer/components/reactnativekeyboardcontroller/Props.h>
|
|
19
|
+
#import <react/renderer/components/reactnativekeyboardcontroller/RCTComponentViewHelpers.h>
|
|
20
|
+
#import <react/renderer/components/reactnativekeyboardcontroller/RNKCKeyboardBackgroundViewComponentDescriptor.h>
|
|
21
|
+
|
|
22
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
#import <React/RCTView.h>
|
|
26
|
+
#import <UIKit/UIKit.h>
|
|
27
|
+
|
|
28
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
29
|
+
using namespace facebook::react;
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
typedef NS_ENUM(NSInteger, KeyboardBackdropStyle) {
|
|
33
|
+
KeyboardBackdropStyleDark = 2030,
|
|
34
|
+
KeyboardBackdropStyleLight = 3901
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
@protocol KeyboardBackdropViewProtocol <NSObject>
|
|
38
|
+
@optional
|
|
39
|
+
- (instancetype)initWithFrame:(CGRect)frame style:(long long)style;
|
|
40
|
+
- (void)transitionToStyle:(long long)style;
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
#pragma mark - Manager
|
|
44
|
+
|
|
45
|
+
@implementation KeyboardBackgroundViewManager
|
|
46
|
+
|
|
47
|
+
RCT_EXPORT_MODULE(KeyboardBackgroundViewManager)
|
|
48
|
+
|
|
49
|
+
+ (BOOL)requiresMainQueueSetup
|
|
50
|
+
{
|
|
51
|
+
return NO;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#ifndef RCT_NEW_ARCH_ENABLED
|
|
55
|
+
- (UIView *)view
|
|
56
|
+
{
|
|
57
|
+
RCTView *containerView = [[RCTView alloc] initWithFrame:CGRectZero];
|
|
58
|
+
containerView.clipsToBounds = YES;
|
|
59
|
+
|
|
60
|
+
KeyboardBackgroundView *backgroundView =
|
|
61
|
+
[[KeyboardBackgroundView alloc] initWithFrame:containerView.bounds];
|
|
62
|
+
backgroundView.autoresizingMask =
|
|
63
|
+
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
64
|
+
[containerView addSubview:backgroundView];
|
|
65
|
+
|
|
66
|
+
return containerView;
|
|
67
|
+
}
|
|
68
|
+
#endif
|
|
69
|
+
|
|
70
|
+
@end
|
|
71
|
+
|
|
72
|
+
#pragma mark - View
|
|
73
|
+
|
|
74
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
75
|
+
@interface KeyboardBackgroundView () <RCTKeyboardBackgroundViewViewProtocol>
|
|
76
|
+
#else
|
|
77
|
+
@interface KeyboardBackgroundView ()
|
|
78
|
+
#endif
|
|
79
|
+
@end
|
|
80
|
+
|
|
81
|
+
@implementation KeyboardBackgroundView {
|
|
82
|
+
UIVisualEffectView *_backdropView;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
86
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
87
|
+
{
|
|
88
|
+
return concreteComponentDescriptorProvider<KeyboardBackgroundViewComponentDescriptor>();
|
|
89
|
+
}
|
|
90
|
+
#endif
|
|
91
|
+
|
|
92
|
+
// Needed because of this: https://github.com/facebook/react-native/pull/37274
|
|
93
|
+
+ (void)load
|
|
94
|
+
{
|
|
95
|
+
[super load];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
99
|
+
{
|
|
100
|
+
self = [super initWithFrame:frame];
|
|
101
|
+
if (self) {
|
|
102
|
+
[self setupBackdropView];
|
|
103
|
+
}
|
|
104
|
+
self.clipsToBounds = YES;
|
|
105
|
+
return self;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
- (void)setupBackdropView
|
|
109
|
+
{
|
|
110
|
+
Class BackdropClass = NSClassFromString(@"UIKBBackdropView");
|
|
111
|
+
if (BackdropClass) {
|
|
112
|
+
long long style = (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark)
|
|
113
|
+
? KeyboardBackdropStyleDark
|
|
114
|
+
: KeyboardBackdropStyleLight;
|
|
115
|
+
|
|
116
|
+
id<KeyboardBackdropViewProtocol> backdrop =
|
|
117
|
+
(id<KeyboardBackdropViewProtocol>)[BackdropClass alloc];
|
|
118
|
+
backdrop = [backdrop initWithFrame:self.bounds style:style];
|
|
119
|
+
|
|
120
|
+
if ([backdrop isKindOfClass:[UIVisualEffectView class]]) {
|
|
121
|
+
_backdropView = (UIVisualEffectView *)backdrop;
|
|
122
|
+
_backdropView.layer.masksToBounds = YES;
|
|
123
|
+
_backdropView.autoresizingMask =
|
|
124
|
+
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
125
|
+
_backdropView.frame = self.bounds;
|
|
126
|
+
[self addSubview:_backdropView];
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
NSLog(@"KeyboardBackdropView class not found");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// MARK: child management
|
|
134
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
135
|
+
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
136
|
+
index:(NSInteger)index
|
|
137
|
+
{
|
|
138
|
+
// preserve slot 0 for blur layer
|
|
139
|
+
[super mountChildComponentView:childComponentView index:index + 1];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
143
|
+
index:(NSInteger)index
|
|
144
|
+
{
|
|
145
|
+
// preserve slot 0 for blur layer
|
|
146
|
+
[super unmountChildComponentView:childComponentView index:index + 1];
|
|
147
|
+
}
|
|
148
|
+
#endif
|
|
149
|
+
|
|
150
|
+
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
|
|
151
|
+
{
|
|
152
|
+
[super traitCollectionDidChange:previousTraitCollection];
|
|
153
|
+
|
|
154
|
+
if (@available(iOS 12.0, *)) {
|
|
155
|
+
if ([previousTraitCollection
|
|
156
|
+
hasDifferentColorAppearanceComparedToTraitCollection:self.traitCollection]) {
|
|
157
|
+
long long style = (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark)
|
|
158
|
+
? KeyboardBackdropStyleDark
|
|
159
|
+
: KeyboardBackdropStyleLight;
|
|
160
|
+
|
|
161
|
+
if ([_backdropView respondsToSelector:@selector(transitionToStyle:)]) {
|
|
162
|
+
[(id<KeyboardBackdropViewProtocol>)_backdropView transitionToStyle:style];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KeyboardExtenderContainerView.swift
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 11/07/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import UIKit
|
|
9
|
+
|
|
10
|
+
@objc
|
|
11
|
+
public class KeyboardExtenderContainerView: UIView {
|
|
12
|
+
@objc public static func create(frame: CGRect, contentView: UIView) -> UIView {
|
|
13
|
+
if #available(iOS 26.0, *) {
|
|
14
|
+
if let glassEffectClass = NSClassFromString("UIGlassEffect") as? UIVisualEffect.Type {
|
|
15
|
+
let paddingHorizontal = 20.0
|
|
16
|
+
let paddingBottom = 10.0
|
|
17
|
+
let isDark = FocusedInputHolder.shared.get()?.keyboardAppearanceValue == "dark"
|
|
18
|
+
|
|
19
|
+
let glassEffect = glassEffectClass.init()
|
|
20
|
+
let color = isDark ? UIColor.black.withAlphaComponent(0.3) : UIColor.gray.withAlphaComponent(0.3)
|
|
21
|
+
glassEffect.setValue(color, forKey: "tintColor")
|
|
22
|
+
glassEffect.setValue(true, forKey: "interactive")
|
|
23
|
+
|
|
24
|
+
// wrapper container will be full frame
|
|
25
|
+
let wrapperView = UIView(frame: frame)
|
|
26
|
+
wrapperView.backgroundColor = .clear
|
|
27
|
+
|
|
28
|
+
let innerWidth = frame.width - paddingHorizontal * 2
|
|
29
|
+
let innerHeight = frame.height
|
|
30
|
+
|
|
31
|
+
let visualEffectView = UIVisualEffectView(effect: glassEffect)
|
|
32
|
+
visualEffectView.overrideUserInterfaceStyle = isDark ? .dark : .light
|
|
33
|
+
|
|
34
|
+
visualEffectView.frame = CGRect(
|
|
35
|
+
x: paddingHorizontal,
|
|
36
|
+
y: -paddingBottom,
|
|
37
|
+
width: innerWidth,
|
|
38
|
+
height: innerHeight
|
|
39
|
+
)
|
|
40
|
+
contentView.frame = CGRect(
|
|
41
|
+
x: -paddingHorizontal,
|
|
42
|
+
y: 0,
|
|
43
|
+
width: innerWidth,
|
|
44
|
+
height: innerHeight
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
visualEffectView.contentView.addSubview(contentView)
|
|
48
|
+
wrapperView.addSubview(visualEffectView)
|
|
49
|
+
|
|
50
|
+
return wrapperView
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let inputView = UIInputView(frame: frame, inputViewStyle: .keyboard)
|
|
55
|
+
contentView.frame = inputView.bounds
|
|
56
|
+
inputView.addSubview(contentView)
|
|
57
|
+
return inputView
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KeyboardExtenderManager.h
|
|
3
|
+
// KeyboardController
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 13.04.25.
|
|
6
|
+
// Copyright © 2025 Facebook. All rights reserved.
|
|
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 KeyboardExtenderManager : RCTViewManager
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@interface KeyboardExtender :
|
|
20
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
21
|
+
RCTViewComponentView
|
|
22
|
+
#else
|
|
23
|
+
UIView
|
|
24
|
+
|
|
25
|
+
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
|
26
|
+
|
|
27
|
+
#endif
|
|
28
|
+
@property (nonatomic, assign) BOOL enabled;
|
|
29
|
+
@end
|