react-native-keyboard-controller 1.14.0 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/reactnativekeyboardcontroller/constants/Keyboard.kt +7 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputLayoutChangedEvent.kt +5 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputSelectionChangedEvent.kt +5 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/FocusedInputTextChangedEvent.kt +5 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/events/KeyboardTransitionEvent.kt +18 -2
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +45 -17
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +11 -7
- package/android/src/main/java/com/reactnativekeyboardcontroller/modal/ModalAttachedWatcher.kt +32 -4
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/StatusBarManagerCompatModuleImpl.kt +7 -2
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +5 -1
- package/ios/{core → animations}/KeyboardAnimation.swift +1 -0
- package/ios/{core → animations}/SpringAnimation.swift +1 -1
- package/ios/{core → animations}/TimingAnimation.swift +21 -20
- package/ios/extensions/UIApplication.swift +17 -1
- package/ios/extensions/UIView.swift +28 -1
- package/ios/extensions/UIWindow.swift +5 -2
- package/ios/observers/FocusedInputObserver.swift +4 -4
- package/ios/views/OverKeyboardViewManager.mm +17 -0
- package/lib/commonjs/components/KeyboardAvoidingView/hooks.js +6 -0
- package/lib/commonjs/components/KeyboardAvoidingView/hooks.js.map +1 -1
- package/lib/module/components/KeyboardAvoidingView/hooks.js +6 -0
- package/lib/module/components/KeyboardAvoidingView/hooks.js.map +1 -1
- package/package.json +1 -1
- package/src/components/KeyboardAvoidingView/hooks.ts +6 -0
|
@@ -20,7 +20,7 @@ class FocusedInputLayoutChangedEvent(
|
|
|
20
20
|
viewId: Int,
|
|
21
21
|
private val event: FocusedInputLayoutChangedEventData,
|
|
22
22
|
) : Event<FocusedInputLayoutChangedEvent>(surfaceId, viewId) {
|
|
23
|
-
override fun getEventName() =
|
|
23
|
+
override fun getEventName() = EVENT_NAME
|
|
24
24
|
|
|
25
25
|
// All events for a given view can be coalesced
|
|
26
26
|
override fun getCoalescingKey(): Short = 0
|
|
@@ -41,4 +41,8 @@ class FocusedInputLayoutChangedEvent(
|
|
|
41
41
|
},
|
|
42
42
|
)
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
companion object {
|
|
46
|
+
const val EVENT_NAME = "topFocusedInputLayoutChanged"
|
|
47
|
+
}
|
|
44
48
|
}
|
|
@@ -19,7 +19,7 @@ class FocusedInputSelectionChangedEvent(
|
|
|
19
19
|
viewId: Int,
|
|
20
20
|
private val event: FocusedInputSelectionChangedEventData,
|
|
21
21
|
) : Event<FocusedInputSelectionChangedEvent>(surfaceId, viewId) {
|
|
22
|
-
override fun getEventName() =
|
|
22
|
+
override fun getEventName() = EVENT_NAME
|
|
23
23
|
|
|
24
24
|
// All events for a given view can be coalesced
|
|
25
25
|
override fun getCoalescingKey(): Short = 0
|
|
@@ -49,4 +49,8 @@ class FocusedInputSelectionChangedEvent(
|
|
|
49
49
|
},
|
|
50
50
|
)
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
companion object {
|
|
54
|
+
const val EVENT_NAME = "topFocusedInputSelectionChanged"
|
|
55
|
+
}
|
|
52
56
|
}
|
|
@@ -9,7 +9,7 @@ class FocusedInputTextChangedEvent(
|
|
|
9
9
|
viewId: Int,
|
|
10
10
|
private val text: String,
|
|
11
11
|
) : Event<FocusedInputTextChangedEvent>(surfaceId, viewId) {
|
|
12
|
-
override fun getEventName() =
|
|
12
|
+
override fun getEventName() = EVENT_NAME
|
|
13
13
|
|
|
14
14
|
// All events for a given view can be coalesced
|
|
15
15
|
override fun getCoalescingKey(): Short = 0
|
|
@@ -18,4 +18,8 @@ class FocusedInputTextChangedEvent(
|
|
|
18
18
|
Arguments.createMap().apply {
|
|
19
19
|
putString("text", text)
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
companion object {
|
|
23
|
+
const val EVENT_NAME = "topFocusedInputTextChanged"
|
|
24
|
+
}
|
|
21
25
|
}
|
package/android/src/main/java/com/reactnativekeyboardcontroller/events/KeyboardTransitionEvent.kt
CHANGED
|
@@ -8,13 +8,13 @@ import com.facebook.react.uimanager.events.Event
|
|
|
8
8
|
class KeyboardTransitionEvent(
|
|
9
9
|
surfaceId: Int,
|
|
10
10
|
viewId: Int,
|
|
11
|
-
private val event:
|
|
11
|
+
private val event: EventName,
|
|
12
12
|
private val height: Double,
|
|
13
13
|
private val progress: Double,
|
|
14
14
|
private val duration: Int,
|
|
15
15
|
private val target: Int,
|
|
16
16
|
) : Event<KeyboardTransitionEvent>(surfaceId, viewId) {
|
|
17
|
-
override fun getEventName() = event
|
|
17
|
+
override fun getEventName() = event.value
|
|
18
18
|
|
|
19
19
|
// All events for a given view can be coalesced?
|
|
20
20
|
override fun getCoalescingKey(): Short = 0
|
|
@@ -26,4 +26,20 @@ class KeyboardTransitionEvent(
|
|
|
26
26
|
putInt("duration", duration)
|
|
27
27
|
putInt("target", target)
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
companion object {
|
|
31
|
+
enum class EventName(
|
|
32
|
+
val value: String,
|
|
33
|
+
) {
|
|
34
|
+
Move("topKeyboardMove"),
|
|
35
|
+
Start("topKeyboardMoveStart"),
|
|
36
|
+
End("topKeyboardMoveEnd"),
|
|
37
|
+
Interactive("topKeyboardMoveInteractive"),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
val Move = EventName.Move
|
|
41
|
+
val Start = EventName.Start
|
|
42
|
+
val End = EventName.End
|
|
43
|
+
val Interactive = EventName.Interactive
|
|
44
|
+
}
|
|
29
45
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package com.reactnativekeyboardcontroller.listeners
|
|
2
2
|
|
|
3
|
-
import android.os.Build
|
|
4
3
|
import android.view.View
|
|
5
4
|
import android.view.ViewTreeObserver.OnGlobalFocusChangeListener
|
|
6
5
|
import androidx.core.graphics.Insets
|
|
@@ -14,6 +13,7 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
|
14
13
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
15
14
|
import com.facebook.react.views.textinput.ReactEditText
|
|
16
15
|
import com.facebook.react.views.view.ReactViewGroup
|
|
16
|
+
import com.reactnativekeyboardcontroller.constants.Keyboard
|
|
17
17
|
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
|
|
18
18
|
import com.reactnativekeyboardcontroller.extensions.dispatchEvent
|
|
19
19
|
import com.reactnativekeyboardcontroller.extensions.dp
|
|
@@ -24,7 +24,7 @@ import com.reactnativekeyboardcontroller.log.Logger
|
|
|
24
24
|
import kotlin.math.abs
|
|
25
25
|
|
|
26
26
|
private val TAG = KeyboardAnimationCallback::class.qualifiedName
|
|
27
|
-
private val isResizeHandledInCallbackMethods =
|
|
27
|
+
private val isResizeHandledInCallbackMethods = Keyboard.IS_ANIMATION_EMULATED
|
|
28
28
|
|
|
29
29
|
data class KeyboardAnimationCallbackConfig(
|
|
30
30
|
val persistentInsetTypes: Int,
|
|
@@ -33,13 +33,22 @@ data class KeyboardAnimationCallbackConfig(
|
|
|
33
33
|
val hasTranslucentNavigationBar: Boolean = false,
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
+
interface Suspendable {
|
|
37
|
+
var isSuspended: Boolean
|
|
38
|
+
|
|
39
|
+
fun suspend(suspended: Boolean) {
|
|
40
|
+
isSuspended = suspended
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
class KeyboardAnimationCallback(
|
|
37
45
|
val eventPropagationView: ReactViewGroup,
|
|
38
46
|
val view: View,
|
|
39
47
|
val context: ThemedReactContext?,
|
|
40
48
|
private val config: KeyboardAnimationCallbackConfig,
|
|
41
49
|
) : WindowInsetsAnimationCompat.Callback(config.dispatchMode),
|
|
42
|
-
OnApplyWindowInsetsListener
|
|
50
|
+
OnApplyWindowInsetsListener,
|
|
51
|
+
Suspendable {
|
|
43
52
|
private val surfaceId = UIManagerHelper.getSurfaceId(eventPropagationView)
|
|
44
53
|
|
|
45
54
|
// state variables
|
|
@@ -50,6 +59,7 @@ class KeyboardAnimationCallback(
|
|
|
50
59
|
private var duration = 0
|
|
51
60
|
private var viewTagFocused = -1
|
|
52
61
|
private var animationsToSkip = hashSetOf<WindowInsetsAnimationCompat>()
|
|
62
|
+
override var isSuspended: Boolean = false
|
|
53
63
|
|
|
54
64
|
// listeners
|
|
55
65
|
private val focusListener =
|
|
@@ -69,7 +79,7 @@ class KeyboardAnimationCallback(
|
|
|
69
79
|
KeyboardTransitionEvent(
|
|
70
80
|
surfaceId,
|
|
71
81
|
eventPropagationView.id,
|
|
72
|
-
|
|
82
|
+
KeyboardTransitionEvent.Start,
|
|
73
83
|
this.persistentKeyboardHeight,
|
|
74
84
|
1.0,
|
|
75
85
|
0,
|
|
@@ -81,7 +91,7 @@ class KeyboardAnimationCallback(
|
|
|
81
91
|
KeyboardTransitionEvent(
|
|
82
92
|
surfaceId,
|
|
83
93
|
eventPropagationView.id,
|
|
84
|
-
|
|
94
|
+
KeyboardTransitionEvent.End,
|
|
85
95
|
this.persistentKeyboardHeight,
|
|
86
96
|
1.0,
|
|
87
97
|
0,
|
|
@@ -147,7 +157,7 @@ class KeyboardAnimationCallback(
|
|
|
147
157
|
this.onKeyboardResized(keyboardHeight)
|
|
148
158
|
}
|
|
149
159
|
|
|
150
|
-
return
|
|
160
|
+
return insets
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
@Suppress("detekt:ReturnCount")
|
|
@@ -155,7 +165,7 @@ class KeyboardAnimationCallback(
|
|
|
155
165
|
animation: WindowInsetsAnimationCompat,
|
|
156
166
|
bounds: WindowInsetsAnimationCompat.BoundsCompat,
|
|
157
167
|
): WindowInsetsAnimationCompat.BoundsCompat {
|
|
158
|
-
if (!animation.isKeyboardAnimation) {
|
|
168
|
+
if (!animation.isKeyboardAnimation || isSuspended) {
|
|
159
169
|
return bounds
|
|
160
170
|
}
|
|
161
171
|
|
|
@@ -193,7 +203,7 @@ class KeyboardAnimationCallback(
|
|
|
193
203
|
KeyboardTransitionEvent(
|
|
194
204
|
surfaceId,
|
|
195
205
|
eventPropagationView.id,
|
|
196
|
-
|
|
206
|
+
KeyboardTransitionEvent.Start,
|
|
197
207
|
keyboardHeight,
|
|
198
208
|
if (!isKeyboardVisible) 0.0 else 1.0,
|
|
199
209
|
duration,
|
|
@@ -211,7 +221,13 @@ class KeyboardAnimationCallback(
|
|
|
211
221
|
// onProgress() is called when any of the running animations progress...
|
|
212
222
|
|
|
213
223
|
// ignore non-keyboard animation or animation that we intentionally want to skip
|
|
214
|
-
|
|
224
|
+
val shouldSkipAnimation =
|
|
225
|
+
runningAnimations.find {
|
|
226
|
+
it.isKeyboardAnimation && !animationsToSkip.contains(it)
|
|
227
|
+
} == null
|
|
228
|
+
if (isSuspended || shouldSkipAnimation) {
|
|
229
|
+
return insets
|
|
230
|
+
}
|
|
215
231
|
|
|
216
232
|
// First we get the insets which are potentially deferred
|
|
217
233
|
val typesInset = insets.getInsets(config.deferredInsetTypes)
|
|
@@ -242,7 +258,12 @@ class KeyboardAnimationCallback(
|
|
|
242
258
|
"DiffY: $diffY $height $progress ${InteractiveKeyboardProvider.isInteractive} $viewTagFocused",
|
|
243
259
|
)
|
|
244
260
|
|
|
245
|
-
val event =
|
|
261
|
+
val event =
|
|
262
|
+
if (InteractiveKeyboardProvider.isInteractive) {
|
|
263
|
+
KeyboardTransitionEvent.Interactive
|
|
264
|
+
} else {
|
|
265
|
+
KeyboardTransitionEvent.Move
|
|
266
|
+
}
|
|
246
267
|
context.dispatchEvent(
|
|
247
268
|
eventPropagationView.id,
|
|
248
269
|
KeyboardTransitionEvent(
|
|
@@ -262,7 +283,7 @@ class KeyboardAnimationCallback(
|
|
|
262
283
|
override fun onEnd(animation: WindowInsetsAnimationCompat) {
|
|
263
284
|
super.onEnd(animation)
|
|
264
285
|
|
|
265
|
-
if (!animation.isKeyboardAnimation) {
|
|
286
|
+
if (!animation.isKeyboardAnimation || isSuspended) {
|
|
266
287
|
return
|
|
267
288
|
}
|
|
268
289
|
|
|
@@ -299,7 +320,7 @@ class KeyboardAnimationCallback(
|
|
|
299
320
|
KeyboardTransitionEvent(
|
|
300
321
|
surfaceId,
|
|
301
322
|
eventPropagationView.id,
|
|
302
|
-
|
|
323
|
+
KeyboardTransitionEvent.End,
|
|
303
324
|
keyboardHeight,
|
|
304
325
|
if (!isKeyboardVisible) 0.0 else 1.0,
|
|
305
326
|
duration,
|
|
@@ -311,10 +332,13 @@ class KeyboardAnimationCallback(
|
|
|
311
332
|
duration = 0
|
|
312
333
|
}
|
|
313
334
|
|
|
314
|
-
fun syncKeyboardPosition(
|
|
315
|
-
|
|
335
|
+
fun syncKeyboardPosition(
|
|
336
|
+
height: Double? = null,
|
|
337
|
+
isVisible: Boolean? = null,
|
|
338
|
+
) {
|
|
339
|
+
val keyboardHeight = height ?: getCurrentKeyboardHeight()
|
|
316
340
|
// update internal state
|
|
317
|
-
isKeyboardVisible = isKeyboardVisible()
|
|
341
|
+
isKeyboardVisible = isVisible ?: isKeyboardVisible()
|
|
318
342
|
prevKeyboardHeight = keyboardHeight
|
|
319
343
|
isTransitioning = false
|
|
320
344
|
duration = 0
|
|
@@ -324,7 +348,7 @@ class KeyboardAnimationCallback(
|
|
|
324
348
|
getEventParams(keyboardHeight),
|
|
325
349
|
)
|
|
326
350
|
// dispatch `onMove` to update RN animated value and `onEnd` to indicate that transition finished
|
|
327
|
-
listOf(
|
|
351
|
+
listOf(KeyboardTransitionEvent.Move, KeyboardTransitionEvent.End).forEach { eventName ->
|
|
328
352
|
context.dispatchEvent(
|
|
329
353
|
eventPropagationView.id,
|
|
330
354
|
KeyboardTransitionEvent(
|
|
@@ -352,7 +376,11 @@ class KeyboardAnimationCallback(
|
|
|
352
376
|
duration = 0
|
|
353
377
|
|
|
354
378
|
context.emitEvent("KeyboardController::keyboardWillShow", getEventParams(keyboardHeight))
|
|
355
|
-
listOf(
|
|
379
|
+
listOf(
|
|
380
|
+
KeyboardTransitionEvent.Start,
|
|
381
|
+
KeyboardTransitionEvent.Move,
|
|
382
|
+
KeyboardTransitionEvent.End,
|
|
383
|
+
).forEach { eventName ->
|
|
356
384
|
context.dispatchEvent(
|
|
357
385
|
eventPropagationView.id,
|
|
358
386
|
KeyboardTransitionEvent(
|
|
@@ -3,6 +3,10 @@ package com.reactnativekeyboardcontroller.managers
|
|
|
3
3
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
4
|
import com.facebook.react.common.MapBuilder
|
|
5
5
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
+
import com.reactnativekeyboardcontroller.events.FocusedInputLayoutChangedEvent
|
|
7
|
+
import com.reactnativekeyboardcontroller.events.FocusedInputSelectionChangedEvent
|
|
8
|
+
import com.reactnativekeyboardcontroller.events.FocusedInputTextChangedEvent
|
|
9
|
+
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
|
|
6
10
|
import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
|
|
7
11
|
|
|
8
12
|
@Suppress("detekt:UnusedPrivateProperty")
|
|
@@ -36,19 +40,19 @@ class KeyboardControllerViewManagerImpl(
|
|
|
36
40
|
fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
|
|
37
41
|
val map: MutableMap<String, Any> =
|
|
38
42
|
MapBuilder.of(
|
|
39
|
-
|
|
43
|
+
KeyboardTransitionEvent.Move.value,
|
|
40
44
|
MapBuilder.of("registrationName", "onKeyboardMove"),
|
|
41
|
-
|
|
45
|
+
KeyboardTransitionEvent.Start.value,
|
|
42
46
|
MapBuilder.of("registrationName", "onKeyboardMoveStart"),
|
|
43
|
-
|
|
47
|
+
KeyboardTransitionEvent.End.value,
|
|
44
48
|
MapBuilder.of("registrationName", "onKeyboardMoveEnd"),
|
|
45
|
-
|
|
49
|
+
KeyboardTransitionEvent.Interactive.value,
|
|
46
50
|
MapBuilder.of("registrationName", "onKeyboardMoveInteractive"),
|
|
47
|
-
|
|
51
|
+
FocusedInputLayoutChangedEvent.EVENT_NAME,
|
|
48
52
|
MapBuilder.of("registrationName", "onFocusedInputLayoutChanged"),
|
|
49
|
-
|
|
53
|
+
FocusedInputTextChangedEvent.EVENT_NAME,
|
|
50
54
|
MapBuilder.of("registrationName", "onFocusedInputTextChanged"),
|
|
51
|
-
|
|
55
|
+
FocusedInputSelectionChangedEvent.EVENT_NAME,
|
|
52
56
|
MapBuilder.of("registrationName", "onFocusedInputSelectionChanged"),
|
|
53
57
|
)
|
|
54
58
|
|
package/android/src/main/java/com/reactnativekeyboardcontroller/modal/ModalAttachedWatcher.kt
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.reactnativekeyboardcontroller.modal
|
|
2
2
|
|
|
3
|
+
import android.view.ViewGroup
|
|
3
4
|
import android.view.WindowManager
|
|
4
5
|
import androidx.core.view.ViewCompat
|
|
5
6
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
@@ -10,16 +11,20 @@ import com.facebook.react.uimanager.events.EventDispatcherListener
|
|
|
10
11
|
import com.facebook.react.views.modal.ReactModalHostView
|
|
11
12
|
import com.facebook.react.views.view.ReactViewGroup
|
|
12
13
|
import com.reactnativekeyboardcontroller.BuildConfig
|
|
14
|
+
import com.reactnativekeyboardcontroller.constants.Keyboard
|
|
15
|
+
import com.reactnativekeyboardcontroller.extensions.removeSelf
|
|
13
16
|
import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallback
|
|
14
17
|
import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallbackConfig
|
|
15
18
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
16
19
|
|
|
17
20
|
private val TAG = ModalAttachedWatcher::class.qualifiedName
|
|
21
|
+
private val areEventsComingFromOwnWindow = !Keyboard.IS_ANIMATION_EMULATED
|
|
18
22
|
|
|
19
23
|
class ModalAttachedWatcher(
|
|
20
24
|
private val view: ReactViewGroup,
|
|
21
25
|
private val reactContext: ThemedReactContext,
|
|
22
26
|
private val config: () -> KeyboardAnimationCallbackConfig,
|
|
27
|
+
private var callback: () -> KeyboardAnimationCallback?,
|
|
23
28
|
) : EventDispatcherListener {
|
|
24
29
|
private val archType = if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) UIManagerType.FABRIC else UIManagerType.DEFAULT
|
|
25
30
|
private val uiManager = UIManagerHelper.getUIManager(reactContext.reactApplicationContext, archType)
|
|
@@ -44,9 +49,13 @@ class ModalAttachedWatcher(
|
|
|
44
49
|
|
|
45
50
|
val dialog = modal.dialog
|
|
46
51
|
val window = dialog?.window
|
|
47
|
-
val rootView = window?.decorView?.rootView
|
|
52
|
+
val rootView = window?.decorView?.rootView as ViewGroup?
|
|
48
53
|
|
|
49
54
|
if (rootView != null) {
|
|
55
|
+
val eventView =
|
|
56
|
+
ReactViewGroup(reactContext).apply {
|
|
57
|
+
layoutParams = ViewGroup.LayoutParams(0, 0)
|
|
58
|
+
}
|
|
50
59
|
val callback =
|
|
51
60
|
KeyboardAnimationCallback(
|
|
52
61
|
view = rootView,
|
|
@@ -55,16 +64,35 @@ class ModalAttachedWatcher(
|
|
|
55
64
|
config = config(),
|
|
56
65
|
)
|
|
57
66
|
|
|
67
|
+
rootView.addView(eventView)
|
|
68
|
+
// on Android < 12 all events for `WindowInsetsAnimationCallback`
|
|
69
|
+
// go through main `rootView`, so we don't need to stop main
|
|
70
|
+
// callback - otherwise keyboard transitions will not be animated
|
|
71
|
+
this.callback()?.suspend(areEventsComingFromOwnWindow)
|
|
58
72
|
ViewCompat.setWindowInsetsAnimationCallback(rootView, callback)
|
|
59
|
-
ViewCompat.setOnApplyWindowInsetsListener(
|
|
73
|
+
ViewCompat.setOnApplyWindowInsetsListener(eventView, callback)
|
|
60
74
|
|
|
61
|
-
|
|
75
|
+
if (areEventsComingFromOwnWindow) {
|
|
76
|
+
// when modal is shown then keyboard will be hidden by default
|
|
77
|
+
//
|
|
78
|
+
// - if events are coming from main window - then keyboard position
|
|
79
|
+
// will be synchronized from main window callback
|
|
80
|
+
// - if events are coming from modal window - then we need to update
|
|
81
|
+
// position ourself, because callback can be attached after keyboard
|
|
82
|
+
// auto-dismissal and we may miss some events and keyboard position
|
|
83
|
+
// will be outdated
|
|
84
|
+
callback.syncKeyboardPosition(0.0, false)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
dialog?.setOnDismissListener {
|
|
62
88
|
callback.syncKeyboardPosition()
|
|
63
89
|
callback.destroy()
|
|
90
|
+
eventView.removeSelf()
|
|
91
|
+
this.callback()?.suspend(false)
|
|
64
92
|
}
|
|
65
93
|
|
|
66
94
|
// imitating edge-to-edge mode behavior
|
|
67
|
-
window
|
|
95
|
+
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
|
68
96
|
}
|
|
69
97
|
}
|
|
70
98
|
|
|
@@ -2,6 +2,7 @@ package com.reactnativekeyboardcontroller.modules
|
|
|
2
2
|
|
|
3
3
|
import android.animation.ArgbEvaluator
|
|
4
4
|
import android.animation.ValueAnimator
|
|
5
|
+
import android.app.Activity
|
|
5
6
|
import android.os.Build
|
|
6
7
|
import androidx.annotation.RequiresApi
|
|
7
8
|
import androidx.core.view.WindowInsetsCompat
|
|
@@ -11,6 +12,7 @@ import com.facebook.react.bridge.UiThreadUtil
|
|
|
11
12
|
import com.reactnativekeyboardcontroller.extensions.rootView
|
|
12
13
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
13
14
|
import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
|
|
15
|
+
import java.lang.ref.WeakReference
|
|
14
16
|
|
|
15
17
|
private val TAG = StatusBarManagerCompatModuleImpl::class.qualifiedName
|
|
16
18
|
|
|
@@ -18,6 +20,7 @@ class StatusBarManagerCompatModuleImpl(
|
|
|
18
20
|
private val mReactContext: ReactApplicationContext,
|
|
19
21
|
) {
|
|
20
22
|
private var controller: WindowInsetsControllerCompat? = null
|
|
23
|
+
private var lastActivity = WeakReference<Activity?>(null)
|
|
21
24
|
|
|
22
25
|
fun setHidden(hidden: Boolean) {
|
|
23
26
|
UiThreadUtil.runOnUiThread {
|
|
@@ -71,8 +74,9 @@ class StatusBarManagerCompatModuleImpl(
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
private fun getController(): WindowInsetsControllerCompat? {
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
val activity = mReactContext.currentActivity
|
|
78
|
+
|
|
79
|
+
if (this.controller == null || activity != lastActivity.get()) {
|
|
76
80
|
if (activity == null) {
|
|
77
81
|
Logger.w(
|
|
78
82
|
TAG,
|
|
@@ -82,6 +86,7 @@ class StatusBarManagerCompatModuleImpl(
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
val window = activity.window
|
|
89
|
+
lastActivity = WeakReference(activity)
|
|
85
90
|
|
|
86
91
|
this.controller = WindowInsetsControllerCompat(window, window.decorView)
|
|
87
92
|
}
|
package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt
CHANGED
|
@@ -47,7 +47,7 @@ class EdgeToEdgeReactViewGroup(
|
|
|
47
47
|
)
|
|
48
48
|
|
|
49
49
|
// managers/watchers
|
|
50
|
-
private val modalAttachedWatcher = ModalAttachedWatcher(this, reactContext, ::config)
|
|
50
|
+
private val modalAttachedWatcher = ModalAttachedWatcher(this, reactContext, ::config, ::getKeyboardCallback)
|
|
51
51
|
|
|
52
52
|
init {
|
|
53
53
|
reactContext.setupWindowDimensionsListener()
|
|
@@ -195,6 +195,10 @@ class EdgeToEdgeReactViewGroup(
|
|
|
195
195
|
}
|
|
196
196
|
// endregion
|
|
197
197
|
|
|
198
|
+
// region Helpers
|
|
199
|
+
private fun getKeyboardCallback(): KeyboardAnimationCallback? = this.callback
|
|
200
|
+
// endregion
|
|
201
|
+
|
|
198
202
|
// region Props setters
|
|
199
203
|
fun setStatusBarTranslucent(isStatusBarTranslucent: Boolean) {
|
|
200
204
|
this.isStatusBarTranslucent = isStatusBarTranslucent
|
|
@@ -10,7 +10,7 @@ import Foundation
|
|
|
10
10
|
import QuartzCore
|
|
11
11
|
|
|
12
12
|
// swiftlint:disable identifier_name
|
|
13
|
-
public class SpringAnimation: KeyboardAnimation {
|
|
13
|
+
public final class SpringAnimation: KeyboardAnimation {
|
|
14
14
|
// internal variables
|
|
15
15
|
private let zeta: Double // Damping ratio
|
|
16
16
|
private let omega0: Double // Undamped angular frequency of the oscillator
|
|
@@ -15,13 +15,13 @@ import QuartzCore
|
|
|
15
15
|
* This class calculates the progress of animations based on Bézier curve control points.
|
|
16
16
|
* For more details on the Bézier curves, see [Desmos Graph](https://www.desmos.com/calculator/eynenh1aga?lang=en).
|
|
17
17
|
*/
|
|
18
|
-
public class TimingAnimation: KeyboardAnimation {
|
|
18
|
+
public final class TimingAnimation: KeyboardAnimation {
|
|
19
19
|
private let p1: CGPoint
|
|
20
20
|
private let p2: CGPoint
|
|
21
21
|
|
|
22
22
|
init(animation: CABasicAnimation, fromValue: Double, toValue: Double) {
|
|
23
23
|
let timingFunction = animation.timingFunction
|
|
24
|
-
var controlPoints:
|
|
24
|
+
var controlPoints: ContiguousArray<Float> = ContiguousArray([0, 0, 0, 0])
|
|
25
25
|
timingFunction?.getControlPoint(at: 1, values: &controlPoints[0])
|
|
26
26
|
timingFunction?.getControlPoint(at: 2, values: &controlPoints[2])
|
|
27
27
|
let p1 = CGPoint(x: CGFloat(controlPoints[0]), y: CGFloat(controlPoints[1]))
|
|
@@ -33,7 +33,20 @@ public class TimingAnimation: KeyboardAnimation {
|
|
|
33
33
|
super.init(fromValue: fromValue, toValue: toValue, animation: animation)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
// public functions
|
|
37
|
+
override func valueAt(time: Double) -> Double {
|
|
38
|
+
let x = time * Double(speed)
|
|
39
|
+
let frames = (animation?.duration ?? 0.0) * Double(speed)
|
|
40
|
+
let fraction = min(x / frames, 1)
|
|
41
|
+
let t = findTForX(xTarget: fraction)
|
|
42
|
+
|
|
43
|
+
let progress = bezierY(t: t)
|
|
44
|
+
|
|
45
|
+
return fromValue + (toValue - fromValue) * CGFloat(progress)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// private functions
|
|
49
|
+
private func bezier(t: CGFloat, valueForPoint: (CGPoint) -> CGFloat) -> CGFloat {
|
|
37
50
|
let u = 1 - t
|
|
38
51
|
let tt = t * t
|
|
39
52
|
let uu = u * u
|
|
@@ -49,27 +62,15 @@ public class TimingAnimation: KeyboardAnimation {
|
|
|
49
62
|
return term1 + term2 + term3
|
|
50
63
|
}
|
|
51
64
|
|
|
52
|
-
func bezierY(t: CGFloat) -> CGFloat {
|
|
65
|
+
private func bezierY(t: CGFloat) -> CGFloat {
|
|
53
66
|
return bezier(t: t) { $0.y }
|
|
54
67
|
}
|
|
55
68
|
|
|
56
|
-
func bezierX(t: CGFloat) -> CGFloat {
|
|
69
|
+
private func bezierX(t: CGFloat) -> CGFloat {
|
|
57
70
|
return bezier(t: t) { $0.x }
|
|
58
71
|
}
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
override func valueAt(time: Double) -> Double {
|
|
62
|
-
let x = time * Double(speed)
|
|
63
|
-
let frames = (animation?.duration ?? 0.0) * Double(speed)
|
|
64
|
-
let fraction = min(x / frames, 1)
|
|
65
|
-
let t = findTForX(xTarget: fraction)
|
|
66
|
-
|
|
67
|
-
let progress = bezierY(t: t)
|
|
68
|
-
|
|
69
|
-
return fromValue + (toValue - fromValue) * CGFloat(progress)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
func findTForX(xTarget: CGFloat, epsilon: CGFloat = 0.0001, maxIterations: Int = 100) -> CGFloat {
|
|
73
|
+
private func findTForX(xTarget: CGFloat, epsilon: CGFloat = 0.0001, maxIterations: Int = 100) -> CGFloat {
|
|
73
74
|
var t: CGFloat = 0.5 // Start with an initial guess of t = 0.5
|
|
74
75
|
for _ in 0 ..< maxIterations {
|
|
75
76
|
let currentX = bezierX(t: t) // Compute the x-coordinate at t
|
|
@@ -84,7 +85,7 @@ public class TimingAnimation: KeyboardAnimation {
|
|
|
84
85
|
return t // Return the approximation of t
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
func bezierDerivative(t: CGFloat, valueForPoint: (CGPoint) -> CGFloat) -> CGFloat {
|
|
88
|
+
private func bezierDerivative(t: CGFloat, valueForPoint: (CGPoint) -> CGFloat) -> CGFloat {
|
|
88
89
|
let u = 1 - t
|
|
89
90
|
let uu = u * u
|
|
90
91
|
let tt = t * t
|
|
@@ -100,7 +101,7 @@ public class TimingAnimation: KeyboardAnimation {
|
|
|
100
101
|
return term1 + term2 + term3
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
func bezierXDerivative(t: CGFloat) -> CGFloat {
|
|
104
|
+
private func bezierXDerivative(t: CGFloat) -> CGFloat {
|
|
104
105
|
return bezierDerivative(t: t) { $0.x }
|
|
105
106
|
}
|
|
106
107
|
}
|
|
@@ -9,8 +9,24 @@ import Foundation
|
|
|
9
9
|
import UIKit
|
|
10
10
|
|
|
11
11
|
public extension UIApplication {
|
|
12
|
+
var activeWindow: UIWindow? {
|
|
13
|
+
if #available(iOS 13.0, *) {
|
|
14
|
+
for scene in connectedScenes {
|
|
15
|
+
if scene.activationState == .foregroundActive,
|
|
16
|
+
let windowScene = scene as? UIWindowScene,
|
|
17
|
+
let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow })
|
|
18
|
+
{
|
|
19
|
+
return keyWindow
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return nil
|
|
23
|
+
} else {
|
|
24
|
+
return windows.last { $0.isKeyWindow }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
12
28
|
static func topViewController(
|
|
13
|
-
base: UIViewController? = UIApplication.shared.
|
|
29
|
+
base: UIViewController? = UIApplication.shared.activeWindow?.rootViewController
|
|
14
30
|
) -> UIViewController? {
|
|
15
31
|
if let nav = base as? UINavigationController {
|
|
16
32
|
return topViewController(base: nav.visibleViewController)
|
|
@@ -11,9 +11,29 @@ import UIKit
|
|
|
11
11
|
|
|
12
12
|
public extension UIView {
|
|
13
13
|
var globalFrame: CGRect? {
|
|
14
|
-
let rootView = UIApplication.shared.
|
|
14
|
+
let rootView = UIApplication.shared.activeWindow?.rootViewController?.view
|
|
15
15
|
return superview?.convert(frame, to: rootView)
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
func isVisibleInHierarchy(initial: Bool = true) -> Bool {
|
|
19
|
+
guard let window = window else {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
if isHidden || alpha == 0.0 {
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
if superview === window {
|
|
26
|
+
return true
|
|
27
|
+
} else if let superview = superview {
|
|
28
|
+
if initial, frame.minY >= superview.frame.height {
|
|
29
|
+
return false
|
|
30
|
+
} else {
|
|
31
|
+
return superview.isVisibleInHierarchy(initial: false)
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
17
37
|
}
|
|
18
38
|
|
|
19
39
|
public extension Optional where Wrapped == UIView {
|
|
@@ -32,4 +52,11 @@ public extension Optional where Wrapped == UIView {
|
|
|
32
52
|
|
|
33
53
|
return (position, frameY)
|
|
34
54
|
}
|
|
55
|
+
|
|
56
|
+
func isVisibleInHierarchy(initial: Bool = true) -> Bool {
|
|
57
|
+
guard let view = self else {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
return view.isVisibleInHierarchy(initial: initial)
|
|
61
|
+
}
|
|
35
62
|
}
|
|
@@ -37,8 +37,11 @@ public extension UIWindow {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
func getTopWindow() -> UIWindow? {
|
|
40
|
-
|
|
41
|
-
return
|
|
40
|
+
let keyboardView = KeyboardView.find()
|
|
41
|
+
// return the keyboard window if it's available and keyboard is visible, otherwise return the last window
|
|
42
|
+
return (keyboardWindow != nil && keyboardView.isVisibleInHierarchy())
|
|
43
|
+
? keyboardWindow
|
|
44
|
+
: UIApplication.shared.activeWindow
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
|
|
@@ -204,10 +204,10 @@ public class FocusedInputObserver: NSObject {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
private func substituteDelegateBack(_ input: UIResponder?) {
|
|
207
|
-
if let textField = input as? UITextField {
|
|
208
|
-
textField.delegate =
|
|
209
|
-
} else if let textView = input as? UITextView {
|
|
210
|
-
(textView as? RCTUITextView)?.setForceDelegate(
|
|
207
|
+
if let textField = input as? UITextField, let oldDelegate = delegate.activeDelegate as? UITextFieldDelegate {
|
|
208
|
+
textField.delegate = oldDelegate
|
|
209
|
+
} else if let textView = input as? UITextView, let oldDelegate = delegate.activeDelegate as? UITextViewDelegate {
|
|
210
|
+
(textView as? RCTUITextView)?.setForceDelegate(oldDelegate)
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -102,10 +102,27 @@ RCT_EXPORT_VIEW_PROPERTY(visible, BOOL)
|
|
|
102
102
|
_touchHandler = [[RCTTouchHandler alloc] initWithBridge:bridge];
|
|
103
103
|
_contentView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
104
104
|
}
|
|
105
|
+
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
106
|
+
selector:@selector(hide)
|
|
107
|
+
name:RCTJavaScriptWillStartLoadingNotification
|
|
108
|
+
object:nil];
|
|
105
109
|
return self;
|
|
106
110
|
}
|
|
107
111
|
#endif
|
|
108
112
|
|
|
113
|
+
- (void)dealloc
|
|
114
|
+
{
|
|
115
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// MARK: lifecycle methods
|
|
119
|
+
- (void)didMoveToSuperview
|
|
120
|
+
{
|
|
121
|
+
if (self.superview == nil) {
|
|
122
|
+
[self hide];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
109
126
|
// MARK: touch handling
|
|
110
127
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
111
128
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNativeReanimated","require","_context","_hooks","useKeyboardAnimation","reanimated","useKeyboardContext","heightWhenOpened","useSharedValue","height","value","progress","isClosed","useKeyboardHandler","onStart","e","onMove","onEnd","exports"],"sources":["hooks.ts"],"sourcesContent":["import { useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardContext } from \"../../context\";\nimport { useKeyboardHandler } from \"../../hooks\";\n\nexport const useKeyboardAnimation = () => {\n const { reanimated } = useKeyboardContext();\n const heightWhenOpened = useSharedValue(-reanimated.height.value);\n const height = useSharedValue(-reanimated.height.value);\n const progress = useSharedValue(reanimated.progress.value);\n const isClosed = useSharedValue(reanimated.progress.value === 0);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\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 height.value = e.height;\n progress.value = e.progress;\n },\n },\n [],\n );\n\n return { height, progress, heightWhenOpened, isClosed };\n};\n"],"mappings":";;;;;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAEO,MAAMG,oBAAoB,GAAGA,CAAA,KAAM;EACxC,MAAM;IAAEC;EAAW,CAAC,GAAG,IAAAC,2BAAkB,EAAC,CAAC;EAC3C,MAAMC,gBAAgB,GAAG,IAAAC,qCAAc,EAAC,CAACH,UAAU,CAACI,MAAM,CAACC,KAAK,CAAC;EACjE,MAAMD,MAAM,GAAG,IAAAD,qCAAc,EAAC,CAACH,UAAU,CAACI,MAAM,CAACC,KAAK,CAAC;EACvD,MAAMC,QAAQ,GAAG,IAAAH,qCAAc,EAACH,UAAU,CAACM,QAAQ,CAACD,KAAK,CAAC;EAC1D,MAAME,QAAQ,GAAG,IAAAJ,qCAAc,EAACH,UAAU,CAACM,QAAQ,CAACD,KAAK,KAAK,CAAC,CAAC;EAEhE,IAAAG,yBAAkB,EAChB;IACEC,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACN,MAAM,GAAG,CAAC,EAAE;QAChB;QACAG,QAAQ,CAACF,KAAK,GAAG,KAAK;QACtBH,gBAAgB,CAACG,KAAK,GAAGK,CAAC,CAACN,MAAM;MACnC;IACF,CAAC;IACDO,MAAM,EAAGD,CAAC,IAAK;MACb,SAAS;;MAETJ,QAAQ,CAACD,KAAK,GAAGK,CAAC,CAACJ,QAAQ;MAC3BF,MAAM,CAACC,KAAK,GAAGK,CAAC,CAACN,MAAM;IACzB,CAAC;IACDQ,
|
|
1
|
+
{"version":3,"names":["_reactNativeReanimated","require","_context","_hooks","useKeyboardAnimation","reanimated","useKeyboardContext","heightWhenOpened","useSharedValue","height","value","progress","isClosed","useKeyboardHandler","onStart","e","onMove","onInteractive","onEnd","exports"],"sources":["hooks.ts"],"sourcesContent":["import { useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardContext } from \"../../context\";\nimport { useKeyboardHandler } from \"../../hooks\";\n\nexport const useKeyboardAnimation = () => {\n const { reanimated } = useKeyboardContext();\n const heightWhenOpened = useSharedValue(-reanimated.height.value);\n const height = useSharedValue(-reanimated.height.value);\n const progress = useSharedValue(reanimated.progress.value);\n const isClosed = useSharedValue(reanimated.progress.value === 0);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\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 onInteractive: (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 height.value = e.height;\n progress.value = e.progress;\n },\n },\n [],\n );\n\n return { height, progress, heightWhenOpened, isClosed };\n};\n"],"mappings":";;;;;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAEO,MAAMG,oBAAoB,GAAGA,CAAA,KAAM;EACxC,MAAM;IAAEC;EAAW,CAAC,GAAG,IAAAC,2BAAkB,EAAC,CAAC;EAC3C,MAAMC,gBAAgB,GAAG,IAAAC,qCAAc,EAAC,CAACH,UAAU,CAACI,MAAM,CAACC,KAAK,CAAC;EACjE,MAAMD,MAAM,GAAG,IAAAD,qCAAc,EAAC,CAACH,UAAU,CAACI,MAAM,CAACC,KAAK,CAAC;EACvD,MAAMC,QAAQ,GAAG,IAAAH,qCAAc,EAACH,UAAU,CAACM,QAAQ,CAACD,KAAK,CAAC;EAC1D,MAAME,QAAQ,GAAG,IAAAJ,qCAAc,EAACH,UAAU,CAACM,QAAQ,CAACD,KAAK,KAAK,CAAC,CAAC;EAEhE,IAAAG,yBAAkB,EAChB;IACEC,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACN,MAAM,GAAG,CAAC,EAAE;QAChB;QACAG,QAAQ,CAACF,KAAK,GAAG,KAAK;QACtBH,gBAAgB,CAACG,KAAK,GAAGK,CAAC,CAACN,MAAM;MACnC;IACF,CAAC;IACDO,MAAM,EAAGD,CAAC,IAAK;MACb,SAAS;;MAETJ,QAAQ,CAACD,KAAK,GAAGK,CAAC,CAACJ,QAAQ;MAC3BF,MAAM,CAACC,KAAK,GAAGK,CAAC,CAACN,MAAM;IACzB,CAAC;IACDQ,aAAa,EAAGF,CAAC,IAAK;MACpB,SAAS;;MAETJ,QAAQ,CAACD,KAAK,GAAGK,CAAC,CAACJ,QAAQ;MAC3BF,MAAM,CAACC,KAAK,GAAGK,CAAC,CAACN,MAAM;IACzB,CAAC;IACDS,KAAK,EAAGH,CAAC,IAAK;MACZ,SAAS;;MAETH,QAAQ,CAACF,KAAK,GAAGK,CAAC,CAACN,MAAM,KAAK,CAAC;MAE/BA,MAAM,CAACC,KAAK,GAAGK,CAAC,CAACN,MAAM;MACvBE,QAAQ,CAACD,KAAK,GAAGK,CAAC,CAACJ,QAAQ;IAC7B;EACF,CAAC,EACD,EACF,CAAC;EAED,OAAO;IAAEF,MAAM;IAAEE,QAAQ;IAAEJ,gBAAgB;IAAEK;EAAS,CAAC;AACzD,CAAC;AAACO,OAAA,CAAAf,oBAAA,GAAAA,oBAAA","ignoreList":[]}
|
|
@@ -25,6 +25,12 @@ export const useKeyboardAnimation = () => {
|
|
|
25
25
|
progress.value = e.progress;
|
|
26
26
|
height.value = e.height;
|
|
27
27
|
},
|
|
28
|
+
onInteractive: e => {
|
|
29
|
+
"worklet";
|
|
30
|
+
|
|
31
|
+
progress.value = e.progress;
|
|
32
|
+
height.value = e.height;
|
|
33
|
+
},
|
|
28
34
|
onEnd: e => {
|
|
29
35
|
"worklet";
|
|
30
36
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useSharedValue","useKeyboardContext","useKeyboardHandler","useKeyboardAnimation","reanimated","heightWhenOpened","height","value","progress","isClosed","onStart","e","onMove","onEnd"],"sources":["hooks.ts"],"sourcesContent":["import { useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardContext } from \"../../context\";\nimport { useKeyboardHandler } from \"../../hooks\";\n\nexport const useKeyboardAnimation = () => {\n const { reanimated } = useKeyboardContext();\n const heightWhenOpened = useSharedValue(-reanimated.height.value);\n const height = useSharedValue(-reanimated.height.value);\n const progress = useSharedValue(reanimated.progress.value);\n const isClosed = useSharedValue(reanimated.progress.value === 0);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\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 height.value = e.height;\n progress.value = e.progress;\n },\n },\n [],\n );\n\n return { height, progress, heightWhenOpened, isClosed };\n};\n"],"mappings":"AAAA,SAASA,cAAc,QAAQ,yBAAyB;AAExD,SAASC,kBAAkB,QAAQ,eAAe;AAClD,SAASC,kBAAkB,QAAQ,aAAa;AAEhD,OAAO,MAAMC,oBAAoB,GAAGA,CAAA,KAAM;EACxC,MAAM;IAAEC;EAAW,CAAC,GAAGH,kBAAkB,CAAC,CAAC;EAC3C,MAAMI,gBAAgB,GAAGL,cAAc,CAAC,CAACI,UAAU,CAACE,MAAM,CAACC,KAAK,CAAC;EACjE,MAAMD,MAAM,GAAGN,cAAc,CAAC,CAACI,UAAU,CAACE,MAAM,CAACC,KAAK,CAAC;EACvD,MAAMC,QAAQ,GAAGR,cAAc,CAACI,UAAU,CAACI,QAAQ,CAACD,KAAK,CAAC;EAC1D,MAAME,QAAQ,GAAGT,cAAc,CAACI,UAAU,CAACI,QAAQ,CAACD,KAAK,KAAK,CAAC,CAAC;EAEhEL,kBAAkB,CAChB;IACEQ,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACL,MAAM,GAAG,CAAC,EAAE;QAChB;QACAG,QAAQ,CAACF,KAAK,GAAG,KAAK;QACtBF,gBAAgB,CAACE,KAAK,GAAGI,CAAC,CAACL,MAAM;MACnC;IACF,CAAC;IACDM,MAAM,EAAGD,CAAC,IAAK;MACb,SAAS;;MAETH,QAAQ,CAACD,KAAK,GAAGI,CAAC,CAACH,QAAQ;MAC3BF,MAAM,CAACC,KAAK,GAAGI,CAAC,CAACL,MAAM;IACzB,CAAC;IACDO,
|
|
1
|
+
{"version":3,"names":["useSharedValue","useKeyboardContext","useKeyboardHandler","useKeyboardAnimation","reanimated","heightWhenOpened","height","value","progress","isClosed","onStart","e","onMove","onInteractive","onEnd"],"sources":["hooks.ts"],"sourcesContent":["import { useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardContext } from \"../../context\";\nimport { useKeyboardHandler } from \"../../hooks\";\n\nexport const useKeyboardAnimation = () => {\n const { reanimated } = useKeyboardContext();\n const heightWhenOpened = useSharedValue(-reanimated.height.value);\n const height = useSharedValue(-reanimated.height.value);\n const progress = useSharedValue(reanimated.progress.value);\n const isClosed = useSharedValue(reanimated.progress.value === 0);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\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 onInteractive: (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 height.value = e.height;\n progress.value = e.progress;\n },\n },\n [],\n );\n\n return { height, progress, heightWhenOpened, isClosed };\n};\n"],"mappings":"AAAA,SAASA,cAAc,QAAQ,yBAAyB;AAExD,SAASC,kBAAkB,QAAQ,eAAe;AAClD,SAASC,kBAAkB,QAAQ,aAAa;AAEhD,OAAO,MAAMC,oBAAoB,GAAGA,CAAA,KAAM;EACxC,MAAM;IAAEC;EAAW,CAAC,GAAGH,kBAAkB,CAAC,CAAC;EAC3C,MAAMI,gBAAgB,GAAGL,cAAc,CAAC,CAACI,UAAU,CAACE,MAAM,CAACC,KAAK,CAAC;EACjE,MAAMD,MAAM,GAAGN,cAAc,CAAC,CAACI,UAAU,CAACE,MAAM,CAACC,KAAK,CAAC;EACvD,MAAMC,QAAQ,GAAGR,cAAc,CAACI,UAAU,CAACI,QAAQ,CAACD,KAAK,CAAC;EAC1D,MAAME,QAAQ,GAAGT,cAAc,CAACI,UAAU,CAACI,QAAQ,CAACD,KAAK,KAAK,CAAC,CAAC;EAEhEL,kBAAkB,CAChB;IACEQ,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACL,MAAM,GAAG,CAAC,EAAE;QAChB;QACAG,QAAQ,CAACF,KAAK,GAAG,KAAK;QACtBF,gBAAgB,CAACE,KAAK,GAAGI,CAAC,CAACL,MAAM;MACnC;IACF,CAAC;IACDM,MAAM,EAAGD,CAAC,IAAK;MACb,SAAS;;MAETH,QAAQ,CAACD,KAAK,GAAGI,CAAC,CAACH,QAAQ;MAC3BF,MAAM,CAACC,KAAK,GAAGI,CAAC,CAACL,MAAM;IACzB,CAAC;IACDO,aAAa,EAAGF,CAAC,IAAK;MACpB,SAAS;;MAETH,QAAQ,CAACD,KAAK,GAAGI,CAAC,CAACH,QAAQ;MAC3BF,MAAM,CAACC,KAAK,GAAGI,CAAC,CAACL,MAAM;IACzB,CAAC;IACDQ,KAAK,EAAGH,CAAC,IAAK;MACZ,SAAS;;MAETF,QAAQ,CAACF,KAAK,GAAGI,CAAC,CAACL,MAAM,KAAK,CAAC;MAE/BA,MAAM,CAACC,KAAK,GAAGI,CAAC,CAACL,MAAM;MACvBE,QAAQ,CAACD,KAAK,GAAGI,CAAC,CAACH,QAAQ;IAC7B;EACF,CAAC,EACD,EACF,CAAC;EAED,OAAO;IAAEF,MAAM;IAAEE,QAAQ;IAAEH,gBAAgB;IAAEI;EAAS,CAAC;AACzD,CAAC","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -27,6 +27,12 @@ export const useKeyboardAnimation = () => {
|
|
|
27
27
|
progress.value = e.progress;
|
|
28
28
|
height.value = e.height;
|
|
29
29
|
},
|
|
30
|
+
onInteractive: (e) => {
|
|
31
|
+
"worklet";
|
|
32
|
+
|
|
33
|
+
progress.value = e.progress;
|
|
34
|
+
height.value = e.height;
|
|
35
|
+
},
|
|
30
36
|
onEnd: (e) => {
|
|
31
37
|
"worklet";
|
|
32
38
|
|