react-native-keyboard-controller 1.21.0-beta.2 → 1.21.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 +1 -0
- package/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +1 -0
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/ClippingScrollViewDecoratorViewManager.kt +14 -0
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +8 -0
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardToolbarGroupViewManager.kt +23 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ReactContext.kt +12 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +2 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt +5 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardToolbarGroupViewManagerImpl.kt +13 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/modal/ModalAttachedWatcher.kt +4 -6
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +26 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/traversal/ViewHierarchyNavigator.kt +31 -4
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/ClippingScrollViewDecoratorView.kt +33 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/KeyboardToolbarGroupReactViewGroup.kt +13 -0
- package/android/src/main/jni/RNKC.h +2 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/ClippingScrollViewDecoratorViewManager.kt +16 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +9 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardToolbarGroupViewManager.kt +15 -0
- package/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +2 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewComponentDescriptor.h +27 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewShadowNode.cpp +14 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewShadowNode.h +30 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewState.h +28 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewComponentDescriptor.h +20 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewShadowNode.cpp +7 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewShadowNode.h +23 -0
- package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewState.h +21 -0
- package/ios/KeyboardControllerModule.mm +36 -0
- package/ios/animations/KeyboardAnimation.swift +2 -2
- package/ios/animations/SpringAnimation.swift +1 -1
- package/ios/animations/TimingAnimation.swift +1 -3
- package/ios/delegates/KCTextInputCompositeDelegate.swift +2 -2
- package/ios/extensions/CGFloat.swift +1 -3
- package/ios/extensions/UIApplication.swift +1 -1
- package/ios/interactive/KeyboardAreaExtender.swift +2 -1
- package/ios/observers/FocusedInputObserver.swift +6 -3
- package/ios/observers/movement/KeyboardTrackingView.swift +4 -1
- package/ios/observers/movement/observer/KeyboardMovementObserver+Interactive.swift +2 -0
- package/ios/observers/movement/observer/KeyboardMovementObserver+Listeners.swift +30 -7
- package/ios/observers/movement/observer/KeyboardMovementObserver.swift +2 -48
- package/ios/protocols/TextInput.swift +1 -1
- package/ios/swizzling/UIResponderSwizzle.swift +2 -4
- package/ios/traversal/FocusedInputHolder.swift +3 -3
- package/ios/traversal/KeyboardView.swift +1 -1
- package/ios/traversal/ViewHierarchyNavigator.swift +51 -5
- package/ios/views/ClippingScrollViewDecoratorViewManager.h +26 -0
- package/ios/views/ClippingScrollViewDecoratorViewManager.mm +231 -0
- package/ios/views/KeyboardControllerViewManager.swift +5 -5
- package/ios/views/KeyboardToolbarGroupViewManager.h +28 -0
- package/ios/views/KeyboardToolbarGroupViewManager.mm +88 -0
- package/jest/index.js +12 -4
- package/lib/commonjs/bindings.js +18 -2
- package/lib/commonjs/bindings.js.map +1 -1
- package/lib/commonjs/bindings.native.js +3 -4
- package/lib/commonjs/bindings.native.js.map +1 -1
- package/lib/commonjs/components/KeyboardAvoidingView/index.js +30 -4
- package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +55 -14
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/hooks.js.map +1 -1
- package/lib/commonjs/components/KeyboardChatScrollView/index.js +111 -0
- package/lib/commonjs/components/KeyboardChatScrollView/index.js.map +1 -0
- package/lib/commonjs/components/KeyboardChatScrollView/types.js.map +1 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js +221 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js.map +1 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +149 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js +240 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js +6 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js +72 -0
- package/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js.map +1 -0
- package/lib/commonjs/components/KeyboardStickyView/index.js +3 -1
- package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/index.js +1 -0
- package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js +36 -15
- package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js.map +1 -1
- package/lib/commonjs/components/hooks/useScrollState.js +20 -1
- package/lib/commonjs/components/hooks/useScrollState.js.map +1 -1
- package/lib/commonjs/components/index.js +7 -7
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/index.js +7 -7
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/ClippingScrollViewDecoratorViewNativeComponent.js +1 -2
- package/lib/commonjs/specs/ClippingScrollViewDecoratorViewNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/KeyboardToolbarGroupViewNativeComponent.js +12 -0
- package/lib/commonjs/specs/KeyboardToolbarGroupViewNativeComponent.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/module/bindings.js +17 -1
- package/lib/module/bindings.js.map +1 -1
- package/lib/module/bindings.native.js +2 -3
- package/lib/module/bindings.native.js.map +1 -1
- package/lib/module/components/KeyboardAvoidingView/index.js +29 -4
- package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/module/components/KeyboardAwareScrollView/index.js +55 -14
- package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/module/components/{ChatKit → KeyboardChatScrollView}/hooks.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/index.js +104 -0
- package/lib/module/components/KeyboardChatScrollView/index.js.map +1 -0
- package/lib/module/components/KeyboardChatScrollView/types.js.map +1 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js +207 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js.map +1 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +143 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js +234 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js +2 -0
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -0
- package/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js +67 -0
- package/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js.map +1 -0
- package/lib/module/components/KeyboardStickyView/index.js +3 -1
- package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/index.js +2 -1
- package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/module/components/ScrollViewWithBottomPadding/index.js +38 -17
- package/lib/module/components/ScrollViewWithBottomPadding/index.js.map +1 -1
- package/lib/module/components/hooks/useScrollState.js +21 -2
- package/lib/module/components/hooks/useScrollState.js.map +1 -1
- package/lib/module/components/index.js +1 -1
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/ClippingScrollViewDecoratorViewNativeComponent.js +1 -2
- package/lib/module/specs/ClippingScrollViewDecoratorViewNativeComponent.js.map +1 -1
- package/lib/module/specs/KeyboardToolbarGroupViewNativeComponent.js +5 -0
- package/lib/module/specs/KeyboardToolbarGroupViewNativeComponent.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/typescript/bindings.d.ts +12 -2
- package/lib/typescript/bindings.native.d.ts +2 -1
- package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +44 -13
- package/lib/typescript/components/KeyboardChatScrollView/hooks.d.ts +2 -0
- package/lib/typescript/components/KeyboardChatScrollView/index.d.ts +15 -0
- package/lib/typescript/components/{ChatKit → KeyboardChatScrollView}/types.d.ts +46 -6
- package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/helpers.d.ts +132 -0
- package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/index.d.ts +18 -0
- package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/index.ios.d.ts +21 -0
- package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts +37 -0
- package/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts +43 -0
- package/lib/typescript/components/KeyboardToolbar/index.d.ts +2 -0
- package/lib/typescript/components/ScrollViewWithBottomPadding/index.d.ts +5 -4
- package/lib/typescript/components/hooks/useScrollState.d.ts +3 -0
- package/lib/typescript/components/index.d.ts +2 -2
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/specs/ClippingScrollViewDecoratorViewNativeComponent.d.ts +2 -0
- package/lib/typescript/specs/KeyboardToolbarGroupViewNativeComponent.d.ts +6 -0
- package/lib/typescript/specs/NativeKeyboardController.d.ts +1 -0
- package/lib/typescript/types/module.d.ts +7 -0
- package/lib/typescript/types/views.d.ts +4 -0
- package/package.json +6 -2
- package/react-native.config.js +2 -0
- package/src/bindings.native.ts +4 -4
- package/src/bindings.ts +15 -1
- package/src/components/KeyboardAvoidingView/index.tsx +56 -29
- package/src/components/KeyboardAwareScrollView/index.tsx +68 -13
- package/src/components/KeyboardChatScrollView/hooks.ts +2 -0
- package/src/components/KeyboardChatScrollView/index.tsx +150 -0
- package/src/components/{ChatKit → KeyboardChatScrollView}/types.ts +46 -6
- package/src/components/KeyboardChatScrollView/useChatKeyboard/helpers.ts +268 -0
- package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts +260 -0
- package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ts +376 -0
- package/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts +39 -0
- package/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts +123 -0
- package/src/components/KeyboardStickyView/index.tsx +4 -3
- package/src/components/KeyboardToolbar/index.tsx +6 -1
- package/src/components/ScrollViewWithBottomPadding/index.tsx +53 -29
- package/src/components/hooks/useScrollState.ts +24 -2
- package/src/components/index.ts +2 -2
- package/src/index.ts +2 -2
- package/src/specs/ClippingScrollViewDecoratorViewNativeComponent.ts +2 -1
- package/src/specs/KeyboardToolbarGroupViewNativeComponent.ts +10 -0
- package/src/specs/NativeKeyboardController.ts +1 -0
- package/src/types/module.ts +9 -0
- package/src/types/views.ts +4 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +0 -2
- package/ios/KeyboardController.xcodeproj/xcuserdata/kirylziusko.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/ios/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/ios/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/Tests/Tests.xcodeproj/project.xcworkspace/xcuserdata/kirylziusko.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/Tests/Tests.xcodeproj/xcuserdata/kirylziusko.xcuserdatad/xcschemes/xcschememanagement.plist +0 -32
- package/lib/commonjs/components/ChatKit/TODO.md +0 -20
- package/lib/commonjs/components/ChatKit/index.js +0 -55
- package/lib/commonjs/components/ChatKit/index.js.map +0 -1
- package/lib/commonjs/components/ChatKit/types.js.map +0 -1
- package/lib/commonjs/components/ChatKit/useChatKeyboard/helpers.js +0 -101
- package/lib/commonjs/components/ChatKit/useChatKeyboard/helpers.js.map +0 -1
- package/lib/commonjs/components/ChatKit/useChatKeyboard/index.js +0 -147
- package/lib/commonjs/components/ChatKit/useChatKeyboard/index.js.map +0 -1
- package/lib/module/components/ChatKit/TODO.md +0 -20
- package/lib/module/components/ChatKit/index.js +0 -48
- package/lib/module/components/ChatKit/index.js.map +0 -1
- package/lib/module/components/ChatKit/types.js.map +0 -1
- package/lib/module/components/ChatKit/useChatKeyboard/helpers.js +0 -92
- package/lib/module/components/ChatKit/useChatKeyboard/helpers.js.map +0 -1
- package/lib/module/components/ChatKit/useChatKeyboard/index.js +0 -141
- package/lib/module/components/ChatKit/useChatKeyboard/index.js.map +0 -1
- package/lib/typescript/components/ChatKit/hooks.d.ts +0 -2
- package/lib/typescript/components/ChatKit/index.d.ts +0 -14
- package/lib/typescript/components/ChatKit/useChatKeyboard/helpers.d.ts +0 -57
- package/lib/typescript/components/ChatKit/useChatKeyboard/index.d.ts +0 -36
- package/src/components/ChatKit/TODO.md +0 -20
- package/src/components/ChatKit/hooks.ts +0 -2
- package/src/components/ChatKit/index.tsx +0 -63
- package/src/components/ChatKit/useChatKeyboard/helpers.ts +0 -118
- package/src/components/ChatKit/useChatKeyboard/index.ts +0 -228
- /package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/hooks.js +0 -0
- /package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/types.js +0 -0
- /package/lib/module/components/{ChatKit → KeyboardChatScrollView}/hooks.js +0 -0
- /package/lib/module/components/{ChatKit → KeyboardChatScrollView}/types.js +0 -0
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
#endif
|
|
24
24
|
|
|
25
25
|
#import <React/RCTEventDispatcherProtocol.h>
|
|
26
|
+
#ifndef RCT_NEW_ARCH_ENABLED
|
|
27
|
+
#import <React/RCTUIManager.h>
|
|
28
|
+
#endif
|
|
26
29
|
|
|
27
30
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
28
31
|
@interface KeyboardController () <NativeKeyboardControllerSpec>
|
|
@@ -95,6 +98,39 @@ RCT_EXPORT_METHOD(setFocusTo : (nonnull NSString *)direction)
|
|
|
95
98
|
[ViewHierarchyNavigator setFocusToDirection:direction];
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
102
|
+
- (void)viewPositionInWindow:(double)viewTag
|
|
103
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
104
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
105
|
+
#else
|
|
106
|
+
RCT_EXPORT_METHOD(viewPositionInWindow
|
|
107
|
+
: (nonnull NSNumber *)viewTag resolve
|
|
108
|
+
: (RCTPromiseResolveBlock)resolve reject
|
|
109
|
+
: (RCTPromiseRejectBlock)reject)
|
|
110
|
+
#endif
|
|
111
|
+
{
|
|
112
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
113
|
+
UIView *view = nil;
|
|
114
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
115
|
+
NSInteger tag = (NSInteger)viewTag;
|
|
116
|
+
view = [UIApplication.sharedApplication.activeWindow viewWithTag:tag];
|
|
117
|
+
#else
|
|
118
|
+
view = [self.bridge.uiManager viewForReactTag:viewTag];
|
|
119
|
+
#endif
|
|
120
|
+
if (!view || !view.superview) {
|
|
121
|
+
reject(@"E_VIEW_NOT_FOUND", @"Could not find view for tag", nil);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
CGRect frame = [view.superview convertRect:view.frame toView:nil];
|
|
125
|
+
resolve(@{
|
|
126
|
+
@"x" : @(frame.origin.x),
|
|
127
|
+
@"y" : @(frame.origin.y),
|
|
128
|
+
@"width" : @(frame.size.width),
|
|
129
|
+
@"height" : @(frame.size.height),
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
98
134
|
+ (KeyboardController *)shared
|
|
99
135
|
{
|
|
100
136
|
return shared;
|
|
@@ -26,7 +26,7 @@ public class KeyboardAnimation: KeyboardAnimationProtocol {
|
|
|
26
26
|
let duration: Double
|
|
27
27
|
let speed: Double
|
|
28
28
|
let timestamp: CFTimeInterval
|
|
29
|
-
|
|
29
|
+
/// internal state
|
|
30
30
|
var lastValue: Double
|
|
31
31
|
|
|
32
32
|
init(fromValue: Double, toValue: Double, animation: CAMediaTiming, duration: Double) {
|
|
@@ -39,7 +39,7 @@ public class KeyboardAnimation: KeyboardAnimationProtocol {
|
|
|
39
39
|
timestamp = CACurrentMediaTime()
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
/// public getters
|
|
43
43
|
var startTime: CFTimeInterval {
|
|
44
44
|
// when concurrent animation happens, then `.beginTime` remains the same
|
|
45
45
|
return max(animation?.beginTime ?? timestamp, timestamp)
|
|
@@ -60,7 +60,7 @@ public final class SpringAnimation: KeyboardAnimation {
|
|
|
60
60
|
super.init(fromValue: fromValue, toValue: toValue, animation: animation, duration: animation.settlingDuration)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
/// public functions
|
|
64
64
|
override func valueAt(time: Double) -> Double {
|
|
65
65
|
let t = time * speed
|
|
66
66
|
|
|
@@ -51,7 +51,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
51
51
|
weak var textViewDelegate: UITextViewDelegate?
|
|
52
52
|
weak var textFieldDelegate: UITextFieldDelegate?
|
|
53
53
|
|
|
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(
|
|
@@ -111,7 +111,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
|
|
|
111
111
|
return true
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
/// Getter for the active delegate
|
|
115
115
|
var activeDelegate: AnyObject? {
|
|
116
116
|
return textViewDelegate ?? textFieldDelegate
|
|
117
117
|
}
|
|
@@ -16,8 +16,6 @@ public extension CGFloat {
|
|
|
16
16
|
let outputMax = outputRange.max() ?? 1
|
|
17
17
|
|
|
18
18
|
let normalizedValue = (currentValue - inputMin) / (inputMax - inputMin)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return interpolatedValue
|
|
19
|
+
return outputMin + (outputMax - outputMin) * normalizedValue
|
|
22
20
|
}
|
|
23
21
|
}
|
|
@@ -55,7 +55,8 @@ class KeyboardAreaExtender: NSObject {
|
|
|
55
55
|
let responder = UIResponder.current
|
|
56
56
|
if let activeTextInput = responder as? TextInput,
|
|
57
57
|
let offset = KeyboardOffsetProvider.shared.getOffset(
|
|
58
|
-
forTextInputNativeID: responder.nativeID
|
|
58
|
+
forTextInputNativeID: responder.nativeID
|
|
59
|
+
),
|
|
59
60
|
responder?.inputAccessoryView == nil
|
|
60
61
|
{
|
|
61
62
|
currentInputAccessoryView = InvisibleInputAccessoryView(height: CGFloat(truncating: offset))
|
|
@@ -32,7 +32,7 @@ public class FocusedInputObserver: NSObject {
|
|
|
32
32
|
var onFocusDidSet: (NSDictionary) -> Void
|
|
33
33
|
/// delegates
|
|
34
34
|
var delegate: KCTextInputCompositeDelegate
|
|
35
|
-
|
|
35
|
+
/// state variables
|
|
36
36
|
private var isMounted = false
|
|
37
37
|
// input tracking
|
|
38
38
|
private var currentInput: UIView?
|
|
@@ -142,14 +142,17 @@ public class FocusedInputObserver: NSObject {
|
|
|
142
142
|
setupObservers()
|
|
143
143
|
// dispatch onSelectionChange on focus
|
|
144
144
|
if let textInput = responder as? UITextInput {
|
|
145
|
-
|
|
145
|
+
DispatchQueue.main.async {
|
|
146
|
+
updateSelectionPosition(textInput: textInput, sendEvent: self.onSelectionChange)
|
|
147
|
+
}
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
syncUpLayout()
|
|
149
151
|
|
|
150
152
|
FocusedInputHolder.shared.set(currentResponder as? TextInput)
|
|
151
153
|
|
|
152
|
-
let
|
|
154
|
+
let groupAncestor = ViewHierarchyNavigator.findGroupAncestor(currentResponder as? UIView)
|
|
155
|
+
let allInputFields = ViewHierarchyNavigator.getAllInputFields(root: groupAncestor)
|
|
153
156
|
let currentIndex = allInputFields.firstIndex(where: { $0 == currentResponder }) ?? -1
|
|
154
157
|
|
|
155
158
|
onFocusDidSet([
|
|
@@ -12,7 +12,10 @@ import UIKit
|
|
|
12
12
|
* and uses `keyboardLayoutGuide` on iOS 26+.
|
|
13
13
|
*/
|
|
14
14
|
public final class KeyboardTrackingView: UIView {
|
|
15
|
-
private var keyboardView: UIView? {
|
|
15
|
+
private var keyboardView: UIView? {
|
|
16
|
+
KeyboardViewLocator.shared.resolve()
|
|
17
|
+
}
|
|
18
|
+
|
|
16
19
|
private var keyboardHeight = 0.0
|
|
17
20
|
private weak var currentAttachedView: UIView?
|
|
18
21
|
private var isAttaching = false
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
extension KeyboardMovementObserver {
|
|
9
9
|
@objc func keyboardWillAppear(_ notification: Notification) {
|
|
10
|
-
guard !
|
|
10
|
+
guard !UIResponder.isKeyboardPreloading else { return }
|
|
11
11
|
|
|
12
12
|
let (duration, frame) = notification.keyboardMetaData()
|
|
13
13
|
if let keyboardFrame = frame {
|
|
@@ -15,6 +15,12 @@ extension KeyboardMovementObserver {
|
|
|
15
15
|
let keyboardHeight = keyboardFrame.cgRectValue.size.height
|
|
16
16
|
self.keyboardHeight = keyboardHeight
|
|
17
17
|
self.notification = notification
|
|
18
|
+
|
|
19
|
+
guard !KeyboardEventsIgnorer.shared.shouldIgnore else {
|
|
20
|
+
KeyboardEventsIgnorer.shared.shouldIgnoreKeyboardEvents = false
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
self.duration = duration
|
|
19
25
|
|
|
20
26
|
onRequestAnimation()
|
|
@@ -23,6 +29,7 @@ extension KeyboardMovementObserver {
|
|
|
23
29
|
|
|
24
30
|
setupKeyboardWatcher()
|
|
25
31
|
initializeAnimation(fromValue: prevKeyboardPosition, toValue: self.keyboardHeight)
|
|
32
|
+
scheduleDidEvent(height: self.keyboardHeight, duration: animation?.duration ?? CGFloat(duration) / 1000)
|
|
26
33
|
}
|
|
27
34
|
}
|
|
28
35
|
|
|
@@ -44,6 +51,7 @@ extension KeyboardMovementObserver {
|
|
|
44
51
|
setupKeyboardWatcher()
|
|
45
52
|
removeKVObserver()
|
|
46
53
|
initializeAnimation(fromValue: prevKeyboardPosition, toValue: 0)
|
|
54
|
+
scheduleDidEvent(height: 0, duration: animation?.duration ?? CGFloat(duration) / 1000)
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
@objc func keyboardDidAppear(_ notification: Notification) {
|
|
@@ -55,12 +63,7 @@ extension KeyboardMovementObserver {
|
|
|
55
63
|
tag = UIResponder.current.reactViewTag
|
|
56
64
|
self.keyboardHeight = keyboardHeight
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
KeyboardEventsIgnorer.shared.shouldIgnoreKeyboardEvents = false
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
let height = self.keyboardHeight - KeyboardAreaExtender.shared.offset
|
|
66
|
+
let height = self.keyboardHeight
|
|
64
67
|
// always limit progress to the maximum possible value
|
|
65
68
|
let progress = min(height / self.keyboardHeight, 1.0)
|
|
66
69
|
|
|
@@ -90,4 +93,24 @@ extension KeyboardMovementObserver {
|
|
|
90
93
|
removeKeyboardWatcher()
|
|
91
94
|
animation = nil
|
|
92
95
|
}
|
|
96
|
+
|
|
97
|
+
@objc func scheduleDidEvent(height: CGFloat, duration: CGFloat) {
|
|
98
|
+
keyboardDidTask?.cancel()
|
|
99
|
+
|
|
100
|
+
guard let notification = notification else {
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let task = DispatchWorkItem { [weak self] in
|
|
105
|
+
guard let self = self else { return }
|
|
106
|
+
if height > 0 {
|
|
107
|
+
self.keyboardDidAppear(notification)
|
|
108
|
+
} else {
|
|
109
|
+
self.keyboardDidDisappear(notification)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
keyboardDidTask = task
|
|
114
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: task)
|
|
115
|
+
}
|
|
93
116
|
}
|
|
@@ -19,30 +19,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
19
19
|
var onCancelAnimation: () -> Void
|
|
20
20
|
// progress tracker
|
|
21
21
|
@objc public var keyboardTrackingView = KeyboardTrackingView()
|
|
22
|
-
var animation: KeyboardAnimation?
|
|
23
|
-
didSet {
|
|
24
|
-
keyboardDidTask?.cancel()
|
|
25
|
-
|
|
26
|
-
guard let animation = animation, let notification = notification else {
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let toValue = animation.toValue
|
|
31
|
-
let duration = animation.duration
|
|
32
|
-
|
|
33
|
-
let task = DispatchWorkItem { [weak self] in
|
|
34
|
-
guard let self = self else { return }
|
|
35
|
-
if toValue > 0 {
|
|
36
|
-
self.keyboardDidAppear(notification)
|
|
37
|
-
} else {
|
|
38
|
-
self.keyboardDidDisappear(notification)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
keyboardDidTask = task
|
|
43
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: task)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
22
|
+
var animation: KeyboardAnimation?
|
|
46
23
|
|
|
47
24
|
var prevKeyboardPosition = 0.0
|
|
48
25
|
var displayLink: CADisplayLink!
|
|
@@ -55,30 +32,7 @@ public class KeyboardMovementObserver: NSObject {
|
|
|
55
32
|
set { _keyboardHeight = newValue }
|
|
56
33
|
}
|
|
57
34
|
|
|
58
|
-
var duration = 0
|
|
59
|
-
didSet {
|
|
60
|
-
keyboardDidTask?.cancel()
|
|
61
|
-
|
|
62
|
-
guard let notification = notification,
|
|
63
|
-
let height = notification.keyboardMetaData().1?.cgRectValue.size.height, duration == 0
|
|
64
|
-
else {
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let task = DispatchWorkItem { [weak self] in
|
|
69
|
-
guard let self = self else { return }
|
|
70
|
-
if height > 0 {
|
|
71
|
-
self.keyboardDidAppear(notification)
|
|
72
|
-
} else {
|
|
73
|
-
self.keyboardDidDisappear(notification)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
keyboardDidTask = task
|
|
78
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + UIUtils.nextFrame, execute: task)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
35
|
+
var duration = 0
|
|
82
36
|
var tag: NSNumber = -1
|
|
83
37
|
// manual did events
|
|
84
38
|
var notification: Notification?
|
|
@@ -15,7 +15,7 @@ public protocol TextInput: UIView {
|
|
|
15
15
|
var inputView: UIView? { get set }
|
|
16
16
|
var keyboardType: UIKeyboardType { get }
|
|
17
17
|
var keyboardAppearance: UIKeyboardAppearance { get }
|
|
18
|
-
|
|
18
|
+
/// custom methods/properties
|
|
19
19
|
func focus()
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -94,8 +94,7 @@ extension UIResponder {
|
|
|
94
94
|
let castOriginalResignFirstResponder = unsafeBitCast(
|
|
95
95
|
originalResignFirstResponder, to: Function.self
|
|
96
96
|
)
|
|
97
|
-
|
|
98
|
-
return result
|
|
97
|
+
return castOriginalResignFirstResponder(self, selector)
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
private func callOriginalBecomeFirstResponder(_ selector: Selector) -> Bool {
|
|
@@ -104,7 +103,6 @@ extension UIResponder {
|
|
|
104
103
|
let castOriginalBecomeFirstResponder = unsafeBitCast(
|
|
105
104
|
originalBecomeFirstResponder, to: Function.self
|
|
106
105
|
)
|
|
107
|
-
|
|
108
|
-
return result
|
|
106
|
+
return castOriginalBecomeFirstResponder(self, selector)
|
|
109
107
|
}
|
|
110
108
|
}
|
|
@@ -11,10 +11,10 @@ import Foundation
|
|
|
11
11
|
class FocusedInputHolder {
|
|
12
12
|
static let shared = FocusedInputHolder()
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/// Using TextInput protocol as the type for currentFocusedInput
|
|
15
15
|
private weak var currentFocusedInput: TextInput?
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
/// Sets the currentFocusedInput to the passed instance conforming to TextInput or clears it if nil is passed
|
|
18
18
|
func set(_ input: TextInput?) {
|
|
19
19
|
currentFocusedInput = input
|
|
20
20
|
}
|
|
@@ -23,7 +23,7 @@ class FocusedInputHolder {
|
|
|
23
23
|
return currentFocusedInput
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
/// Requests focus for the currentFocusedInput if it's set
|
|
27
27
|
func focus() {
|
|
28
28
|
currentFocusedInput?.focus()
|
|
29
29
|
}
|
|
@@ -13,7 +13,7 @@ enum KeyboardView {
|
|
|
13
13
|
private static let windowPrefix = "<UITextEffectsWindow"
|
|
14
14
|
private static let containerPrefixes = ["<UIInputSetContainerView", "<UITrackingWindowView"]
|
|
15
15
|
private static let hostPrefixes = ["<UIInputSetHostView", "<UIKeyboardItemContainerView"]
|
|
16
|
-
|
|
16
|
+
/// inspired by https://stackoverflow.com/questions/32598490/show-uiview-with-buttons-over-keyboard-like-in-skype-viber-messengers-swift-i
|
|
17
17
|
static func find() -> UIView? {
|
|
18
18
|
let windows = UIApplication.shared.windows
|
|
19
19
|
for window in windows {
|
|
@@ -11,6 +11,8 @@ import UIKit
|
|
|
11
11
|
|
|
12
12
|
@objc(ViewHierarchyNavigator)
|
|
13
13
|
public class ViewHierarchyNavigator: NSObject {
|
|
14
|
+
private static let groupViewTypeName = "KeyboardToolbarGroupView"
|
|
15
|
+
|
|
14
16
|
@objc public static func setFocusTo(direction: String) {
|
|
15
17
|
DispatchQueue.main.async {
|
|
16
18
|
if direction == "current" {
|
|
@@ -30,30 +32,67 @@ public class ViewHierarchyNavigator: NSObject {
|
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
public static func getAllInputFields() -> [TextInput] {
|
|
35
|
+
return getAllInputFields(root: nil)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public static func getAllInputFields(root: UIView?) -> [TextInput] {
|
|
33
39
|
var textInputs = [TextInput]()
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
let rootView: UIView?
|
|
42
|
+
if let root = root {
|
|
43
|
+
rootView = root
|
|
44
|
+
} else {
|
|
45
|
+
rootView = UIApplication.topViewController()?.view
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
guard let rootView = rootView else {
|
|
36
49
|
return []
|
|
37
50
|
}
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
let isGroupRoot = isGroupView(rootView)
|
|
53
|
+
|
|
54
|
+
/// Helper function to recursively search for TextInput views
|
|
40
55
|
func findTextInputs(in view: UIView?) {
|
|
41
56
|
guard let view = view else { return }
|
|
42
57
|
|
|
43
58
|
if let textInput = isValidTextInput(view) {
|
|
44
59
|
textInputs.append(textInput)
|
|
45
|
-
} else {
|
|
60
|
+
} else if !isGroupView(view) {
|
|
46
61
|
for subview in view.subviews {
|
|
47
62
|
findTextInputs(in: subview)
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
}
|
|
51
66
|
|
|
52
|
-
|
|
67
|
+
if isGroupRoot {
|
|
68
|
+
// When root is a group, search its children directly
|
|
69
|
+
for subview in rootView.subviews {
|
|
70
|
+
findTextInputs(in: subview)
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
findTextInputs(in: rootView)
|
|
74
|
+
}
|
|
53
75
|
|
|
54
76
|
return textInputs
|
|
55
77
|
}
|
|
56
78
|
|
|
79
|
+
/// Finds the closest KeyboardToolbarGroupView ancestor of the given view.
|
|
80
|
+
/// Returns nil if the view is not inside any group.
|
|
81
|
+
public static func findGroupAncestor(_ view: UIView?) -> UIView? {
|
|
82
|
+
var current = view?.superview
|
|
83
|
+
while let parent = current {
|
|
84
|
+
if isGroupView(parent) {
|
|
85
|
+
return parent
|
|
86
|
+
}
|
|
87
|
+
current = parent.superview
|
|
88
|
+
}
|
|
89
|
+
return nil
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private static func isGroupView(_ view: UIView) -> Bool {
|
|
93
|
+
return String(describing: type(of: view)) == groupViewTypeName
|
|
94
|
+
}
|
|
95
|
+
|
|
57
96
|
private static func findTextInputInDirection(currentFocus: UIView, direction: String) -> TextInput? {
|
|
58
97
|
// Find the parent view group
|
|
59
98
|
guard let parentViewGroup = currentFocus.superview else {
|
|
@@ -81,6 +120,11 @@ public class ViewHierarchyNavigator: NSObject {
|
|
|
81
120
|
}
|
|
82
121
|
}
|
|
83
122
|
|
|
123
|
+
// Don't navigate outside the group boundary
|
|
124
|
+
if isGroupView(parentViewGroup) {
|
|
125
|
+
return nil
|
|
126
|
+
}
|
|
127
|
+
|
|
84
128
|
// If no next or previous sibling was found in the parent, recurse to the parent's parent
|
|
85
129
|
return findTextInputInDirection(currentFocus: parentViewGroup, direction: direction)
|
|
86
130
|
}
|
|
@@ -91,6 +135,8 @@ public class ViewHierarchyNavigator: NSObject {
|
|
|
91
135
|
return validTextInput
|
|
92
136
|
}
|
|
93
137
|
|
|
138
|
+
guard !isGroupView(view) else { return nil }
|
|
139
|
+
|
|
94
140
|
// Determine the iteration order based on the direction
|
|
95
141
|
let subviews = direction == "next" ? view.subviews : view.subviews.reversed()
|
|
96
142
|
|
|
@@ -104,7 +150,7 @@ public class ViewHierarchyNavigator: NSObject {
|
|
|
104
150
|
return nil // No valid UITextField or UITextView found
|
|
105
151
|
}
|
|
106
152
|
|
|
107
|
-
|
|
153
|
+
/// Function to check if the view is a valid text field or text view
|
|
108
154
|
private static func isValidTextInput(_ view: UIView) -> TextInput? {
|
|
109
155
|
if let textField = view as? UITextField, textField.isEnabled {
|
|
110
156
|
return textField
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ClippingScrollViewDecoratorViewManager.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 03/03/2025.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
9
|
+
#import <React/RCTViewComponentView.h>
|
|
10
|
+
#else
|
|
11
|
+
#import <React/RCTView.h>
|
|
12
|
+
#endif
|
|
13
|
+
#import <React/RCTViewManager.h>
|
|
14
|
+
#import <UIKit/UIKit.h>
|
|
15
|
+
|
|
16
|
+
@interface ClippingScrollViewDecoratorViewManager : RCTViewManager
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@interface ClippingScrollViewDecoratorView :
|
|
20
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
21
|
+
RCTViewComponentView
|
|
22
|
+
#else
|
|
23
|
+
UIView
|
|
24
|
+
#endif
|
|
25
|
+
@property (nonatomic, assign) BOOL applyWorkaroundForContentInsetHitTestBug;
|
|
26
|
+
@end
|