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.
Files changed (214) hide show
  1. package/README.md +1 -0
  2. package/android/src/base/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +1 -0
  3. package/android/src/fabric/java/com/reactnativekeyboardcontroller/ClippingScrollViewDecoratorViewManager.kt +14 -0
  4. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +8 -0
  5. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardToolbarGroupViewManager.kt +23 -0
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ReactContext.kt +12 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/FocusedInputObserver.kt +2 -1
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt +5 -1
  9. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardToolbarGroupViewManagerImpl.kt +13 -0
  10. package/android/src/main/java/com/reactnativekeyboardcontroller/modal/ModalAttachedWatcher.kt +4 -6
  11. package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +26 -0
  12. package/android/src/main/java/com/reactnativekeyboardcontroller/traversal/ViewHierarchyNavigator.kt +31 -4
  13. package/android/src/main/java/com/reactnativekeyboardcontroller/views/ClippingScrollViewDecoratorView.kt +33 -1
  14. package/android/src/main/java/com/reactnativekeyboardcontroller/views/KeyboardToolbarGroupReactViewGroup.kt +13 -0
  15. package/android/src/main/jni/RNKC.h +2 -0
  16. package/android/src/paper/java/com/reactnativekeyboardcontroller/ClippingScrollViewDecoratorViewManager.kt +16 -0
  17. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +9 -0
  18. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardToolbarGroupViewManager.kt +15 -0
  19. package/android/src/turbo/java/com/reactnativekeyboardcontroller/KeyboardControllerPackage.kt +2 -0
  20. package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewComponentDescriptor.h +27 -0
  21. package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewShadowNode.cpp +14 -0
  22. package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewShadowNode.h +30 -0
  23. package/common/cpp/react/renderer/components/RNKC/RNKCClippingScrollViewDecoratorViewState.h +28 -0
  24. package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewComponentDescriptor.h +20 -0
  25. package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewShadowNode.cpp +7 -0
  26. package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewShadowNode.h +23 -0
  27. package/common/cpp/react/renderer/components/RNKC/RNKCKeyboardToolbarGroupViewState.h +21 -0
  28. package/ios/KeyboardControllerModule.mm +36 -0
  29. package/ios/animations/KeyboardAnimation.swift +2 -2
  30. package/ios/animations/SpringAnimation.swift +1 -1
  31. package/ios/animations/TimingAnimation.swift +1 -3
  32. package/ios/delegates/KCTextInputCompositeDelegate.swift +2 -2
  33. package/ios/extensions/CGFloat.swift +1 -3
  34. package/ios/extensions/UIApplication.swift +1 -1
  35. package/ios/interactive/KeyboardAreaExtender.swift +2 -1
  36. package/ios/observers/FocusedInputObserver.swift +6 -3
  37. package/ios/observers/movement/KeyboardTrackingView.swift +4 -1
  38. package/ios/observers/movement/observer/KeyboardMovementObserver+Interactive.swift +2 -0
  39. package/ios/observers/movement/observer/KeyboardMovementObserver+Listeners.swift +30 -7
  40. package/ios/observers/movement/observer/KeyboardMovementObserver.swift +2 -48
  41. package/ios/protocols/TextInput.swift +1 -1
  42. package/ios/swizzling/UIResponderSwizzle.swift +2 -4
  43. package/ios/traversal/FocusedInputHolder.swift +3 -3
  44. package/ios/traversal/KeyboardView.swift +1 -1
  45. package/ios/traversal/ViewHierarchyNavigator.swift +51 -5
  46. package/ios/views/ClippingScrollViewDecoratorViewManager.h +26 -0
  47. package/ios/views/ClippingScrollViewDecoratorViewManager.mm +231 -0
  48. package/ios/views/KeyboardControllerViewManager.swift +5 -5
  49. package/ios/views/KeyboardToolbarGroupViewManager.h +28 -0
  50. package/ios/views/KeyboardToolbarGroupViewManager.mm +88 -0
  51. package/jest/index.js +12 -4
  52. package/lib/commonjs/bindings.js +18 -2
  53. package/lib/commonjs/bindings.js.map +1 -1
  54. package/lib/commonjs/bindings.native.js +3 -4
  55. package/lib/commonjs/bindings.native.js.map +1 -1
  56. package/lib/commonjs/components/KeyboardAvoidingView/index.js +30 -4
  57. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
  58. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +55 -14
  59. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  60. package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/hooks.js.map +1 -1
  61. package/lib/commonjs/components/KeyboardChatScrollView/index.js +111 -0
  62. package/lib/commonjs/components/KeyboardChatScrollView/index.js.map +1 -0
  63. package/lib/commonjs/components/KeyboardChatScrollView/types.js.map +1 -0
  64. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js +221 -0
  65. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js.map +1 -0
  66. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +149 -0
  67. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -0
  68. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js +240 -0
  69. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -0
  70. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js +6 -0
  71. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -0
  72. package/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js +72 -0
  73. package/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js.map +1 -0
  74. package/lib/commonjs/components/KeyboardStickyView/index.js +3 -1
  75. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  76. package/lib/commonjs/components/KeyboardToolbar/index.js +1 -0
  77. package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
  78. package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js +36 -15
  79. package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js.map +1 -1
  80. package/lib/commonjs/components/hooks/useScrollState.js +20 -1
  81. package/lib/commonjs/components/hooks/useScrollState.js.map +1 -1
  82. package/lib/commonjs/components/index.js +7 -7
  83. package/lib/commonjs/components/index.js.map +1 -1
  84. package/lib/commonjs/index.js +7 -7
  85. package/lib/commonjs/index.js.map +1 -1
  86. package/lib/commonjs/specs/ClippingScrollViewDecoratorViewNativeComponent.js +1 -2
  87. package/lib/commonjs/specs/ClippingScrollViewDecoratorViewNativeComponent.js.map +1 -1
  88. package/lib/commonjs/specs/KeyboardToolbarGroupViewNativeComponent.js +12 -0
  89. package/lib/commonjs/specs/KeyboardToolbarGroupViewNativeComponent.js.map +1 -0
  90. package/lib/commonjs/specs/NativeKeyboardController.js.map +1 -1
  91. package/lib/commonjs/types/module.js.map +1 -1
  92. package/lib/commonjs/types/views.js.map +1 -1
  93. package/lib/module/bindings.js +17 -1
  94. package/lib/module/bindings.js.map +1 -1
  95. package/lib/module/bindings.native.js +2 -3
  96. package/lib/module/bindings.native.js.map +1 -1
  97. package/lib/module/components/KeyboardAvoidingView/index.js +29 -4
  98. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
  99. package/lib/module/components/KeyboardAwareScrollView/index.js +55 -14
  100. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  101. package/lib/module/components/{ChatKit → KeyboardChatScrollView}/hooks.js.map +1 -1
  102. package/lib/module/components/KeyboardChatScrollView/index.js +104 -0
  103. package/lib/module/components/KeyboardChatScrollView/index.js.map +1 -0
  104. package/lib/module/components/KeyboardChatScrollView/types.js.map +1 -0
  105. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js +207 -0
  106. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js.map +1 -0
  107. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +143 -0
  108. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -0
  109. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js +234 -0
  110. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -0
  111. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js +2 -0
  112. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -0
  113. package/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js +67 -0
  114. package/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js.map +1 -0
  115. package/lib/module/components/KeyboardStickyView/index.js +3 -1
  116. package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
  117. package/lib/module/components/KeyboardToolbar/index.js +2 -1
  118. package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
  119. package/lib/module/components/ScrollViewWithBottomPadding/index.js +38 -17
  120. package/lib/module/components/ScrollViewWithBottomPadding/index.js.map +1 -1
  121. package/lib/module/components/hooks/useScrollState.js +21 -2
  122. package/lib/module/components/hooks/useScrollState.js.map +1 -1
  123. package/lib/module/components/index.js +1 -1
  124. package/lib/module/components/index.js.map +1 -1
  125. package/lib/module/index.js +1 -1
  126. package/lib/module/index.js.map +1 -1
  127. package/lib/module/specs/ClippingScrollViewDecoratorViewNativeComponent.js +1 -2
  128. package/lib/module/specs/ClippingScrollViewDecoratorViewNativeComponent.js.map +1 -1
  129. package/lib/module/specs/KeyboardToolbarGroupViewNativeComponent.js +5 -0
  130. package/lib/module/specs/KeyboardToolbarGroupViewNativeComponent.js.map +1 -0
  131. package/lib/module/specs/NativeKeyboardController.js.map +1 -1
  132. package/lib/module/types/module.js.map +1 -1
  133. package/lib/module/types/views.js.map +1 -1
  134. package/lib/typescript/bindings.d.ts +12 -2
  135. package/lib/typescript/bindings.native.d.ts +2 -1
  136. package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +44 -13
  137. package/lib/typescript/components/KeyboardChatScrollView/hooks.d.ts +2 -0
  138. package/lib/typescript/components/KeyboardChatScrollView/index.d.ts +15 -0
  139. package/lib/typescript/components/{ChatKit → KeyboardChatScrollView}/types.d.ts +46 -6
  140. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/helpers.d.ts +132 -0
  141. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/index.d.ts +18 -0
  142. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/index.ios.d.ts +21 -0
  143. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts +37 -0
  144. package/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts +43 -0
  145. package/lib/typescript/components/KeyboardToolbar/index.d.ts +2 -0
  146. package/lib/typescript/components/ScrollViewWithBottomPadding/index.d.ts +5 -4
  147. package/lib/typescript/components/hooks/useScrollState.d.ts +3 -0
  148. package/lib/typescript/components/index.d.ts +2 -2
  149. package/lib/typescript/index.d.ts +2 -2
  150. package/lib/typescript/specs/ClippingScrollViewDecoratorViewNativeComponent.d.ts +2 -0
  151. package/lib/typescript/specs/KeyboardToolbarGroupViewNativeComponent.d.ts +6 -0
  152. package/lib/typescript/specs/NativeKeyboardController.d.ts +1 -0
  153. package/lib/typescript/types/module.d.ts +7 -0
  154. package/lib/typescript/types/views.d.ts +4 -0
  155. package/package.json +6 -2
  156. package/react-native.config.js +2 -0
  157. package/src/bindings.native.ts +4 -4
  158. package/src/bindings.ts +15 -1
  159. package/src/components/KeyboardAvoidingView/index.tsx +56 -29
  160. package/src/components/KeyboardAwareScrollView/index.tsx +68 -13
  161. package/src/components/KeyboardChatScrollView/hooks.ts +2 -0
  162. package/src/components/KeyboardChatScrollView/index.tsx +150 -0
  163. package/src/components/{ChatKit → KeyboardChatScrollView}/types.ts +46 -6
  164. package/src/components/KeyboardChatScrollView/useChatKeyboard/helpers.ts +268 -0
  165. package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts +260 -0
  166. package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ts +376 -0
  167. package/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts +39 -0
  168. package/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts +123 -0
  169. package/src/components/KeyboardStickyView/index.tsx +4 -3
  170. package/src/components/KeyboardToolbar/index.tsx +6 -1
  171. package/src/components/ScrollViewWithBottomPadding/index.tsx +53 -29
  172. package/src/components/hooks/useScrollState.ts +24 -2
  173. package/src/components/index.ts +2 -2
  174. package/src/index.ts +2 -2
  175. package/src/specs/ClippingScrollViewDecoratorViewNativeComponent.ts +2 -1
  176. package/src/specs/KeyboardToolbarGroupViewNativeComponent.ts +10 -0
  177. package/src/specs/NativeKeyboardController.ts +1 -0
  178. package/src/types/module.ts +9 -0
  179. package/src/types/views.ts +4 -0
  180. package/android/.settings/org.eclipse.buildship.core.prefs +0 -2
  181. package/ios/KeyboardController.xcodeproj/xcuserdata/kirylziusko.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  182. package/ios/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  183. package/ios/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  184. package/ios/Tests/Tests.xcodeproj/project.xcworkspace/xcuserdata/kirylziusko.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  185. package/ios/Tests/Tests.xcodeproj/xcuserdata/kirylziusko.xcuserdatad/xcschemes/xcschememanagement.plist +0 -32
  186. package/lib/commonjs/components/ChatKit/TODO.md +0 -20
  187. package/lib/commonjs/components/ChatKit/index.js +0 -55
  188. package/lib/commonjs/components/ChatKit/index.js.map +0 -1
  189. package/lib/commonjs/components/ChatKit/types.js.map +0 -1
  190. package/lib/commonjs/components/ChatKit/useChatKeyboard/helpers.js +0 -101
  191. package/lib/commonjs/components/ChatKit/useChatKeyboard/helpers.js.map +0 -1
  192. package/lib/commonjs/components/ChatKit/useChatKeyboard/index.js +0 -147
  193. package/lib/commonjs/components/ChatKit/useChatKeyboard/index.js.map +0 -1
  194. package/lib/module/components/ChatKit/TODO.md +0 -20
  195. package/lib/module/components/ChatKit/index.js +0 -48
  196. package/lib/module/components/ChatKit/index.js.map +0 -1
  197. package/lib/module/components/ChatKit/types.js.map +0 -1
  198. package/lib/module/components/ChatKit/useChatKeyboard/helpers.js +0 -92
  199. package/lib/module/components/ChatKit/useChatKeyboard/helpers.js.map +0 -1
  200. package/lib/module/components/ChatKit/useChatKeyboard/index.js +0 -141
  201. package/lib/module/components/ChatKit/useChatKeyboard/index.js.map +0 -1
  202. package/lib/typescript/components/ChatKit/hooks.d.ts +0 -2
  203. package/lib/typescript/components/ChatKit/index.d.ts +0 -14
  204. package/lib/typescript/components/ChatKit/useChatKeyboard/helpers.d.ts +0 -57
  205. package/lib/typescript/components/ChatKit/useChatKeyboard/index.d.ts +0 -36
  206. package/src/components/ChatKit/TODO.md +0 -20
  207. package/src/components/ChatKit/hooks.ts +0 -2
  208. package/src/components/ChatKit/index.tsx +0 -63
  209. package/src/components/ChatKit/useChatKeyboard/helpers.ts +0 -118
  210. package/src/components/ChatKit/useChatKeyboard/index.ts +0 -228
  211. /package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/hooks.js +0 -0
  212. /package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/types.js +0 -0
  213. /package/lib/module/components/{ChatKit → KeyboardChatScrollView}/hooks.js +0 -0
  214. /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
- // internal state
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
- // public getters
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
- // public functions
63
+ /// public functions
64
64
  override func valueAt(time: Double) -> Double {
65
65
  let t = time * speed
66
66
 
@@ -56,9 +56,7 @@ public final class TimingAnimation: KeyboardAnimation {
56
56
  let x = bezierX(t: t)
57
57
 
58
58
  let duration = animation?.duration ?? 0.0
59
- let time = x * duration / speed
60
-
61
- return time
59
+ return x * duration / speed
62
60
  }
63
61
 
64
62
  // private functions
@@ -51,7 +51,7 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
51
51
  weak var textViewDelegate: UITextViewDelegate?
52
52
  weak var textFieldDelegate: UITextFieldDelegate?
53
53
 
54
- // Keep track of which textField we’re observing (iOS < 13 only)
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
- // Getter for the active delegate
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
- let interpolatedValue = outputMin + (outputMax - outputMin) * normalizedValue
20
-
21
- return interpolatedValue
19
+ return outputMin + (outputMax - outputMin) * normalizedValue
22
20
  }
23
21
  }
@@ -9,7 +9,7 @@ import Foundation
9
9
  import UIKit
10
10
 
11
11
  public extension UIApplication {
12
- var activeWindow: UIWindow? {
12
+ @objc var activeWindow: UIWindow? {
13
13
  if #available(iOS 13.0, *) {
14
14
  for scene in connectedScenes {
15
15
  if scene.activationState == .foregroundActive,
@@ -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
- // state variables
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
- updateSelectionPosition(textInput: textInput, sendEvent: onSelectionChange)
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 allInputFields = ViewHierarchyNavigator.getAllInputFields()
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? { KeyboardViewLocator.shared.resolve() }
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
@@ -49,6 +49,8 @@ extension KeyboardMovementObserver {
49
49
 
50
50
  prevKeyboardPosition = position
51
51
 
52
+ keyboardDidTask?.cancel()
53
+
52
54
  onEvent(
53
55
  "onKeyboardMoveInteractive",
54
56
  position as NSNumber,
@@ -7,7 +7,7 @@
7
7
 
8
8
  extension KeyboardMovementObserver {
9
9
  @objc func keyboardWillAppear(_ notification: Notification) {
10
- guard !KeyboardEventsIgnorer.shared.shouldIgnore, !UIResponder.isKeyboardPreloading else { return }
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
- guard !KeyboardEventsIgnorer.shared.shouldIgnore else {
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
- // custom methods/properties
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
- let result = castOriginalResignFirstResponder(self, selector)
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
- let result = castOriginalBecomeFirstResponder(self, selector)
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
- // Using TextInput protocol as the type for currentFocusedInput
14
+ /// Using TextInput protocol as the type for currentFocusedInput
15
15
  private weak var currentFocusedInput: TextInput?
16
16
 
17
- // Sets the currentFocusedInput to the passed instance conforming to TextInput or clears it if nil is passed
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
- // Requests focus for the currentFocusedInput if it's set
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
- // inspired by https://stackoverflow.com/questions/32598490/show-uiview-with-buttons-over-keyboard-like-in-skype-viber-messengers-swift-i
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
- guard let rootView = UIApplication.topViewController()?.view else {
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
- // Helper function to recursively search for TextInput views
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
- findTextInputs(in: rootView)
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
- // Function to check if the view is a valid text field or text view
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