react-native-keyboard-controller 1.6.1 → 1.8.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 (75) hide show
  1. package/README.md +2 -0
  2. package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +5 -0
  3. package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardAnimationCallback.kt +9 -1
  4. package/android/src/main/java/com/reactnativekeyboardcontroller/events/KeyboardTransitionEvent.kt +9 -9
  5. package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ViewGroup.kt +10 -0
  6. package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +4 -0
  7. package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +13 -7
  8. package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +111 -31
  9. package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +5 -0
  10. package/ios/KeyboardControllerView.mm +16 -1
  11. package/ios/KeyboardControllerViewManager.mm +4 -0
  12. package/ios/KeyboardControllerViewManager.swift +11 -1
  13. package/lib/commonjs/animated.js +17 -3
  14. package/lib/commonjs/animated.js.map +1 -1
  15. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js +43 -0
  16. package/lib/commonjs/components/KeyboardAvoidingView/hooks.js.map +1 -0
  17. package/lib/commonjs/components/KeyboardAvoidingView/index.js +100 -0
  18. package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -0
  19. package/lib/commonjs/components/index.js +14 -0
  20. package/lib/commonjs/components/index.js.map +1 -0
  21. package/lib/commonjs/context.js +3 -1
  22. package/lib/commonjs/context.js.map +1 -1
  23. package/lib/commonjs/hooks.js +8 -0
  24. package/lib/commonjs/hooks.js.map +1 -1
  25. package/lib/commonjs/index.js +17 -1
  26. package/lib/commonjs/index.js.map +1 -1
  27. package/lib/commonjs/monkey-patch.android.js +32 -20
  28. package/lib/commonjs/monkey-patch.android.js.map +1 -1
  29. package/lib/commonjs/monkey-patch.js +11 -1
  30. package/lib/commonjs/monkey-patch.js.map +1 -1
  31. package/lib/commonjs/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  32. package/lib/commonjs/types.js.map +1 -1
  33. package/lib/module/animated.js +18 -4
  34. package/lib/module/animated.js.map +1 -1
  35. package/lib/module/components/KeyboardAvoidingView/hooks.js +36 -0
  36. package/lib/module/components/KeyboardAvoidingView/hooks.js.map +1 -0
  37. package/lib/module/components/KeyboardAvoidingView/index.js +91 -0
  38. package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -0
  39. package/lib/module/components/index.js +2 -0
  40. package/lib/module/components/index.js.map +1 -0
  41. package/lib/module/context.js +3 -1
  42. package/lib/module/context.js.map +1 -1
  43. package/lib/module/hooks.js +7 -0
  44. package/lib/module/hooks.js.map +1 -1
  45. package/lib/module/index.js +1 -1
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/monkey-patch.android.js +26 -20
  48. package/lib/module/monkey-patch.android.js.map +1 -1
  49. package/lib/module/monkey-patch.js +3 -0
  50. package/lib/module/monkey-patch.js.map +1 -1
  51. package/lib/module/specs/KeyboardControllerViewNativeComponent.js.map +1 -1
  52. package/lib/module/types.js.map +1 -1
  53. package/lib/typescript/animated.d.ts +8 -1
  54. package/lib/typescript/components/KeyboardAvoidingView/hooks.d.ts +6 -0
  55. package/lib/typescript/components/KeyboardAvoidingView/index.d.ts +29 -0
  56. package/lib/typescript/components/index.d.ts +1 -0
  57. package/lib/typescript/context.d.ts +4 -2
  58. package/lib/typescript/hooks.d.ts +4 -0
  59. package/lib/typescript/index.d.ts +1 -1
  60. package/lib/typescript/monkey-patch.android.d.ts +2 -1
  61. package/lib/typescript/monkey-patch.d.ts +2 -0
  62. package/lib/typescript/specs/KeyboardControllerViewNativeComponent.d.ts +1 -0
  63. package/lib/typescript/types.d.ts +1 -0
  64. package/package.json +1 -1
  65. package/src/animated.tsx +25 -4
  66. package/src/components/KeyboardAvoidingView/hooks.ts +36 -0
  67. package/src/components/KeyboardAvoidingView/index.tsx +151 -0
  68. package/src/components/index.ts +1 -0
  69. package/src/context.ts +6 -2
  70. package/src/hooks.ts +6 -0
  71. package/src/index.ts +2 -2
  72. package/src/monkey-patch.android.ts +27 -21
  73. package/src/monkey-patch.ts +3 -0
  74. package/src/specs/KeyboardControllerViewNativeComponent.ts +1 -0
  75. package/src/types.ts +1 -0
package/README.md CHANGED
@@ -13,6 +13,8 @@ Keyboard manager which works in identical way on both iOS and Android.
13
13
  - module for changing soft input mode on Android 🤔
14
14
  - reanimated support 🚀
15
15
  - interactive keyboard dismissing 👆📱
16
+ - re-worked prebuilt components (such as `KeyboardAvoidingView`) 📚
17
+ - works with any navigation library 🧭
16
18
  - and more is coming... Stay tuned! 😊
17
19
 
18
20
  ## Installation
@@ -37,6 +37,11 @@ class KeyboardControllerViewManager(mReactContext: ReactApplicationContext) :
37
37
  return manager.setNavigationBarTranslucent(view as EdgeToEdgeReactViewGroup, value)
38
38
  }
39
39
 
40
+ @ReactProp(name = "enabled")
41
+ override fun setEnabled(view: ReactViewGroup, value: Boolean) {
42
+ return manager.setEnabled(view as EdgeToEdgeReactViewGroup, value)
43
+ }
44
+
40
45
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
41
46
  return manager.getExportedCustomDirectEventTypeConstants()
42
47
  }
@@ -32,6 +32,7 @@ class KeyboardAnimationCallback(
32
32
  dispatchMode: Int = DISPATCH_MODE_STOP,
33
33
  val context: ThemedReactContext?,
34
34
  ) : WindowInsetsAnimationCompat.Callback(dispatchMode), OnApplyWindowInsetsListener {
35
+ private val surfaceId = UIManagerHelper.getSurfaceId(view)
35
36
  private var persistentKeyboardHeight = 0.0
36
37
  private var isKeyboardVisible = false
37
38
  private var isTransitioning = false
@@ -57,6 +58,7 @@ class KeyboardAnimationCallback(
57
58
  // can bring breaking changes
58
59
  this.sendEventToJS(
59
60
  KeyboardTransitionEvent(
61
+ surfaceId,
60
62
  view.id,
61
63
  "topKeyboardMoveStart",
62
64
  this.persistentKeyboardHeight,
@@ -67,6 +69,7 @@ class KeyboardAnimationCallback(
67
69
  )
68
70
  this.sendEventToJS(
69
71
  KeyboardTransitionEvent(
72
+ surfaceId,
70
73
  view.id,
71
74
  "topKeyboardMoveEnd",
72
75
  this.persistentKeyboardHeight,
@@ -115,6 +118,7 @@ class KeyboardAnimationCallback(
115
118
  this.emitEvent("KeyboardController::keyboardWillShow", getEventParams(keyboardHeight))
116
119
  this.sendEventToJS(
117
120
  KeyboardTransitionEvent(
121
+ surfaceId,
118
122
  view.id,
119
123
  "topKeyboardMoveStart",
120
124
  keyboardHeight,
@@ -129,6 +133,7 @@ class KeyboardAnimationCallback(
129
133
  val toValue = animator.animatedValue as Float
130
134
  this.sendEventToJS(
131
135
  KeyboardTransitionEvent(
136
+ surfaceId,
132
137
  view.id,
133
138
  "topKeyboardMove",
134
139
  toValue.toDouble(),
@@ -142,6 +147,7 @@ class KeyboardAnimationCallback(
142
147
  this.emitEvent("KeyboardController::keyboardDidShow", getEventParams(keyboardHeight))
143
148
  this.sendEventToJS(
144
149
  KeyboardTransitionEvent(
150
+ surfaceId,
145
151
  view.id,
146
152
  "topKeyboardMoveEnd",
147
153
  keyboardHeight,
@@ -182,6 +188,7 @@ class KeyboardAnimationCallback(
182
188
  Log.i(TAG, "HEIGHT:: $keyboardHeight TAG:: $viewTagFocused")
183
189
  this.sendEventToJS(
184
190
  KeyboardTransitionEvent(
191
+ surfaceId,
185
192
  view.id,
186
193
  "topKeyboardMoveStart",
187
194
  keyboardHeight,
@@ -223,7 +230,7 @@ class KeyboardAnimationCallback(
223
230
  Log.i(TAG, "DiffY: $diffY $height $progress ${InteractiveKeyboardProvider.isInteractive} $viewTagFocused")
224
231
 
225
232
  val event = if (InteractiveKeyboardProvider.isInteractive) "topKeyboardMoveInteractive" else "topKeyboardMove"
226
- this.sendEventToJS(KeyboardTransitionEvent(view.id, event, height, progress, duration, viewTagFocused))
233
+ this.sendEventToJS(KeyboardTransitionEvent(surfaceId, view.id, event, height, progress, duration, viewTagFocused))
227
234
 
228
235
  return insets
229
236
  }
@@ -254,6 +261,7 @@ class KeyboardAnimationCallback(
254
261
  )
255
262
  this.sendEventToJS(
256
263
  KeyboardTransitionEvent(
264
+ surfaceId,
257
265
  view.id,
258
266
  "topKeyboardMoveEnd",
259
267
  keyboardHeight,
@@ -1,28 +1,28 @@
1
1
  package com.reactnativekeyboardcontroller.events
2
2
 
3
3
  import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
4
5
  import com.facebook.react.uimanager.events.Event
5
- import com.facebook.react.uimanager.events.RCTEventEmitter
6
6
 
7
+ @Suppress("detekt:LongParameterList")
7
8
  class KeyboardTransitionEvent(
9
+ surfaceId: Int,
8
10
  viewId: Int,
9
11
  private val event: String,
10
12
  private val height: Double,
11
13
  private val progress: Double,
12
14
  private val duration: Int,
13
15
  private val target: Int,
14
- ) : Event<KeyboardTransitionEvent>(viewId) {
16
+ ) : Event<KeyboardTransitionEvent>(surfaceId, viewId) {
15
17
  override fun getEventName() = event
16
18
 
17
19
  // All events for a given view can be coalesced?
18
20
  override fun getCoalescingKey(): Short = 0
19
21
 
20
- override fun dispatch(rctEventEmitter: RCTEventEmitter) {
21
- val map = Arguments.createMap()
22
- map.putDouble("progress", progress)
23
- map.putDouble("height", height)
24
- map.putInt("duration", duration)
25
- map.putInt("target", target)
26
- rctEventEmitter.receiveEvent(viewTag, eventName, map)
22
+ override fun getEventData(): WritableMap? = Arguments.createMap().apply {
23
+ putDouble("progress", progress)
24
+ putDouble("height", height)
25
+ putInt("duration", duration)
26
+ putInt("target", target)
27
27
  }
28
28
  }
@@ -0,0 +1,10 @@
1
+ package com.reactnativekeyboardcontroller.extensions
2
+
3
+ import android.view.ViewGroup
4
+
5
+ fun ViewGroup?.removeSelf() {
6
+ this ?: return
7
+ val parent = parent as? ViewGroup ?: return
8
+
9
+ parent.removeView(this)
10
+ }
@@ -11,6 +11,10 @@ class KeyboardControllerViewManagerImpl(mReactContext: ReactApplicationContext)
11
11
  return EdgeToEdgeReactViewGroup(reactContext)
12
12
  }
13
13
 
14
+ fun setEnabled(view: EdgeToEdgeReactViewGroup, enabled: Boolean) {
15
+ view.setActive(enabled)
16
+ }
17
+
14
18
  fun setStatusBarTranslucent(view: EdgeToEdgeReactViewGroup, isStatusBarTranslucent: Boolean) {
15
19
  view.setStatusBarTranslucent(isStatusBarTranslucent)
16
20
  }
@@ -5,12 +5,7 @@ import com.facebook.react.bridge.ReactApplicationContext
5
5
  import com.facebook.react.bridge.UiThreadUtil
6
6
 
7
7
  class KeyboardControllerModuleImpl(private val mReactContext: ReactApplicationContext) {
8
- private val mDefaultMode: Int = mReactContext
9
- .currentActivity
10
- ?.window
11
- ?.attributes
12
- ?.softInputMode
13
- ?: WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
8
+ private val mDefaultMode: Int = getCurrentMode()
14
9
 
15
10
  fun setInputMode(mode: Int) {
16
11
  setSoftInputMode(mode)
@@ -22,10 +17,21 @@ class KeyboardControllerModuleImpl(private val mReactContext: ReactApplicationCo
22
17
 
23
18
  private fun setSoftInputMode(mode: Int) {
24
19
  UiThreadUtil.runOnUiThread {
25
- mReactContext.currentActivity?.window?.setSoftInputMode(mode)
20
+ if (getCurrentMode() != mode) {
21
+ mReactContext.currentActivity?.window?.setSoftInputMode(mode)
22
+ }
26
23
  }
27
24
  }
28
25
 
26
+ private fun getCurrentMode(): Int {
27
+ return mReactContext
28
+ .currentActivity
29
+ ?.window
30
+ ?.attributes
31
+ ?.softInputMode
32
+ ?: WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
33
+ }
34
+
29
35
  companion object {
30
36
  const val NAME = "KeyboardController"
31
37
  }
@@ -13,60 +13,73 @@ import androidx.core.view.WindowInsetsCompat
13
13
  import com.facebook.react.uimanager.ThemedReactContext
14
14
  import com.facebook.react.views.view.ReactViewGroup
15
15
  import com.reactnativekeyboardcontroller.KeyboardAnimationCallback
16
+ import com.reactnativekeyboardcontroller.extensions.removeSelf
16
17
  import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached
17
18
  import com.reactnativekeyboardcontroller.extensions.rootView
18
19
 
19
20
  private val TAG = EdgeToEdgeReactViewGroup::class.qualifiedName
20
21
 
22
+ @Suppress("detekt:TooManyFunctions")
21
23
  @SuppressLint("ViewConstructor")
22
24
  class EdgeToEdgeReactViewGroup(private val reactContext: ThemedReactContext) : ReactViewGroup(reactContext) {
25
+ // props
23
26
  private var isStatusBarTranslucent = false
24
27
  private var isNavigationBarTranslucent = false
28
+ private var active = false
25
29
 
26
- init {
27
- val activity = reactContext.currentActivity
30
+ // internal class members
31
+ private var eventView: ReactViewGroup? = null
32
+ private var wasMounted = false
28
33
 
29
- if (activity != null) {
30
- val callback = KeyboardAnimationCallback(
31
- view = this,
32
- persistentInsetTypes = WindowInsetsCompat.Type.systemBars(),
33
- deferredInsetTypes = WindowInsetsCompat.Type.ime(),
34
- // We explicitly allow dispatch to continue down to binding.messageHolder's
35
- // child views, so that step 2.5 below receives the call
36
- dispatchMode = WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE,
37
- context = reactContext,
38
- )
39
- ViewCompat.setWindowInsetsAnimationCallback(this, callback)
40
- ViewCompat.setOnApplyWindowInsetsListener(this, callback)
41
- this.requestApplyInsetsWhenAttached()
42
- } else {
43
- Log.w(TAG, "Can not setup keyboard animation listener, since `currentActivity` is null")
34
+ // region View lifecycles
35
+ override fun onAttachedToWindow() {
36
+ super.onAttachedToWindow()
37
+
38
+ if (!wasMounted) {
39
+ // skip logic with callback re-creation if it was first render/mount
40
+ wasMounted = true
41
+ return
44
42
  }
43
+
44
+ this.setupKeyboardCallbacks()
45
+ }
46
+
47
+ override fun onDetachedFromWindow() {
48
+ super.onDetachedFromWindow()
49
+
50
+ // we need to remove view asynchronously from `onDetachedFromWindow` method
51
+ // otherwise we may face NPE when app is getting opened via universal link
52
+ // see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/242
53
+ // for more details
54
+ Handler(Looper.getMainLooper()).post { this.removeKeyboardCallbacks() }
45
55
  }
56
+ // endregion
46
57
 
58
+ // region State manager helpers
47
59
  private fun setupWindowInsets() {
48
60
  val rootView = reactContext.rootView
49
61
  if (rootView != null) {
50
62
  ViewCompat.setOnApplyWindowInsetsListener(rootView) { v, insets ->
51
- val content =
52
- reactContext.rootView?.findViewById<FitWindowsLinearLayout>(
53
- androidx.appcompat.R.id.action_bar_root,
54
- )
63
+ val content = getContentView()
55
64
  val params = FrameLayout.LayoutParams(
56
65
  FrameLayout.LayoutParams.MATCH_PARENT,
57
66
  FrameLayout.LayoutParams.MATCH_PARENT,
58
67
  )
59
68
 
69
+ val shouldApplyZeroPaddingTop = !active || this.isStatusBarTranslucent
70
+ val shouldApplyZeroPaddingBottom = !active || this.isNavigationBarTranslucent
60
71
  params.setMargins(
61
72
  0,
62
- if (this.isStatusBarTranslucent) {
73
+ if (shouldApplyZeroPaddingTop) {
63
74
  0
64
75
  } else {
65
- insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.top
66
- ?: 0
76
+ (
77
+ insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.top
78
+ ?: 0
79
+ )
67
80
  },
68
81
  0,
69
- if (this.isNavigationBarTranslucent) {
82
+ if (shouldApplyZeroPaddingBottom) {
70
83
  0
71
84
  } else {
72
85
  insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom
@@ -76,23 +89,79 @@ class EdgeToEdgeReactViewGroup(private val reactContext: ThemedReactContext) : R
76
89
 
77
90
  content?.layoutParams = params
78
91
 
79
- insets
92
+ val defaultInsets = ViewCompat.onApplyWindowInsets(v, insets)
93
+
94
+ defaultInsets.replaceSystemWindowInsets(
95
+ defaultInsets.systemWindowInsetLeft,
96
+ if (this.isStatusBarTranslucent) 0 else defaultInsets.systemWindowInsetTop,
97
+ defaultInsets.systemWindowInsetRight,
98
+ defaultInsets.systemWindowInsetBottom,
99
+ )
80
100
  }
81
101
  }
82
102
  }
83
103
 
84
- override fun onAttachedToWindow() {
85
- super.onAttachedToWindow()
86
-
87
- Handler(Looper.getMainLooper()).post(this::setupWindowInsets)
104
+ private fun goToEdgeToEdge(edgeToEdge: Boolean) {
88
105
  reactContext.currentActivity?.let {
89
106
  WindowCompat.setDecorFitsSystemWindows(
90
107
  it.window,
91
- false,
108
+ !edgeToEdge,
92
109
  )
93
110
  }
94
111
  }
95
112
 
113
+ private fun setupKeyboardCallbacks() {
114
+ val activity = reactContext.currentActivity
115
+
116
+ if (activity != null) {
117
+ eventView = ReactViewGroup(context)
118
+ val root = this.getContentView()
119
+ root?.addView(eventView)
120
+
121
+ val callback = KeyboardAnimationCallback(
122
+ view = this,
123
+ persistentInsetTypes = WindowInsetsCompat.Type.systemBars(),
124
+ deferredInsetTypes = WindowInsetsCompat.Type.ime(),
125
+ dispatchMode = WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE,
126
+ context = reactContext,
127
+ )
128
+
129
+ eventView?.let {
130
+ ViewCompat.setWindowInsetsAnimationCallback(it, callback)
131
+ ViewCompat.setOnApplyWindowInsetsListener(it, callback)
132
+ it.requestApplyInsetsWhenAttached()
133
+ }
134
+ } else {
135
+ Log.w(TAG, "Can not setup keyboard animation listener, since `currentActivity` is null")
136
+ }
137
+ }
138
+
139
+ private fun removeKeyboardCallbacks() {
140
+ eventView.removeSelf()
141
+ }
142
+
143
+ private fun getContentView(): FitWindowsLinearLayout? {
144
+ return reactContext.currentActivity?.window?.decorView?.rootView?.findViewById(
145
+ androidx.appcompat.R.id.action_bar_root,
146
+ )
147
+ }
148
+ // endregion
149
+
150
+ // region State managers
151
+ private fun enable() {
152
+ this.goToEdgeToEdge(true)
153
+ this.setupWindowInsets()
154
+ this.setupKeyboardCallbacks()
155
+ }
156
+
157
+ private fun disable() {
158
+ this.goToEdgeToEdge(false)
159
+ this.setupWindowInsets()
160
+ this.removeKeyboardCallbacks()
161
+ }
162
+ // endregion
163
+
164
+ // region Props setters
96
165
  fun setStatusBarTranslucent(isStatusBarTranslucent: Boolean) {
97
166
  this.isStatusBarTranslucent = isStatusBarTranslucent
98
167
  }
@@ -100,4 +169,15 @@ class EdgeToEdgeReactViewGroup(private val reactContext: ThemedReactContext) : R
100
169
  fun setNavigationBarTranslucent(isNavigationBarTranslucent: Boolean) {
101
170
  this.isNavigationBarTranslucent = isNavigationBarTranslucent
102
171
  }
172
+
173
+ fun setActive(active: Boolean) {
174
+ this.active = active
175
+
176
+ if (active) {
177
+ this.enable()
178
+ } else {
179
+ this.disable()
180
+ }
181
+ }
182
+ // endregion
103
183
  }
@@ -16,6 +16,11 @@ class KeyboardControllerViewManager(mReactContext: ReactApplicationContext) : Re
16
16
  return manager.createViewInstance(reactContext)
17
17
  }
18
18
 
19
+ @ReactProp(name = "enabled")
20
+ fun setEnabled(view: EdgeToEdgeReactViewGroup, enabled: Boolean) {
21
+ manager.setEnabled(view, enabled)
22
+ }
23
+
19
24
  @ReactProp(name = "statusBarTranslucent")
20
25
  fun setStatusBarTranslucent(view: EdgeToEdgeReactViewGroup, isStatusBarTranslucent: Boolean) {
21
26
  manager.setStatusBarTranslucent(view, isStatusBarTranslucent)
@@ -110,12 +110,27 @@ using namespace facebook::react;
110
110
  onNotify:^(NSString *event, NSDictionary *data) {
111
111
  [KeyboardController.shared sendEvent:event body:data];
112
112
  }];
113
- [observer mount];
114
113
  }
115
114
 
116
115
  return self;
117
116
  }
118
117
 
118
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
119
+ {
120
+ const auto &oldViewProps = *std::static_pointer_cast<const KeyboardControllerViewProps>(_props);
121
+ const auto &newViewProps = *std::static_pointer_cast<const KeyboardControllerViewProps>(props);
122
+
123
+ if (newViewProps.enabled != oldViewProps.enabled) {
124
+ if (newViewProps.enabled) {
125
+ [observer mount];
126
+ } else {
127
+ [observer unmount];
128
+ }
129
+ }
130
+
131
+ [super updateProps:props oldProps:oldProps];
132
+ }
133
+
119
134
  Class<RCTComponentViewProtocol> KeyboardControllerViewCls(void)
120
135
  {
121
136
  return KeyboardControllerView.class;
@@ -2,6 +2,10 @@
2
2
 
3
3
  @interface RCT_EXTERN_MODULE (KeyboardControllerViewManager, RCTViewManager)
4
4
 
5
+ // props
6
+ RCT_EXPORT_VIEW_PROPERTY(enabled, BOOL)
7
+
8
+ // callbacks
5
9
  RCT_EXPORT_VIEW_PROPERTY(onKeyboardMoveStart, RCTDirectEventBlock);
6
10
  RCT_EXPORT_VIEW_PROPERTY(onKeyboardMove, RCTDirectEventBlock);
7
11
  RCT_EXPORT_VIEW_PROPERTY(onKeyboardMoveEnd, RCTDirectEventBlock);
@@ -14,11 +14,21 @@ class KeyboardControllerView: UIView {
14
14
  private var keyboardObserver: KeyboardMovementObserver?
15
15
  private var eventDispatcher: RCTEventDispatcherProtocol
16
16
  private var bridge: RCTBridge
17
- // react props
17
+ // react callbacks
18
18
  @objc var onKeyboardMoveStart: RCTDirectEventBlock?
19
19
  @objc var onKeyboardMove: RCTDirectEventBlock?
20
20
  @objc var onKeyboardMoveEnd: RCTDirectEventBlock?
21
21
  @objc var onKeyboardMoveInteractive: RCTDirectEventBlock?
22
+ // react props
23
+ @objc var enabled: ObjCBool = true {
24
+ didSet {
25
+ if enabled.boolValue {
26
+ keyboardObserver?.mount()
27
+ } else {
28
+ keyboardObserver?.unmount()
29
+ }
30
+ }
31
+ }
22
32
 
23
33
  init(frame: CGRect, bridge: RCTBridge) {
24
34
  self.bridge = bridge
@@ -11,6 +11,7 @@ var _context = require("./context");
11
11
  var _internal = require("./internal");
12
12
  var _bindings = require("./bindings");
13
13
  var _reanimated = require("./reanimated");
14
+ var _monkeyPatch = require("./monkey-patch");
14
15
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
16
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
16
17
  const KeyboardControllerViewAnimated = _reactNativeReanimated.default.createAnimatedComponent(_reactNative.Animated.createAnimatedComponent(_bindings.KeyboardControllerView));
@@ -27,8 +28,10 @@ const KeyboardProvider = _ref => {
27
28
  let {
28
29
  children,
29
30
  statusBarTranslucent,
30
- navigationBarTranslucent
31
+ navigationBarTranslucent,
32
+ enabled: initiallyEnabled = true
31
33
  } = _ref;
34
+ const [enabled, setEnabled] = (0, _react.useState)(initiallyEnabled);
32
35
  // animated values
33
36
  const progress = (0, _internal.useAnimatedValue)(0);
34
37
  const height = (0, _internal.useAnimatedValue)(0);
@@ -41,6 +44,7 @@ const KeyboardProvider = _ref => {
41
44
  } = (0, _internal.useSharedHandlers)();
42
45
  // memo
43
46
  const context = (0, _react.useMemo)(() => ({
47
+ enabled,
44
48
  animated: {
45
49
  progress: progress,
46
50
  height: _reactNative.Animated.multiply(height, -1)
@@ -49,8 +53,9 @@ const KeyboardProvider = _ref => {
49
53
  progress: progressSV,
50
54
  height: heightSV
51
55
  },
52
- setHandlers
53
- }), []);
56
+ setHandlers,
57
+ setEnabled
58
+ }), [enabled]);
54
59
  const style = (0, _react.useMemo)(() => [styles.hidden, {
55
60
  transform: [{
56
61
  translateX: height
@@ -100,9 +105,18 @@ const KeyboardProvider = _ref => {
100
105
  broadcast('onInteractive', event);
101
106
  }
102
107
  }, []);
108
+ // effects
109
+ (0, _react.useEffect)(() => {
110
+ if (enabled) {
111
+ (0, _monkeyPatch.applyMonkeyPatch)();
112
+ } else {
113
+ (0, _monkeyPatch.revertMonkeyPatch)();
114
+ }
115
+ }, [enabled]);
103
116
  return /*#__PURE__*/_react.default.createElement(_context.KeyboardContext.Provider, {
104
117
  value: context
105
118
  }, /*#__PURE__*/_react.default.createElement(KeyboardControllerViewAnimated, {
119
+ enabled: enabled,
106
120
  onKeyboardMoveReanimated: handler,
107
121
  onKeyboardMoveStart: _reactNative.Platform.OS === 'ios' ? onKeyboardMove : undefined,
108
122
  onKeyboardMove: _reactNative.Platform.OS === 'android' ? onKeyboardMove : undefined,
@@ -1 +1 @@
1
- {"version":3,"names":["KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","styles","StyleSheet","create","container","flex","hidden","display","position","KeyboardProvider","children","statusBarTranslucent","navigationBarTranslucent","progress","useAnimatedValue","height","progressSV","useSharedValue","heightSV","setHandlers","broadcast","useSharedHandlers","context","useMemo","animated","multiply","reanimated","style","transform","translateX","translateY","onKeyboardMove","event","nativeEvent","useNativeDriver","updateSharedValues","platforms","includes","Platform","OS","value","handler","useAnimatedKeyboardHandler","onKeyboardMoveStart","onKeyboardMoveEnd","onKeyboardMoveInteractive","undefined"],"sources":["animated.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { Animated, Platform, StyleSheet, ViewStyle } from 'react-native';\nimport Reanimated, { useSharedValue } from 'react-native-reanimated';\n\nimport { KeyboardContext } from './context';\nimport { useSharedHandlers, useAnimatedValue } from './internal';\nimport { KeyboardControllerView } from './bindings';\nimport { useAnimatedKeyboardHandler } from './reanimated';\n\nimport type {\n KeyboardControllerProps,\n KeyboardHandler,\n NativeEvent,\n} from './types';\n\nconst KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(\n Animated.createAnimatedComponent(\n KeyboardControllerView\n ) as React.FC<KeyboardControllerProps>\n);\n\ntype Styles = {\n container: ViewStyle;\n hidden: ViewStyle;\n};\n\nconst styles = StyleSheet.create<Styles>({\n container: {\n flex: 1,\n },\n hidden: {\n display: 'none',\n position: 'absolute',\n },\n});\n\ntype KeyboardProviderProps = {\n children: React.ReactNode;\n /**\n * Set the value to `true`, if you use translucent status bar on Android.\n * If you already control status bar translucency via `react-native-screens`\n * or `StatusBar` component from `react-native`, you can ignore it.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/14\n * @platform android\n */\n statusBarTranslucent?: boolean;\n /**\n * Set the value to `true`, if you use translucent navigation bar on Android.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/119\n * @platform android\n */\n navigationBarTranslucent?: boolean;\n};\n\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n navigationBarTranslucent,\n}: KeyboardProviderProps) => {\n // animated values\n const progress = useAnimatedValue(0);\n const height = useAnimatedValue(0);\n // shared values\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const { setHandlers, broadcast } = useSharedHandlers<KeyboardHandler>();\n // memo\n const context = useMemo(\n () => ({\n animated: { progress: progress, height: Animated.multiply(height, -1) },\n reanimated: { progress: progressSV, height: heightSV },\n setHandlers,\n }),\n []\n );\n const style = useMemo(\n () => [\n styles.hidden,\n { transform: [{ translateX: height }, { translateY: progress }] },\n ],\n []\n );\n const onKeyboardMove = useMemo(\n () =>\n Animated.event(\n [\n {\n nativeEvent: {\n progress,\n height,\n },\n },\n ],\n { useNativeDriver: true }\n ),\n []\n );\n // handlers\n const updateSharedValues = (event: NativeEvent, platforms: string[]) => {\n 'worklet';\n\n if (platforms.includes(Platform.OS)) {\n progressSV.value = event.progress;\n heightSV.value = -event.height;\n }\n };\n const handler = useAnimatedKeyboardHandler(\n {\n onKeyboardMoveStart: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onStart', event);\n updateSharedValues(event, ['ios']);\n },\n onKeyboardMove: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onMove', event);\n updateSharedValues(event, ['android']);\n },\n onKeyboardMoveEnd: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onEnd', event);\n },\n onKeyboardMoveInteractive: (event: NativeEvent) => {\n 'worklet';\n\n updateSharedValues(event, ['android', 'ios']);\n broadcast('onInteractive', event);\n },\n },\n []\n );\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n onKeyboardMoveReanimated={handler}\n onKeyboardMoveStart={Platform.OS === 'ios' ? onKeyboardMove : undefined}\n onKeyboardMove={Platform.OS === 'android' ? onKeyboardMove : undefined}\n onKeyboardMoveInteractive={onKeyboardMove}\n navigationBarTranslucent={navigationBarTranslucent}\n statusBarTranslucent={statusBarTranslucent}\n // @ts-expect-error https://github.com/software-mansion/react-native-reanimated/pull/4923\n style={styles.container}\n >\n {children}\n </KeyboardControllerViewAnimated>\n <Animated.View\n // we are using this small hack, because if the component (where\n // animated value has been used) is unmounted, then animation will\n // stop receiving events (seems like it's react-native optimization).\n // So we need to keep a reference to the animated value, to keep it's\n // always mounted (keep a reference to an animated value).\n //\n // To test why it's needed, try to open screen which consumes Animated.Value\n // then close it and open it again (for example 'Animated transition').\n style={style}\n />\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","styles","StyleSheet","create","container","flex","hidden","display","position","KeyboardProvider","children","statusBarTranslucent","navigationBarTranslucent","enabled","initiallyEnabled","setEnabled","useState","progress","useAnimatedValue","height","progressSV","useSharedValue","heightSV","setHandlers","broadcast","useSharedHandlers","context","useMemo","animated","multiply","reanimated","style","transform","translateX","translateY","onKeyboardMove","event","nativeEvent","useNativeDriver","updateSharedValues","platforms","includes","Platform","OS","value","handler","useAnimatedKeyboardHandler","onKeyboardMoveStart","onKeyboardMoveEnd","onKeyboardMoveInteractive","useEffect","applyMonkeyPatch","revertMonkeyPatch","undefined"],"sources":["animated.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { Animated, Platform, StyleSheet, ViewStyle } from 'react-native';\nimport Reanimated, { useSharedValue } from 'react-native-reanimated';\n\nimport { KeyboardAnimationContext, KeyboardContext } from './context';\nimport { useSharedHandlers, useAnimatedValue } from './internal';\nimport { KeyboardControllerView } from './bindings';\nimport { useAnimatedKeyboardHandler } from './reanimated';\n\nimport type {\n KeyboardControllerProps,\n KeyboardHandler,\n NativeEvent,\n} from './types';\nimport { applyMonkeyPatch, revertMonkeyPatch } from './monkey-patch';\n\nconst KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(\n Animated.createAnimatedComponent(\n KeyboardControllerView\n ) as React.FC<KeyboardControllerProps>\n);\n\ntype Styles = {\n container: ViewStyle;\n hidden: ViewStyle;\n};\n\nconst styles = StyleSheet.create<Styles>({\n container: {\n flex: 1,\n },\n hidden: {\n display: 'none',\n position: 'absolute',\n },\n});\n\ntype KeyboardProviderProps = {\n children: React.ReactNode;\n /**\n * Set the value to `true`, if you use translucent status bar on Android.\n * If you already control status bar translucency via `react-native-screens`\n * or `StatusBar` component from `react-native`, you can ignore it.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/14\n * @platform android\n */\n statusBarTranslucent?: boolean;\n /**\n * Set the value to `true`, if you use translucent navigation bar on Android.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/119\n * @platform android\n */\n navigationBarTranslucent?: boolean;\n /**\n * A boolean prop indicating whether the module is enabled. It indicate only initial state,\n * i. e. if you try to change this prop after component mount it will not have any effect.\n * To change the property in runtime use `useKeyboardController` hook and `setEnabled` method.\n * Defaults to `true`.\n */\n enabled?: boolean;\n};\n\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n navigationBarTranslucent,\n enabled: initiallyEnabled = true,\n}: KeyboardProviderProps) => {\n const [enabled, setEnabled] = useState(initiallyEnabled);\n // animated values\n const progress = useAnimatedValue(0);\n const height = useAnimatedValue(0);\n // shared values\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const { setHandlers, broadcast } = useSharedHandlers<KeyboardHandler>();\n // memo\n const context = useMemo<KeyboardAnimationContext>(\n () => ({\n enabled,\n animated: { progress: progress, height: Animated.multiply(height, -1) },\n reanimated: { progress: progressSV, height: heightSV },\n setHandlers,\n setEnabled,\n }),\n [enabled]\n );\n const style = useMemo(\n () => [\n styles.hidden,\n { transform: [{ translateX: height }, { translateY: progress }] },\n ],\n []\n );\n const onKeyboardMove = useMemo(\n () =>\n Animated.event(\n [\n {\n nativeEvent: {\n progress,\n height,\n },\n },\n ],\n { useNativeDriver: true }\n ),\n []\n );\n // handlers\n const updateSharedValues = (event: NativeEvent, platforms: string[]) => {\n 'worklet';\n\n if (platforms.includes(Platform.OS)) {\n progressSV.value = event.progress;\n heightSV.value = -event.height;\n }\n };\n const handler = useAnimatedKeyboardHandler(\n {\n onKeyboardMoveStart: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onStart', event);\n updateSharedValues(event, ['ios']);\n },\n onKeyboardMove: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onMove', event);\n updateSharedValues(event, ['android']);\n },\n onKeyboardMoveEnd: (event: NativeEvent) => {\n 'worklet';\n\n broadcast('onEnd', event);\n },\n onKeyboardMoveInteractive: (event: NativeEvent) => {\n 'worklet';\n\n updateSharedValues(event, ['android', 'ios']);\n broadcast('onInteractive', event);\n },\n },\n []\n );\n // effects\n useEffect(() => {\n if (enabled) {\n applyMonkeyPatch();\n } else {\n revertMonkeyPatch();\n }\n }, [enabled]);\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n enabled={enabled}\n onKeyboardMoveReanimated={handler}\n onKeyboardMoveStart={Platform.OS === 'ios' ? onKeyboardMove : undefined}\n onKeyboardMove={Platform.OS === 'android' ? onKeyboardMove : undefined}\n onKeyboardMoveInteractive={onKeyboardMove}\n navigationBarTranslucent={navigationBarTranslucent}\n statusBarTranslucent={statusBarTranslucent}\n // @ts-expect-error https://github.com/software-mansion/react-native-reanimated/pull/4923\n style={styles.container}\n >\n {children}\n </KeyboardControllerViewAnimated>\n <Animated.View\n // we are using this small hack, because if the component (where\n // animated value has been used) is unmounted, then animation will\n // stop receiving events (seems like it's react-native optimization).\n // So we need to keep a reference to the animated value, to keep it's\n // always mounted (keep a reference to an animated value).\n //\n // To test why it's needed, try to open screen which consumes Animated.Value\n // then close it and open it again (for example 'Animated transition').\n style={style}\n />\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useKeyboardAnimation = void 0;
7
+ var _reactNativeReanimated = require("react-native-reanimated");
8
+ var _hooks = require("../../hooks");
9
+ const useKeyboardAnimation = () => {
10
+ const heightWhenOpened = (0, _reactNativeReanimated.useSharedValue)(0);
11
+ const height = (0, _reactNativeReanimated.useSharedValue)(0);
12
+ const progress = (0, _reactNativeReanimated.useSharedValue)(0);
13
+ const isClosed = (0, _reactNativeReanimated.useSharedValue)(true);
14
+ (0, _hooks.useKeyboardHandler)({
15
+ onStart: e => {
16
+ 'worklet';
17
+
18
+ if (e.height > 0) {
19
+ isClosed.value = false;
20
+ heightWhenOpened.value = e.height;
21
+ }
22
+ },
23
+ onMove: e => {
24
+ 'worklet';
25
+
26
+ progress.value = e.progress;
27
+ height.value = e.height;
28
+ },
29
+ onEnd: e => {
30
+ 'worklet';
31
+
32
+ isClosed.value = e.height === 0;
33
+ }
34
+ }, []);
35
+ return {
36
+ height,
37
+ progress,
38
+ heightWhenOpened,
39
+ isClosed
40
+ };
41
+ };
42
+ exports.useKeyboardAnimation = useKeyboardAnimation;
43
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useKeyboardAnimation","heightWhenOpened","useSharedValue","height","progress","isClosed","useKeyboardHandler","onStart","e","value","onMove","onEnd"],"sources":["hooks.ts"],"sourcesContent":["import { useSharedValue } from 'react-native-reanimated';\nimport { useKeyboardHandler } from '../../hooks';\n\nexport const useKeyboardAnimation = () => {\n const heightWhenOpened = useSharedValue(0);\n const height = useSharedValue(0);\n const progress = useSharedValue(0);\n const isClosed = useSharedValue(true);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n 'worklet';\n\n if (e.height > 0) {\n isClosed.value = false;\n heightWhenOpened.value = e.height;\n }\n },\n onMove: (e) => {\n 'worklet';\n\n progress.value = e.progress;\n height.value = e.height;\n },\n onEnd: (e) => {\n 'worklet';\n\n isClosed.value = e.height === 0;\n },\n },\n []\n );\n\n return { height, progress, heightWhenOpened, isClosed };\n};\n"],"mappings":";;;;;;AAAA;AACA;AAEO,MAAMA,oBAAoB,GAAG,MAAM;EACxC,MAAMC,gBAAgB,GAAG,IAAAC,qCAAc,EAAC,CAAC,CAAC;EAC1C,MAAMC,MAAM,GAAG,IAAAD,qCAAc,EAAC,CAAC,CAAC;EAChC,MAAME,QAAQ,GAAG,IAAAF,qCAAc,EAAC,CAAC,CAAC;EAClC,MAAMG,QAAQ,GAAG,IAAAH,qCAAc,EAAC,IAAI,CAAC;EAErC,IAAAI,yBAAkB,EAChB;IACEC,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACL,MAAM,GAAG,CAAC,EAAE;QAChBE,QAAQ,CAACI,KAAK,GAAG,KAAK;QACtBR,gBAAgB,CAACQ,KAAK,GAAGD,CAAC,CAACL,MAAM;MACnC;IACF,CAAC;IACDO,MAAM,EAAGF,CAAC,IAAK;MACb,SAAS;;MAETJ,QAAQ,CAACK,KAAK,GAAGD,CAAC,CAACJ,QAAQ;MAC3BD,MAAM,CAACM,KAAK,GAAGD,CAAC,CAACL,MAAM;IACzB,CAAC;IACDQ,KAAK,EAAGH,CAAC,IAAK;MACZ,SAAS;;MAETH,QAAQ,CAACI,KAAK,GAAGD,CAAC,CAACL,MAAM,KAAK,CAAC;IACjC;EACF,CAAC,EACD,EAAE,CACH;EAED,OAAO;IAAEA,MAAM;IAAEC,QAAQ;IAAEH,gBAAgB;IAAEI;EAAS,CAAC;AACzD,CAAC;AAAC"}