react-native-keyboard-controller 1.17.2 → 1.17.4

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 (36) hide show
  1. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +15 -4
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +20 -5
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +4 -0
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt +13 -4
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +14 -2
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +12 -6
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/views/overlay/OverKeyboardViewGroup.kt +11 -0
  8. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +13 -3
  9. package/ios/KeyboardControllerModule.mm +2 -0
  10. package/ios/swizzling/UIResponderSwizzle.swift +57 -10
  11. package/ios/views/KeyboardControllerView.mm +18 -0
  12. package/ios/views/KeyboardControllerViewManager.swift +19 -0
  13. package/ios/views/KeyboardGestureAreaManager.mm +1 -0
  14. package/lib/commonjs/components/KeyboardAvoidingView/index.js +3 -2
  15. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
  16. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +3 -0
  17. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  18. package/lib/commonjs/hooks/useWindowDimensions/index.js +29 -6
  19. package/lib/commonjs/hooks/useWindowDimensions/index.js.map +1 -1
  20. package/lib/module/components/KeyboardAvoidingView/index.js +3 -2
  21. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
  22. package/lib/module/components/KeyboardAwareScrollView/index.js +5 -2
  23. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  24. package/lib/module/hooks/useWindowDimensions/index.js +28 -1
  25. package/lib/module/hooks/useWindowDimensions/index.js.map +1 -1
  26. package/lib/typescript/hooks/useWindowDimensions/index.d.ts +2 -1
  27. package/package.json +1 -1
  28. package/src/components/KeyboardAvoidingView/index.tsx +3 -2
  29. package/src/components/KeyboardAwareScrollView/index.tsx +6 -1
  30. package/src/hooks/useWindowDimensions/index.ts +41 -1
  31. package/lib/commonjs/hooks/useWindowDimensions/index.android.js +0 -34
  32. package/lib/commonjs/hooks/useWindowDimensions/index.android.js.map +0 -1
  33. package/lib/module/hooks/useWindowDimensions/index.android.js +0 -27
  34. package/lib/module/hooks/useWindowDimensions/index.android.js.map +0 -1
  35. package/lib/typescript/hooks/useWindowDimensions/index.android.d.ts +0 -2
  36. package/src/hooks/useWindowDimensions/index.android.ts +0 -38
@@ -18,17 +18,21 @@ class KeyboardControllerViewManager(
18
18
  private val manager = KeyboardControllerViewManagerImpl(mReactContext)
19
19
  private val mDelegate = KeyboardControllerViewManagerDelegate(this)
20
20
 
21
- override fun getDelegate(): ViewManagerDelegate<ReactViewGroup> = mDelegate
22
-
23
- override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
24
-
21
+ // region Lifecycle
25
22
  override fun createViewInstance(context: ThemedReactContext): ReactViewGroup = manager.createViewInstance(context)
26
23
 
24
+ override fun invalidate() {
25
+ super.invalidate()
26
+ manager.invalidate()
27
+ }
28
+
27
29
  override fun onAfterUpdateTransaction(view: ReactViewGroup) {
28
30
  super.onAfterUpdateTransaction(view)
29
31
  manager.setEdgeToEdge(view as EdgeToEdgeReactViewGroup)
30
32
  }
33
+ // endregion
31
34
 
35
+ // region Props setters
32
36
  @ReactProp(name = "statusBarTranslucent")
33
37
  override fun setStatusBarTranslucent(
34
38
  view: ReactViewGroup,
@@ -52,7 +56,14 @@ class KeyboardControllerViewManager(
52
56
  view: ReactViewGroup,
53
57
  value: Boolean,
54
58
  ) = manager.setEnabled(view as EdgeToEdgeReactViewGroup, value)
59
+ // endregion
55
60
 
61
+ // region Getters
56
62
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
57
63
  manager.getExportedCustomDirectEventTypeConstants()
64
+
65
+ override fun getDelegate(): ViewManagerDelegate<ReactViewGroup> = mDelegate
66
+
67
+ override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
68
+ // endregion
58
69
  }
@@ -2,6 +2,7 @@ package com.reactnativekeyboardcontroller.extensions
2
2
 
3
3
  import android.content.Context
4
4
  import android.os.Build
5
+ import com.facebook.react.bridge.Arguments
5
6
  import com.facebook.react.bridge.ReactContext
6
7
  import com.facebook.react.bridge.WritableMap
7
8
  import com.facebook.react.modules.core.DeviceEventManagerModule
@@ -9,13 +10,8 @@ import com.facebook.react.uimanager.ThemedReactContext
9
10
  import com.facebook.react.uimanager.UIManagerHelper
10
11
  import com.facebook.react.uimanager.events.Event
11
12
  import com.facebook.react.uimanager.events.EventDispatcher
12
- import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener
13
13
  import com.reactnativekeyboardcontroller.log.Logger
14
14
 
15
- fun ThemedReactContext.setupWindowDimensionsListener() {
16
- WindowDimensionListener(this)
17
- }
18
-
19
15
  fun ThemedReactContext?.dispatchEvent(
20
16
  viewId: Int,
21
17
  event: Event<*>,
@@ -37,6 +33,25 @@ fun ThemedReactContext?.emitEvent(
37
33
  Logger.i("ThemedReactContext", event)
38
34
  }
39
35
 
36
+ fun ThemedReactContext?.keepShadowNodesInSync(viewId: Int) {
37
+ // originally by viewId we should lookup all connected nodes
38
+ // and send them to JS
39
+ // but at the moment JS side broadcasts events to all ViewType
40
+ // instances, so we can send even empty array
41
+ val tags = intArrayOf(viewId)
42
+
43
+ val tagsArray = Arguments.createArray()
44
+ for (tag in tags) {
45
+ tagsArray.pushInt(tag)
46
+ }
47
+
48
+ // emit the event to JS to re-sync the trees
49
+ val onAnimationEndedData = Arguments.createMap()
50
+ onAnimationEndedData.putArray("tags", tagsArray)
51
+
52
+ this?.reactApplicationContext?.emitDeviceEvent("onUserDrivenAnimationEnded", onAnimationEndedData)
53
+ }
54
+
40
55
  val ThemedReactContext?.appearance: String
41
56
  get() =
42
57
  when {
@@ -20,6 +20,7 @@ import com.reactnativekeyboardcontroller.extensions.dispatchEvent
20
20
  import com.reactnativekeyboardcontroller.extensions.dp
21
21
  import com.reactnativekeyboardcontroller.extensions.emitEvent
22
22
  import com.reactnativekeyboardcontroller.extensions.isKeyboardAnimation
23
+ import com.reactnativekeyboardcontroller.extensions.keepShadowNodesInSync
23
24
  import com.reactnativekeyboardcontroller.extensions.keyboardType
24
25
  import com.reactnativekeyboardcontroller.interactive.InteractiveKeyboardProvider
25
26
  import com.reactnativekeyboardcontroller.log.Logger
@@ -327,6 +328,8 @@ class KeyboardAnimationCallback(
327
328
 
328
329
  // reset to initial state
329
330
  duration = 0
331
+
332
+ context.keepShadowNodesInSync(eventPropagationView.id)
330
333
  }
331
334
 
332
335
  if (isKeyboardInteractive) {
@@ -401,6 +404,7 @@ class KeyboardAnimationCallback(
401
404
  )
402
405
  }
403
406
  context.emitEvent("KeyboardController::keyboardDidShow", getEventParams(keyboardHeight))
407
+ context.keepShadowNodesInSync(eventPropagationView.id)
404
408
 
405
409
  this.persistentKeyboardHeight = keyboardHeight
406
410
  }
@@ -1,6 +1,7 @@
1
1
  package com.reactnativekeyboardcontroller.listeners
2
2
 
3
3
  import android.view.ViewGroup
4
+ import android.view.ViewTreeObserver
4
5
  import com.facebook.react.bridge.Arguments
5
6
  import com.facebook.react.uimanager.ThemedReactContext
6
7
  import com.reactnativekeyboardcontroller.extensions.content
@@ -16,8 +17,9 @@ class WindowDimensionListener(
16
17
  private val context: ThemedReactContext?,
17
18
  ) {
18
19
  private var lastDispatchedDimensions = Dimensions(0.0, 0.0)
20
+ private var layoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
19
21
 
20
- init {
22
+ public fun attachListener() {
21
23
  // attach to content view only once per app instance
22
24
  if (context != null && listenerID != context.hashCode()) {
23
25
  listenerID = context.hashCode()
@@ -26,12 +28,19 @@ class WindowDimensionListener(
26
28
 
27
29
  updateWindowDimensions(content)
28
30
 
29
- content?.viewTreeObserver?.addOnGlobalLayoutListener {
30
- updateWindowDimensions(content)
31
- }
31
+ layoutListener =
32
+ ViewTreeObserver.OnGlobalLayoutListener {
33
+ updateWindowDimensions(content)
34
+ }
35
+
36
+ content?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener)
32
37
  }
33
38
  }
34
39
 
40
+ public fun detachListener() {
41
+ context?.content?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener)
42
+ }
43
+
35
44
  private fun updateWindowDimensions(content: ViewGroup?) {
36
45
  if (content == null) {
37
46
  return
@@ -7,14 +7,26 @@ import com.reactnativekeyboardcontroller.events.FocusedInputLayoutChangedEvent
7
7
  import com.reactnativekeyboardcontroller.events.FocusedInputSelectionChangedEvent
8
8
  import com.reactnativekeyboardcontroller.events.FocusedInputTextChangedEvent
9
9
  import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
10
+ import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener
10
11
  import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
11
12
 
12
13
  @Suppress("detekt:UnusedPrivateProperty")
13
14
  class KeyboardControllerViewManagerImpl(
14
15
  mReactContext: ReactApplicationContext,
15
16
  ) {
16
- fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup =
17
- EdgeToEdgeReactViewGroup(reactContext)
17
+ private var listener: WindowDimensionListener? = null
18
+
19
+ fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup {
20
+ if (listener == null) {
21
+ listener = WindowDimensionListener(reactContext)
22
+ listener?.attachListener()
23
+ }
24
+ return EdgeToEdgeReactViewGroup(reactContext)
25
+ }
26
+
27
+ fun invalidate() {
28
+ listener?.detachListener()
29
+ }
18
30
 
19
31
  fun setEnabled(
20
32
  view: EdgeToEdgeReactViewGroup,
@@ -15,7 +15,6 @@ import com.reactnativekeyboardcontroller.extensions.content
15
15
  import com.reactnativekeyboardcontroller.extensions.removeSelf
16
16
  import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached
17
17
  import com.reactnativekeyboardcontroller.extensions.rootView
18
- import com.reactnativekeyboardcontroller.extensions.setupWindowDimensionsListener
19
18
  import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallback
20
19
  import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallbackConfig
21
20
  import com.reactnativekeyboardcontroller.log.Logger
@@ -51,7 +50,6 @@ class EdgeToEdgeReactViewGroup(
51
50
  private val modalAttachedWatcher = ModalAttachedWatcher(this, reactContext, config, ::getKeyboardCallback)
52
51
 
53
52
  init {
54
- reactContext.setupWindowDimensionsListener()
55
53
  tag = VIEW_TAG
56
54
  }
57
55
 
@@ -65,13 +63,13 @@ class EdgeToEdgeReactViewGroup(
65
63
  return
66
64
  }
67
65
 
68
- this.setupKeyboardCallbacks()
66
+ this.activate()
69
67
  }
70
68
 
71
69
  override fun onDetachedFromWindow() {
72
70
  super.onDetachedFromWindow()
73
71
 
74
- this.removeKeyboardCallbacks()
72
+ this.deactivate()
75
73
  }
76
74
 
77
75
  override fun onConfigurationChanged(newConfig: Configuration?) {
@@ -189,12 +187,20 @@ class EdgeToEdgeReactViewGroup(
189
187
  // region State managers
190
188
  private fun enable() {
191
189
  this.setupWindowInsets()
192
- this.setupKeyboardCallbacks()
193
- modalAttachedWatcher.enable()
190
+ this.activate()
194
191
  }
195
192
 
196
193
  private fun disable() {
197
194
  this.setupWindowInsets()
195
+ this.deactivate()
196
+ }
197
+
198
+ private fun activate() {
199
+ this.setupKeyboardCallbacks()
200
+ modalAttachedWatcher.enable()
201
+ }
202
+
203
+ private fun deactivate() {
198
204
  this.removeKeyboardCallbacks()
199
205
  modalAttachedWatcher.disable()
200
206
  }
@@ -6,6 +6,7 @@ import android.graphics.PixelFormat
6
6
  import android.view.MotionEvent
7
7
  import android.view.View
8
8
  import android.view.WindowManager
9
+ import android.view.accessibility.AccessibilityEvent
9
10
  import com.facebook.react.bridge.UiThreadUtil
10
11
  import com.facebook.react.bridge.WritableMap
11
12
  import com.facebook.react.bridge.WritableNativeMap
@@ -84,6 +85,16 @@ class OverKeyboardHostView(
84
85
  }
85
86
  // endregion
86
87
 
88
+ // region Accessibility
89
+ override fun addChildrenForAccessibility(outChildren: ArrayList<View>) {
90
+ // Don’t let Android try to reach children that are not actual descendants
91
+ }
92
+
93
+ // Explicitly override this to prevent accessibility events being passed down to children
94
+ // Those will be handled by the `hostView` which lives in the `windowManager`
95
+ override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent): Boolean = false
96
+ // endregion
97
+
87
98
  fun show() {
88
99
  val layoutParams =
89
100
  WindowManager.LayoutParams(
@@ -13,16 +13,21 @@ class KeyboardControllerViewManager(
13
13
  ) : ReactViewManager() {
14
14
  private val manager = KeyboardControllerViewManagerImpl(mReactContext)
15
15
 
16
- override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
16
+ // region Lifecycle
17
+ override fun createViewInstance(context: ThemedReactContext): ReactViewGroup = manager.createViewInstance(context)
17
18
 
18
- override fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup =
19
- manager.createViewInstance(reactContext)
19
+ override fun invalidate() {
20
+ super.invalidate()
21
+ manager.invalidate()
22
+ }
20
23
 
21
24
  override fun onAfterUpdateTransaction(view: ReactViewGroup) {
22
25
  super.onAfterUpdateTransaction(view)
23
26
  manager.setEdgeToEdge(view as EdgeToEdgeReactViewGroup)
24
27
  }
28
+ // endregion
25
29
 
30
+ // region Props setters
26
31
  @ReactProp(name = "enabled")
27
32
  fun setEnabled(
28
33
  view: EdgeToEdgeReactViewGroup,
@@ -54,7 +59,12 @@ class KeyboardControllerViewManager(
54
59
  ) {
55
60
  manager.setPreserveEdgeToEdge(view, isPreservingEdgeToEdge)
56
61
  }
62
+ // endregion
57
63
 
64
+ // region Getters
58
65
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
59
66
  manager.getExportedCustomDirectEventTypeConstants()
67
+
68
+ override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
69
+ // endregion
60
70
  }
@@ -119,6 +119,8 @@ RCT_EXPORT_METHOD(setFocusTo : (nonnull NSString *)direction)
119
119
  @"KeyboardController::keyboardDidHide",
120
120
  // focused input
121
121
  @"KeyboardController::focusDidSet",
122
+ // window dimensions
123
+ @"KeyboardController::windowDidResize",
122
124
  ];
123
125
  }
124
126
 
@@ -8,29 +8,64 @@
8
8
  import Foundation
9
9
  import UIKit
10
10
 
11
+ private var pendingBecomeResponder: TextInput?
11
12
  private var originalResignFirstResponder: IMP?
13
+ private var originalBecomeFirstResponder: IMP?
12
14
 
13
15
  @objc
14
16
  extension UIResponder {
17
+ public static func swizzleBecomeFirstResponder() {
18
+ let originalBecomeSelector = #selector(becomeFirstResponder)
19
+ guard
20
+ let originalBecomeMethod = class_getInstanceMethod(UIResponder.self, originalBecomeSelector)
21
+ else {
22
+ return
23
+ }
24
+
25
+ originalBecomeFirstResponder = method_getImplementation(originalBecomeMethod)
26
+
27
+ let swizzledBecomeImplementation: @convention(block) (UIResponder) -> Bool = { (self) in
28
+ pendingBecomeResponder = self as? TextInput
29
+
30
+ DispatchQueue.main.asyncAfter(deadline: .now() + UIUtils.nextFrame) {
31
+ pendingBecomeResponder = nil
32
+ }
33
+
34
+ return self.callOriginalBecomeFirstResponder(originalBecomeSelector)
35
+ }
36
+
37
+ let implementation = imp_implementationWithBlock(swizzledBecomeImplementation)
38
+ method_setImplementation(originalBecomeMethod, implementation)
39
+ }
40
+
15
41
  public static func swizzleResignFirstResponder() {
16
- let originalSelector = #selector(resignFirstResponder)
42
+ let originalResignSelector = #selector(resignFirstResponder)
17
43
 
18
- guard let originalMethod = class_getInstanceMethod(UIResponder.self, originalSelector) else {
44
+ guard
45
+ let originalResignMethod = class_getInstanceMethod(UIResponder.self, originalResignSelector)
46
+ else {
19
47
  return
20
48
  }
21
49
 
22
- originalResignFirstResponder = method_getImplementation(originalMethod)
50
+ originalResignFirstResponder = method_getImplementation(originalResignMethod)
23
51
 
24
- let swizzledImplementation: @convention(block) (UIResponder) -> Bool = { (self) in
52
+ let swizzledResignImplementation: @convention(block) (UIResponder) -> Bool = { (self) in
25
53
  // Check the type of responder
26
54
  if let textField = self as? TextInput {
27
55
  // check inputAccessoryView and call original method immediately if not InvisibleInputAccessoryView
28
56
  if !(textField.inputAccessoryView is InvisibleInputAccessoryView) {
29
- return self.callOriginalResignFirstResponder(originalSelector)
57
+ return self.callOriginalResignFirstResponder(originalResignSelector)
58
+ } else if pendingBecomeResponder != nil {
59
+ // if we already have a new focus request
60
+ pendingBecomeResponder = nil
61
+ KeyboardAreaExtender.shared.hide()
62
+ (self as? TextInput)?.inputAccessoryView = nil
63
+ KeyboardAreaExtender.shared.remove()
64
+ return self.callOriginalResignFirstResponder(originalResignSelector)
30
65
  }
31
66
  } else {
32
67
  // If casting to TextInput fails
33
- return self.callOriginalResignFirstResponder(originalSelector)
68
+ return self.callOriginalResignFirstResponder(originalResignSelector)
34
69
  }
35
70
 
36
71
  KeyboardAreaExtender.shared.hide()
@@ -39,22 +74,34 @@ extension UIResponder {
39
74
  DispatchQueue.main.asyncAfter(deadline: .now() + UIUtils.nextFrame) {
40
75
  (self as? TextInput)?.inputAccessoryView = nil
41
76
  KeyboardAreaExtender.shared.remove()
42
- _ = self.callOriginalResignFirstResponder(originalSelector)
77
+ _ = self.callOriginalResignFirstResponder(originalResignSelector)
43
78
  }
44
79
 
45
80
  // We need to return a value immediately, even though the actual action is delayed
46
81
  return false
47
82
  }
48
83
 
49
- let implementation = imp_implementationWithBlock(swizzledImplementation)
50
- method_setImplementation(originalMethod, implementation)
84
+ let implementation = imp_implementationWithBlock(swizzledResignImplementation)
85
+ method_setImplementation(originalResignMethod, implementation)
51
86
  }
52
87
 
53
88
  private func callOriginalResignFirstResponder(_ selector: Selector) -> Bool {
54
89
  guard let originalResignFirstResponder = originalResignFirstResponder else { return false }
55
90
  typealias Function = @convention(c) (AnyObject, Selector) -> Bool
56
- let castOriginalResignFirstResponder = unsafeBitCast(originalResignFirstResponder, to: Function.self)
91
+ let castOriginalResignFirstResponder = unsafeBitCast(
92
+ originalResignFirstResponder, to: Function.self
93
+ )
57
94
  let result = castOriginalResignFirstResponder(self, selector)
58
95
  return result
59
96
  }
97
+
98
+ private func callOriginalBecomeFirstResponder(_ selector: Selector) -> Bool {
99
+ guard let originalBecomeFirstResponder = originalBecomeFirstResponder else { return false }
100
+ typealias Function = @convention(c) (AnyObject, Selector) -> Bool
101
+ let castOriginalBecomeFirstResponder = unsafeBitCast(
102
+ originalBecomeFirstResponder, to: Function.self
103
+ )
104
+ let result = castOriginalBecomeFirstResponder(self, selector)
105
+ return result
106
+ }
60
107
  }
@@ -37,6 +37,8 @@ using namespace facebook::react;
37
37
  @implementation KeyboardControllerView {
38
38
  KeyboardMovementObserver *keyboardObserver;
39
39
  FocusedInputObserver *inputObserver;
40
+
41
+ CGSize _lastScreenSize;
40
42
  }
41
43
 
42
44
  + (ComponentDescriptorProvider)componentDescriptorProvider
@@ -211,6 +213,22 @@ using namespace facebook::react;
211
213
  return self;
212
214
  }
213
215
 
216
+ - (void)layoutSubviews
217
+ {
218
+ [super layoutSubviews];
219
+
220
+ CGSize screenSize = [UIScreen mainScreen].bounds.size;
221
+ if (CGSizeEqualToSize(screenSize, _lastScreenSize)) {
222
+ return;
223
+ }
224
+
225
+ _lastScreenSize = screenSize;
226
+
227
+ NSDictionary *data = @{@"width" : @(screenSize.width), @"height" : @(screenSize.height)};
228
+
229
+ [KeyboardController.shared sendEvent:@"KeyboardController::windowDidResize" body:data];
230
+ }
231
+
214
232
  - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
215
233
  {
216
234
  const auto &oldViewProps = *std::static_pointer_cast<const KeyboardControllerViewProps>(_props);
@@ -15,6 +15,8 @@ class KeyboardControllerView: UIView {
15
15
  private var inputObserver: FocusedInputObserver?
16
16
  private var eventDispatcher: RCTEventDispatcherProtocol
17
17
  private var bridge: RCTBridge
18
+ // internal state
19
+ private var lastScreenSize: CGSize = .zero
18
20
  // react callbacks
19
21
  /// keyboard
20
22
  @objc var onKeyboardMoveStart: RCTDirectEventBlock?
@@ -83,6 +85,23 @@ class KeyboardControllerView: UIView {
83
85
  }
84
86
  }
85
87
 
88
+ override func layoutSubviews() {
89
+ super.layoutSubviews()
90
+
91
+ let screenSize = UIScreen.main.bounds.size
92
+
93
+ if lastScreenSize == screenSize {
94
+ return
95
+ }
96
+
97
+ lastScreenSize = screenSize
98
+
99
+ var data = [AnyHashable: Any]()
100
+ data["width"] = screenSize.width
101
+ data["height"] = screenSize.height
102
+ onNotify(event: "KeyboardController::windowDidResize", data: data)
103
+ }
104
+
86
105
  func onLayoutChanged(event: NSObject) {
87
106
  guard isJSThreadReady() else { return }
88
107
 
@@ -75,6 +75,7 @@ RCT_EXPORT_VIEW_PROPERTY(offset, NSNumber *)
75
75
  [super load];
76
76
 
77
77
  [UIResponder swizzleResignFirstResponder];
78
+ [UIResponder swizzleBecomeFirstResponder];
78
79
  }
79
80
 
80
81
  // MARK: Constructor
@@ -80,11 +80,12 @@ const KeyboardAvoidingView = /*#__PURE__*/(0, _react.forwardRef)(({
80
80
  const translateY = interpolateToRelativeKeyboardHeight(translate.value);
81
81
  const paddingBottom = interpolateToRelativeKeyboardHeight(padding.value);
82
82
  const bottomHeight = enabled ? bottom : 0;
83
+ const height = frame.value.height - bottomHeight;
83
84
  switch (behavior) {
84
85
  case "height":
85
- if (!keyboard.isClosed.value) {
86
+ if (!keyboard.isClosed.value && height > 0) {
86
87
  return {
87
- height: frame.value.height - bottomHeight,
88
+ height,
88
89
  flex: 0
89
90
  };
90
91
  }
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_hooks","_hooks2","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","_extends","assign","bind","arguments","length","apply","defaultLayout","x","y","width","height","KeyboardAvoidingView","forwardRef","behavior","children","contentContainerStyle","enabled","keyboardVerticalOffset","style","onLayout","onLayoutProps","props","ref","initialFrame","useSharedValue","frame","useDerivedValue","value","translate","padding","useTranslateAnimation","keyboard","useKeyboardAnimation","screenHeight","useWindowDimensions","relativeKeyboardHeight","useCallback","keyboardY","heightWhenOpened","Math","max","interpolateToRelativeKeyboardHeight","interpolate","onLayoutWorklet","layout","isClosed","runOnUI","nativeEvent","animatedStyle","useAnimatedStyle","bottom","progress","translateY","paddingBottom","bottomHeight","flex","paddingTop","transform","isPositionBehavior","containerStyle","combinedStyles","useMemo","createElement","View","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport Reanimated, {\n interpolate,\n runOnUI,\n useAnimatedStyle,\n useDerivedValue,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport { useWindowDimensions } from \"../../hooks\";\n\nimport { useKeyboardAnimation, useTranslateAnimation } from \"./hooks\";\n\nimport type { LayoutRectangle, ViewProps } from \"react-native\";\n\nexport type KeyboardAvoidingViewBaseProps = {\n /**\n * Controls whether this `KeyboardAvoidingView` instance should take effect.\n * This is useful when more than one is on the screen. Defaults to true.\n */\n enabled?: boolean;\n\n /**\n * Distance between the top of the user screen and the React Native view. This\n * may be non-zero in some cases. Defaults to 0.\n */\n keyboardVerticalOffset?: number;\n} & ViewProps;\n\nexport type KeyboardAvoidingViewProps = KeyboardAvoidingViewBaseProps &\n (\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"position\";\n\n /**\n * Style of the content container when `behavior` is 'position'.\n */\n contentContainerStyle?: ViewProps[\"style\"];\n }\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"height\" | \"padding\" | \"translate-with-padding\";\n\n /**\n * `contentContainerStyle` is not allowed for these behaviors.\n */\n contentContainerStyle?: never;\n }\n );\n\nconst defaultLayout: LayoutRectangle = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n};\n\n/**\n * A View component that automatically adjusts its height, position, or bottom padding\n * when the keyboard appears to ensure that the content remains visible.\n *\n * @returns A View component that adjusts to keyboard visibility.\n * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view|Documentation} page for more details.\n * @example\n * ```tsx\n * <KeyboardAvoidingView behavior=\"padding\">\n * <TextInput />\n * </KeyboardAvoidingView>\n * ```\n */\nconst KeyboardAvoidingView = forwardRef<\n View,\n React.PropsWithChildren<KeyboardAvoidingViewProps>\n>(\n (\n {\n behavior,\n children,\n contentContainerStyle,\n enabled = true,\n keyboardVerticalOffset = 0,\n style,\n onLayout: onLayoutProps,\n ...props\n },\n ref,\n ) => {\n const initialFrame = useSharedValue<LayoutRectangle | null>(null);\n const frame = useDerivedValue(() => initialFrame.value || defaultLayout);\n\n const { translate, padding } = useTranslateAnimation();\n const keyboard = useKeyboardAnimation();\n const { height: screenHeight } = useWindowDimensions();\n\n const relativeKeyboardHeight = useCallback(() => {\n \"worklet\";\n\n const keyboardY =\n screenHeight - keyboard.heightWhenOpened.value - keyboardVerticalOffset;\n\n return Math.max(frame.value.y + frame.value.height - keyboardY, 0);\n }, [screenHeight, keyboardVerticalOffset]);\n const interpolateToRelativeKeyboardHeight = useCallback(\n (value: number) => {\n \"worklet\";\n\n return interpolate(value, [0, 1], [0, relativeKeyboardHeight()]);\n },\n [relativeKeyboardHeight],\n );\n\n const onLayoutWorklet = useCallback(\n (layout: LayoutRectangle) => {\n \"worklet\";\n\n if (\n keyboard.isClosed.value ||\n initialFrame.value === null ||\n behavior !== \"height\"\n ) {\n // eslint-disable-next-line react-compiler/react-compiler\n initialFrame.value = layout;\n }\n },\n [behavior],\n );\n const onLayout = useCallback<NonNullable<ViewProps[\"onLayout\"]>>(\n (e) => {\n runOnUI(onLayoutWorklet)(e.nativeEvent.layout);\n onLayoutProps?.(e);\n },\n [onLayoutProps],\n );\n\n const animatedStyle = useAnimatedStyle(() => {\n const bottom = interpolateToRelativeKeyboardHeight(\n keyboard.progress.value,\n );\n const translateY = interpolateToRelativeKeyboardHeight(translate.value);\n const paddingBottom = interpolateToRelativeKeyboardHeight(padding.value);\n const bottomHeight = enabled ? bottom : 0;\n\n switch (behavior) {\n case \"height\":\n if (!keyboard.isClosed.value) {\n return {\n height: frame.value.height - bottomHeight,\n flex: 0,\n };\n }\n\n return {};\n\n case \"position\":\n return { bottom: bottomHeight };\n\n case \"padding\":\n return { paddingBottom: bottomHeight };\n\n case \"translate-with-padding\":\n return {\n paddingTop: paddingBottom,\n transform: [{ translateY: -translateY }],\n };\n\n default:\n return {};\n }\n }, [behavior, enabled, interpolateToRelativeKeyboardHeight]);\n const isPositionBehavior = behavior === \"position\";\n const containerStyle = isPositionBehavior ? contentContainerStyle : style;\n const combinedStyles = useMemo(\n () => [containerStyle, animatedStyle],\n [containerStyle, animatedStyle],\n );\n\n if (isPositionBehavior) {\n return (\n <View ref={ref} style={style} onLayout={onLayout} {...props}>\n <Reanimated.View style={combinedStyles}>{children}</Reanimated.View>\n </View>\n );\n }\n\n return (\n <Reanimated.View\n ref={ref}\n style={combinedStyles}\n onLayout={onLayout}\n {...props}\n >\n {children}\n </Reanimated.View>\n );\n },\n);\n\nexport default KeyboardAvoidingView;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_hooks","_hooks2","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","_extends","assign","bind","arguments","length","apply","defaultLayout","x","y","width","height","KeyboardAvoidingView","forwardRef","behavior","children","contentContainerStyle","enabled","keyboardVerticalOffset","style","onLayout","onLayoutProps","props","ref","initialFrame","useSharedValue","frame","useDerivedValue","value","translate","padding","useTranslateAnimation","keyboard","useKeyboardAnimation","screenHeight","useWindowDimensions","relativeKeyboardHeight","useCallback","keyboardY","heightWhenOpened","Math","max","interpolateToRelativeKeyboardHeight","interpolate","onLayoutWorklet","layout","isClosed","runOnUI","nativeEvent","animatedStyle","useAnimatedStyle","bottom","progress","translateY","paddingBottom","bottomHeight","flex","paddingTop","transform","isPositionBehavior","containerStyle","combinedStyles","useMemo","createElement","View","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport Reanimated, {\n interpolate,\n runOnUI,\n useAnimatedStyle,\n useDerivedValue,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport { useWindowDimensions } from \"../../hooks\";\n\nimport { useKeyboardAnimation, useTranslateAnimation } from \"./hooks\";\n\nimport type { LayoutRectangle, ViewProps } from \"react-native\";\n\nexport type KeyboardAvoidingViewBaseProps = {\n /**\n * Controls whether this `KeyboardAvoidingView` instance should take effect.\n * This is useful when more than one is on the screen. Defaults to true.\n */\n enabled?: boolean;\n\n /**\n * Distance between the top of the user screen and the React Native view. This\n * may be non-zero in some cases. Defaults to 0.\n */\n keyboardVerticalOffset?: number;\n} & ViewProps;\n\nexport type KeyboardAvoidingViewProps = KeyboardAvoidingViewBaseProps &\n (\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"position\";\n\n /**\n * Style of the content container when `behavior` is 'position'.\n */\n contentContainerStyle?: ViewProps[\"style\"];\n }\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"height\" | \"padding\" | \"translate-with-padding\";\n\n /**\n * `contentContainerStyle` is not allowed for these behaviors.\n */\n contentContainerStyle?: never;\n }\n );\n\nconst defaultLayout: LayoutRectangle = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n};\n\n/**\n * A View component that automatically adjusts its height, position, or bottom padding\n * when the keyboard appears to ensure that the content remains visible.\n *\n * @returns A View component that adjusts to keyboard visibility.\n * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view|Documentation} page for more details.\n * @example\n * ```tsx\n * <KeyboardAvoidingView behavior=\"padding\">\n * <TextInput />\n * </KeyboardAvoidingView>\n * ```\n */\nconst KeyboardAvoidingView = forwardRef<\n View,\n React.PropsWithChildren<KeyboardAvoidingViewProps>\n>(\n (\n {\n behavior,\n children,\n contentContainerStyle,\n enabled = true,\n keyboardVerticalOffset = 0,\n style,\n onLayout: onLayoutProps,\n ...props\n },\n ref,\n ) => {\n const initialFrame = useSharedValue<LayoutRectangle | null>(null);\n const frame = useDerivedValue(() => initialFrame.value || defaultLayout);\n\n const { translate, padding } = useTranslateAnimation();\n const keyboard = useKeyboardAnimation();\n const { height: screenHeight } = useWindowDimensions();\n\n const relativeKeyboardHeight = useCallback(() => {\n \"worklet\";\n\n const keyboardY =\n screenHeight - keyboard.heightWhenOpened.value - keyboardVerticalOffset;\n\n return Math.max(frame.value.y + frame.value.height - keyboardY, 0);\n }, [screenHeight, keyboardVerticalOffset]);\n const interpolateToRelativeKeyboardHeight = useCallback(\n (value: number) => {\n \"worklet\";\n\n return interpolate(value, [0, 1], [0, relativeKeyboardHeight()]);\n },\n [relativeKeyboardHeight],\n );\n\n const onLayoutWorklet = useCallback(\n (layout: LayoutRectangle) => {\n \"worklet\";\n\n if (\n keyboard.isClosed.value ||\n initialFrame.value === null ||\n behavior !== \"height\"\n ) {\n // eslint-disable-next-line react-compiler/react-compiler\n initialFrame.value = layout;\n }\n },\n [behavior],\n );\n const onLayout = useCallback<NonNullable<ViewProps[\"onLayout\"]>>(\n (e) => {\n runOnUI(onLayoutWorklet)(e.nativeEvent.layout);\n onLayoutProps?.(e);\n },\n [onLayoutProps],\n );\n\n const animatedStyle = useAnimatedStyle(() => {\n const bottom = interpolateToRelativeKeyboardHeight(\n keyboard.progress.value,\n );\n const translateY = interpolateToRelativeKeyboardHeight(translate.value);\n const paddingBottom = interpolateToRelativeKeyboardHeight(padding.value);\n const bottomHeight = enabled ? bottom : 0;\n const height = frame.value.height - bottomHeight;\n\n switch (behavior) {\n case \"height\":\n if (!keyboard.isClosed.value && height > 0) {\n return {\n height,\n flex: 0,\n };\n }\n\n return {};\n\n case \"position\":\n return { bottom: bottomHeight };\n\n case \"padding\":\n return { paddingBottom: bottomHeight };\n\n case \"translate-with-padding\":\n return {\n paddingTop: paddingBottom,\n transform: [{ translateY: -translateY }],\n };\n\n default:\n return {};\n }\n }, [behavior, enabled, interpolateToRelativeKeyboardHeight]);\n const isPositionBehavior = behavior === \"position\";\n const containerStyle = isPositionBehavior ? contentContainerStyle : style;\n const combinedStyles = useMemo(\n () => [containerStyle, animatedStyle],\n [containerStyle, animatedStyle],\n );\n\n if (isPositionBehavior) {\n return (\n <View ref={ref} style={style} onLayout={onLayout} {...props}>\n <Reanimated.View style={combinedStyles}>{children}</Reanimated.View>\n </View>\n );\n }\n\n return (\n <Reanimated.View\n ref={ref}\n style={combinedStyles}\n onLayout={onLayout}\n {...props}\n >\n {children}\n </Reanimated.View>\n );\n },\n);\n\nexport default KeyboardAvoidingView;\n"],"mappings":"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","ignoreList":[]}
@@ -249,6 +249,9 @@ const KeyboardAwareScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
249
249
  syncKeyboardFrame(e);
250
250
  }
251
251
  }, [maybeScroll, disableScrollOnKeyboardHide, syncKeyboardFrame]);
252
+ (0, _react.useEffect)(() => {
253
+ (0, _reactNativeReanimated.runOnUI)(maybeScroll)(keyboardHeight.value, true);
254
+ }, [bottomOffset]);
252
255
  (0, _reactNativeReanimated.useAnimatedReaction)(() => input.value, (current, previous) => {
253
256
  if ((current === null || current === void 0 ? void 0 : current.target) === (previous === null || previous === void 0 ? void 0 : previous.target) && (current === null || current === void 0 ? void 0 : current.layout.height) !== (previous === null || previous === void 0 ? void 0 : previous.layout.height)) {
254
257
  const prevLayout = layout.value;