react-native-keyboard-controller 1.21.4 → 1.21.6
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/extensions/ReactContext.kt +10 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/View.kt +0 -40
- package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +3 -11
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/ClippingScrollViewDecoratorView.kt +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +19 -22
- package/lib/commonjs/components/KeyboardChatScrollView/index.js +3 -2
- package/lib/commonjs/components/KeyboardChatScrollView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardChatScrollView/types.js.map +1 -1
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +3 -3
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -1
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js +4 -4
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -1
- package/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js +2 -2
- package/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardToolbar/index.js +12 -3
- package/lib/commonjs/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js +1 -10
- package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js.map +1 -1
- package/lib/commonjs/hooks/useKeyboardState/index.js +1 -7
- package/lib/commonjs/hooks/useKeyboardState/index.js.map +1 -1
- package/lib/commonjs/module.js +1 -1
- package/lib/commonjs/module.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/index.js +3 -2
- package/lib/module/components/KeyboardChatScrollView/index.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/types.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +3 -3
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js +4 -4
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -1
- package/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js +2 -2
- package/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js.map +1 -1
- package/lib/module/components/KeyboardToolbar/index.js +12 -3
- package/lib/module/components/KeyboardToolbar/index.js.map +1 -1
- package/lib/module/components/ScrollViewWithBottomPadding/index.js +2 -11
- package/lib/module/components/ScrollViewWithBottomPadding/index.js.map +1 -1
- package/lib/module/hooks/useKeyboardState/index.js +1 -7
- package/lib/module/hooks/useKeyboardState/index.js.map +1 -1
- package/lib/module/module.js +1 -1
- package/lib/module/module.js.map +1 -1
- package/lib/typescript/components/KeyboardChatScrollView/index.d.ts +1 -1
- package/lib/typescript/components/KeyboardChatScrollView/types.d.ts +1 -1
- package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts +1 -1
- package/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/KeyboardChatScrollView/index.tsx +5 -2
- package/src/components/KeyboardChatScrollView/types.ts +1 -1
- package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts +3 -3
- package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ts +4 -4
- package/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts +1 -1
- package/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts +3 -3
- package/src/components/KeyboardToolbar/index.tsx +13 -4
- package/src/components/ScrollViewWithBottomPadding/index.tsx +2 -12
- package/src/hooks/useKeyboardState/index.ts +1 -8
- package/src/module.ts +1 -1
|
@@ -2,6 +2,7 @@ package com.reactnativekeyboardcontroller.extensions
|
|
|
2
2
|
|
|
3
3
|
import android.view.View
|
|
4
4
|
import android.view.ViewGroup
|
|
5
|
+
import android.view.WindowManager
|
|
5
6
|
import com.facebook.react.bridge.ReactContext
|
|
6
7
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
7
8
|
import com.facebook.react.uimanager.common.UIManagerType
|
|
@@ -28,3 +29,12 @@ val ReactContext.content: ViewGroup?
|
|
|
28
29
|
this.currentActivity?.window?.decorView?.rootView?.findViewById(
|
|
29
30
|
androidx.appcompat.R.id.action_bar_root,
|
|
30
31
|
)
|
|
32
|
+
|
|
33
|
+
val ReactContext.windowSoftInputMode: Int
|
|
34
|
+
get() =
|
|
35
|
+
this
|
|
36
|
+
.currentActivity
|
|
37
|
+
?.window
|
|
38
|
+
?.attributes
|
|
39
|
+
?.softInputMode
|
|
40
|
+
?: WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
|
|
@@ -4,9 +4,7 @@ import android.annotation.SuppressLint
|
|
|
4
4
|
import android.graphics.Rect
|
|
5
5
|
import android.os.Build
|
|
6
6
|
import android.view.View
|
|
7
|
-
import androidx.core.graphics.Insets
|
|
8
7
|
import androidx.core.view.ViewCompat
|
|
9
|
-
import androidx.core.view.WindowInsetsCompat
|
|
10
8
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
11
9
|
|
|
12
10
|
/**
|
|
@@ -61,41 +59,3 @@ val View.screenLocation get(): IntArray {
|
|
|
61
59
|
|
|
62
60
|
return point
|
|
63
61
|
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Safely replaces status bar insets so that when we edge-to-edge mode gets disabled/enabled
|
|
67
|
-
* the app content is not jumping/resizing a window.
|
|
68
|
-
* */
|
|
69
|
-
@Suppress("DEPRECATION")
|
|
70
|
-
fun View.replaceStatusBarInsets(
|
|
71
|
-
insets: WindowInsetsCompat,
|
|
72
|
-
isStatusBarTranslucent: Boolean,
|
|
73
|
-
active: Boolean,
|
|
74
|
-
): WindowInsetsCompat {
|
|
75
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
76
|
-
val sysBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
77
|
-
val navBars = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
|
|
78
|
-
val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
|
|
79
|
-
val adjustedTop = if (isStatusBarTranslucent) 0 else sysBars.top
|
|
80
|
-
// pick bottom: use IME if present, otherwise nav bar bottom (respect translucency)
|
|
81
|
-
val bottomFromImeOrNav = if (ime.bottom > 0) ime.bottom else navBars.bottom
|
|
82
|
-
val adjustedInsets =
|
|
83
|
-
WindowInsetsCompat
|
|
84
|
-
.Builder(insets)
|
|
85
|
-
.setInsets(
|
|
86
|
-
WindowInsetsCompat.Type.systemBars(),
|
|
87
|
-
Insets.of(sysBars.left, adjustedTop, sysBars.right, if (active) sysBars.bottom else bottomFromImeOrNav),
|
|
88
|
-
).build()
|
|
89
|
-
|
|
90
|
-
return ViewCompat.onApplyWindowInsets(this, adjustedInsets)
|
|
91
|
-
} else {
|
|
92
|
-
val defaultInsets = ViewCompat.onApplyWindowInsets(this, insets)
|
|
93
|
-
|
|
94
|
-
return defaultInsets.replaceSystemWindowInsets(
|
|
95
|
-
defaultInsets.systemWindowInsetLeft,
|
|
96
|
-
if (isStatusBarTranslucent) 0 else defaultInsets.systemWindowInsetTop,
|
|
97
|
-
defaultInsets.systemWindowInsetRight,
|
|
98
|
-
defaultInsets.systemWindowInsetBottom,
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -3,7 +3,6 @@ package com.reactnativekeyboardcontroller.modules
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.os.Build
|
|
5
5
|
import android.view.View
|
|
6
|
-
import android.view.WindowManager
|
|
7
6
|
import android.view.inputmethod.InputMethodManager
|
|
8
7
|
import com.facebook.react.bridge.Arguments
|
|
9
8
|
import com.facebook.react.bridge.Promise
|
|
@@ -12,6 +11,7 @@ import com.facebook.react.bridge.UiThreadUtil
|
|
|
12
11
|
import com.reactnativekeyboardcontroller.extensions.dp
|
|
13
12
|
import com.reactnativekeyboardcontroller.extensions.screenLocation
|
|
14
13
|
import com.reactnativekeyboardcontroller.extensions.uiManager
|
|
14
|
+
import com.reactnativekeyboardcontroller.extensions.windowSoftInputMode
|
|
15
15
|
import com.reactnativekeyboardcontroller.interactive.KeyboardAnimationController
|
|
16
16
|
import com.reactnativekeyboardcontroller.traversal.FocusedInputHolder
|
|
17
17
|
import com.reactnativekeyboardcontroller.traversal.ViewHierarchyNavigator
|
|
@@ -21,7 +21,7 @@ class KeyboardControllerModuleImpl(
|
|
|
21
21
|
) {
|
|
22
22
|
private val uiManager = mReactContext.uiManager
|
|
23
23
|
private val controller = KeyboardAnimationController()
|
|
24
|
-
private val mDefaultMode: Int =
|
|
24
|
+
private val mDefaultMode: Int = mReactContext.windowSoftInputMode
|
|
25
25
|
|
|
26
26
|
// region Module methods
|
|
27
27
|
fun setInputMode(mode: Int) {
|
|
@@ -108,19 +108,11 @@ class KeyboardControllerModuleImpl(
|
|
|
108
108
|
// region Helpers
|
|
109
109
|
private fun setSoftInputMode(mode: Int) {
|
|
110
110
|
UiThreadUtil.runOnUiThread {
|
|
111
|
-
if (
|
|
111
|
+
if (mReactContext.windowSoftInputMode != mode) {
|
|
112
112
|
mReactContext.currentActivity?.window?.setSoftInputMode(mode)
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
|
|
117
|
-
private fun getCurrentMode(): Int =
|
|
118
|
-
mReactContext
|
|
119
|
-
.currentActivity
|
|
120
|
-
?.window
|
|
121
|
-
?.attributes
|
|
122
|
-
?.softInputMode
|
|
123
|
-
?: WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
|
|
124
116
|
// endregion
|
|
125
117
|
|
|
126
118
|
// region Module constants
|
|
@@ -48,7 +48,7 @@ class ClippingScrollViewDecoratorView(
|
|
|
48
48
|
// virtualizer calculations correct (it reads layout positions,
|
|
49
49
|
// not translationY).
|
|
50
50
|
val contentView = scrollView.getChildAt(0) as? ViewGroup ?: return
|
|
51
|
-
|
|
51
|
+
contentView.translationY = newTopInsetPx.toFloat()
|
|
52
52
|
|
|
53
53
|
scrollView.setPadding(
|
|
54
54
|
scrollView.paddingLeft,
|
package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt
CHANGED
|
@@ -5,6 +5,7 @@ import android.content.res.Configuration
|
|
|
5
5
|
import android.os.Handler
|
|
6
6
|
import android.os.Looper
|
|
7
7
|
import android.view.WindowManager
|
|
8
|
+
import android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
|
8
9
|
import android.widget.FrameLayout
|
|
9
10
|
import androidx.core.view.ViewCompat
|
|
10
11
|
import androidx.core.view.WindowCompat
|
|
@@ -14,14 +15,15 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
|
14
15
|
import com.facebook.react.views.view.ReactViewGroup
|
|
15
16
|
import com.reactnativekeyboardcontroller.extensions.content
|
|
16
17
|
import com.reactnativekeyboardcontroller.extensions.removeSelf
|
|
17
|
-
import com.reactnativekeyboardcontroller.extensions.replaceStatusBarInsets
|
|
18
18
|
import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached
|
|
19
19
|
import com.reactnativekeyboardcontroller.extensions.rootView
|
|
20
|
+
import com.reactnativekeyboardcontroller.extensions.windowSoftInputMode
|
|
20
21
|
import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallback
|
|
21
22
|
import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallbackConfig
|
|
22
23
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
23
24
|
import com.reactnativekeyboardcontroller.modal.ModalAttachedWatcher
|
|
24
25
|
import java.lang.ref.WeakReference
|
|
26
|
+
import kotlin.math.max
|
|
25
27
|
|
|
26
28
|
private val TAG = EdgeToEdgeReactViewGroup::class.qualifiedName
|
|
27
29
|
|
|
@@ -44,7 +46,6 @@ class EdgeToEdgeReactViewGroup(
|
|
|
44
46
|
private var isStatusBarTranslucent = false
|
|
45
47
|
private var isNavigationBarTranslucent = false
|
|
46
48
|
private var isPreservingEdgeToEdge = false
|
|
47
|
-
private var isEdgeToEdge = false
|
|
48
49
|
var active: Boolean = false
|
|
49
50
|
set(value) {
|
|
50
51
|
field = value
|
|
@@ -110,47 +111,43 @@ class EdgeToEdgeReactViewGroup(
|
|
|
110
111
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
111
112
|
)
|
|
112
113
|
|
|
113
|
-
val
|
|
114
|
-
|
|
114
|
+
val shouldApplyBottomPadding =
|
|
115
|
+
!active && reactContext.windowSoftInputMode == SOFT_INPUT_ADJUST_RESIZE && !isPreservingEdgeToEdge
|
|
115
116
|
val navBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
|
|
116
117
|
val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
118
|
+
val keyboardInsets =
|
|
119
|
+
if (!shouldApplyBottomPadding) 0 else insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
|
117
120
|
|
|
118
121
|
params.setMargins(
|
|
119
122
|
navBarInsets.left,
|
|
120
|
-
if (
|
|
123
|
+
if (this.isStatusBarTranslucent) {
|
|
121
124
|
0
|
|
122
125
|
} else {
|
|
123
126
|
systemBarInsets.top
|
|
124
127
|
},
|
|
125
128
|
navBarInsets.right,
|
|
126
|
-
if (
|
|
127
|
-
|
|
129
|
+
if (this.isNavigationBarTranslucent) {
|
|
130
|
+
keyboardInsets
|
|
128
131
|
} else {
|
|
129
|
-
navBarInsets.bottom
|
|
132
|
+
max(navBarInsets.bottom, keyboardInsets)
|
|
130
133
|
},
|
|
131
134
|
)
|
|
132
135
|
content?.layoutParams = params
|
|
133
136
|
|
|
134
|
-
|
|
137
|
+
ViewCompat.onApplyWindowInsets(v, insets)
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
fun setEdgeToEdge() {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
reactContext.currentActivity?.let {
|
|
146
|
-
WindowCompat.setDecorFitsSystemWindows(
|
|
147
|
-
it.window,
|
|
148
|
-
!isEdgeToEdge,
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
// unclear legacy flag if it was set earlier
|
|
152
|
-
reactContext.currentActivity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
143
|
+
reactContext.currentActivity?.let {
|
|
144
|
+
WindowCompat.setDecorFitsSystemWindows(
|
|
145
|
+
it.window,
|
|
146
|
+
false,
|
|
147
|
+
)
|
|
153
148
|
}
|
|
149
|
+
// unclear legacy flag if it was set earlier
|
|
150
|
+
reactContext.currentActivity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
154
151
|
}
|
|
155
152
|
|
|
156
153
|
private fun setupKeyboardCallbacks() {
|
|
@@ -32,6 +32,7 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
32
32
|
}, ref) => {
|
|
33
33
|
const scrollViewRef = (0, _reactNativeReanimated.useAnimatedRef)();
|
|
34
34
|
const onRef = (0, _useCombinedRef.default)(ref, scrollViewRef);
|
|
35
|
+
const freezeSV = (0, _reactNativeReanimated.useDerivedValue)(() => typeof freeze === "boolean" ? freeze : freeze.value);
|
|
35
36
|
const {
|
|
36
37
|
padding,
|
|
37
38
|
currentHeight,
|
|
@@ -44,7 +45,7 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
44
45
|
} = (0, _useChatKeyboard.useChatKeyboard)(scrollViewRef, {
|
|
45
46
|
inverted,
|
|
46
47
|
keyboardLiftBehavior,
|
|
47
|
-
freeze,
|
|
48
|
+
freeze: freezeSV,
|
|
48
49
|
offset,
|
|
49
50
|
blankSpace,
|
|
50
51
|
extraContentPadding
|
|
@@ -60,7 +61,7 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
60
61
|
contentOffsetY,
|
|
61
62
|
inverted,
|
|
62
63
|
keyboardLiftBehavior,
|
|
63
|
-
freeze
|
|
64
|
+
freeze: freezeSV
|
|
64
65
|
});
|
|
65
66
|
const totalPadding = (0, _reactNativeReanimated.useDerivedValue)(() => Math.max(blankSpace.value, padding.value + extraContentPadding.value));
|
|
66
67
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_useCombinedRef","_interopRequireDefault","_ScrollViewWithBottomPadding","_useChatKeyboard","_useExtraContentPadding","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","ZERO_CONTENT_PADDING","makeMutable","ZERO_BLANK_SPACE","KeyboardChatScrollView","forwardRef","children","ScrollViewComponent","Reanimated","ScrollView","inverted","keyboardLiftBehavior","freeze","offset","extraContentPadding","blankSpace","applyWorkaroundForContentInsetHitTestBug","onLayout","onLayoutProp","onContentSizeChange","onContentSizeChangeProp","rest","ref","scrollViewRef","useAnimatedRef","onRef","useCombinedRef","padding","currentHeight","contentOffsetY","scroll","layout","size","onLayoutInternal","onContentSizeChangeInternal","useChatKeyboard","useExtraContentPadding","keyboardPadding","totalPadding","useDerivedValue","Math","max","value","indicatorPadding","useCallback","w","h","commitStyle","useAnimatedStyle","transform","translateY","commit","useMemo","styles","commitView","createElement","Fragment","bottomPadding","scrollIndicatorPadding","View","style","StyleSheet","create","display","position","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport {\n makeMutable,\n useAnimatedRef,\n useAnimatedStyle,\n useDerivedValue,\n} from \"react-native-reanimated\";\nimport Reanimated from \"react-native-reanimated\";\n\nimport useCombinedRef from \"../hooks/useCombinedRef\";\nimport ScrollViewWithBottomPadding from \"../ScrollViewWithBottomPadding\";\n\nimport { useChatKeyboard } from \"./useChatKeyboard\";\nimport { useExtraContentPadding } from \"./useExtraContentPadding\";\n\nimport type { KeyboardChatScrollViewProps } from \"./types\";\nimport type { LayoutChangeEvent } from \"react-native\";\n\nconst ZERO_CONTENT_PADDING = makeMutable(0);\nconst ZERO_BLANK_SPACE = makeMutable(0);\n\nconst KeyboardChatScrollView = forwardRef<\n Reanimated.ScrollView,\n React.PropsWithChildren<KeyboardChatScrollViewProps>\n>(\n (\n {\n children,\n ScrollViewComponent = Reanimated.ScrollView,\n inverted = false,\n keyboardLiftBehavior = \"always\",\n freeze = false,\n offset = 0,\n extraContentPadding = ZERO_CONTENT_PADDING,\n blankSpace = ZERO_BLANK_SPACE,\n applyWorkaroundForContentInsetHitTestBug = false,\n onLayout: onLayoutProp,\n onContentSizeChange: onContentSizeChangeProp,\n ...rest\n },\n ref,\n ) => {\n const scrollViewRef = useAnimatedRef<Reanimated.ScrollView>();\n const onRef = useCombinedRef(ref, scrollViewRef);\n const {\n padding,\n currentHeight,\n contentOffsetY,\n scroll,\n layout,\n size,\n onLayout: onLayoutInternal,\n onContentSizeChange: onContentSizeChangeInternal,\n } = useChatKeyboard(scrollViewRef, {\n inverted,\n keyboardLiftBehavior,\n freeze,\n offset,\n blankSpace,\n extraContentPadding,\n });\n\n useExtraContentPadding({\n scrollViewRef,\n extraContentPadding,\n keyboardPadding: padding,\n blankSpace,\n scroll,\n layout,\n size,\n contentOffsetY,\n inverted,\n keyboardLiftBehavior,\n freeze,\n });\n\n const totalPadding = useDerivedValue(() =>\n Math.max(blankSpace.value, padding.value + extraContentPadding.value),\n );\n\n // Scroll indicator inset = keyboard + extraContentPadding (excludes blankSpace).\n // Apps that render into the unsafe area can supply a negative\n // scrollIndicatorInsets adjustment at the application layer.\n const indicatorPadding = useDerivedValue(\n () => padding.value + extraContentPadding.value,\n );\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n onLayoutInternal(e);\n onLayoutProp?.(e);\n },\n [onLayoutInternal, onLayoutProp],\n );\n\n const onContentSizeChange = useCallback(\n (w: number, h: number) => {\n onContentSizeChangeInternal(w, h);\n onContentSizeChangeProp?.(w, h);\n },\n [onContentSizeChangeInternal, onContentSizeChangeProp],\n );\n\n // Invisible view whose animated style changes every frame during keyboard\n // animation. On Fabric, this forces Reanimated to schedule a commit,\n // which flushes the scrollTo call in the same frame (fixing de-synchronization).\n // see https://github.com/software-mansion/react-native-reanimated/issues/9000\n const commitStyle = useAnimatedStyle(\n () => ({\n transform: [{ translateY: -currentHeight.value }],\n }),\n [],\n );\n const commit = useMemo(\n () => [styles.commitView, commitStyle],\n [commitStyle],\n );\n\n return (\n <>\n <ScrollViewWithBottomPadding\n ref={onRef}\n {...rest}\n applyWorkaroundForContentInsetHitTestBug={\n applyWorkaroundForContentInsetHitTestBug\n }\n bottomPadding={totalPadding}\n contentOffsetY={contentOffsetY}\n inverted={inverted}\n scrollIndicatorPadding={indicatorPadding}\n ScrollViewComponent={ScrollViewComponent}\n onContentSizeChange={onContentSizeChange}\n onLayout={onLayout}\n >\n {children}\n </ScrollViewWithBottomPadding>\n <Reanimated.View style={commit} />\n </>\n );\n },\n);\n\nconst styles = StyleSheet.create({\n commitView: {\n display: \"none\",\n position: \"absolute\",\n },\n});\n\nexport default KeyboardChatScrollView;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_useCombinedRef","_interopRequireDefault","_ScrollViewWithBottomPadding","_useChatKeyboard","_useExtraContentPadding","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","ZERO_CONTENT_PADDING","makeMutable","ZERO_BLANK_SPACE","KeyboardChatScrollView","forwardRef","children","ScrollViewComponent","Reanimated","ScrollView","inverted","keyboardLiftBehavior","freeze","offset","extraContentPadding","blankSpace","applyWorkaroundForContentInsetHitTestBug","onLayout","onLayoutProp","onContentSizeChange","onContentSizeChangeProp","rest","ref","scrollViewRef","useAnimatedRef","onRef","useCombinedRef","freezeSV","useDerivedValue","value","padding","currentHeight","contentOffsetY","scroll","layout","size","onLayoutInternal","onContentSizeChangeInternal","useChatKeyboard","useExtraContentPadding","keyboardPadding","totalPadding","Math","max","indicatorPadding","useCallback","w","h","commitStyle","useAnimatedStyle","transform","translateY","commit","useMemo","styles","commitView","createElement","Fragment","bottomPadding","scrollIndicatorPadding","View","style","StyleSheet","create","display","position","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport {\n makeMutable,\n useAnimatedRef,\n useAnimatedStyle,\n useDerivedValue,\n} from \"react-native-reanimated\";\nimport Reanimated from \"react-native-reanimated\";\n\nimport useCombinedRef from \"../hooks/useCombinedRef\";\nimport ScrollViewWithBottomPadding from \"../ScrollViewWithBottomPadding\";\n\nimport { useChatKeyboard } from \"./useChatKeyboard\";\nimport { useExtraContentPadding } from \"./useExtraContentPadding\";\n\nimport type { KeyboardChatScrollViewProps } from \"./types\";\nimport type { LayoutChangeEvent } from \"react-native\";\n\nconst ZERO_CONTENT_PADDING = makeMutable(0);\nconst ZERO_BLANK_SPACE = makeMutable(0);\n\nconst KeyboardChatScrollView = forwardRef<\n Reanimated.ScrollView,\n React.PropsWithChildren<KeyboardChatScrollViewProps>\n>(\n (\n {\n children,\n ScrollViewComponent = Reanimated.ScrollView,\n inverted = false,\n keyboardLiftBehavior = \"always\",\n freeze = false,\n offset = 0,\n extraContentPadding = ZERO_CONTENT_PADDING,\n blankSpace = ZERO_BLANK_SPACE,\n applyWorkaroundForContentInsetHitTestBug = false,\n onLayout: onLayoutProp,\n onContentSizeChange: onContentSizeChangeProp,\n ...rest\n },\n ref,\n ) => {\n const scrollViewRef = useAnimatedRef<Reanimated.ScrollView>();\n const onRef = useCombinedRef(ref, scrollViewRef);\n const freezeSV = useDerivedValue(() =>\n typeof freeze === \"boolean\" ? freeze : freeze.value,\n );\n const {\n padding,\n currentHeight,\n contentOffsetY,\n scroll,\n layout,\n size,\n onLayout: onLayoutInternal,\n onContentSizeChange: onContentSizeChangeInternal,\n } = useChatKeyboard(scrollViewRef, {\n inverted,\n keyboardLiftBehavior,\n freeze: freezeSV,\n offset,\n blankSpace,\n extraContentPadding,\n });\n\n useExtraContentPadding({\n scrollViewRef,\n extraContentPadding,\n keyboardPadding: padding,\n blankSpace,\n scroll,\n layout,\n size,\n contentOffsetY,\n inverted,\n keyboardLiftBehavior,\n freeze: freezeSV,\n });\n\n const totalPadding = useDerivedValue(() =>\n Math.max(blankSpace.value, padding.value + extraContentPadding.value),\n );\n\n // Scroll indicator inset = keyboard + extraContentPadding (excludes blankSpace).\n // Apps that render into the unsafe area can supply a negative\n // scrollIndicatorInsets adjustment at the application layer.\n const indicatorPadding = useDerivedValue(\n () => padding.value + extraContentPadding.value,\n );\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n onLayoutInternal(e);\n onLayoutProp?.(e);\n },\n [onLayoutInternal, onLayoutProp],\n );\n\n const onContentSizeChange = useCallback(\n (w: number, h: number) => {\n onContentSizeChangeInternal(w, h);\n onContentSizeChangeProp?.(w, h);\n },\n [onContentSizeChangeInternal, onContentSizeChangeProp],\n );\n\n // Invisible view whose animated style changes every frame during keyboard\n // animation. On Fabric, this forces Reanimated to schedule a commit,\n // which flushes the scrollTo call in the same frame (fixing de-synchronization).\n // see https://github.com/software-mansion/react-native-reanimated/issues/9000\n const commitStyle = useAnimatedStyle(\n () => ({\n transform: [{ translateY: -currentHeight.value }],\n }),\n [],\n );\n const commit = useMemo(\n () => [styles.commitView, commitStyle],\n [commitStyle],\n );\n\n return (\n <>\n <ScrollViewWithBottomPadding\n ref={onRef}\n {...rest}\n applyWorkaroundForContentInsetHitTestBug={\n applyWorkaroundForContentInsetHitTestBug\n }\n bottomPadding={totalPadding}\n contentOffsetY={contentOffsetY}\n inverted={inverted}\n scrollIndicatorPadding={indicatorPadding}\n ScrollViewComponent={ScrollViewComponent}\n onContentSizeChange={onContentSizeChange}\n onLayout={onLayout}\n >\n {children}\n </ScrollViewWithBottomPadding>\n <Reanimated.View style={commit} />\n </>\n );\n },\n);\n\nconst styles = StyleSheet.create({\n commitView: {\n display: \"none\",\n position: \"absolute\",\n },\n});\n\nexport default KeyboardChatScrollView;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { AnimatedScrollViewComponent } from \"../ScrollViewWithBottomPadding\";\nimport type { KeyboardLiftBehavior } from \"./useChatKeyboard/types\";\nimport type { ScrollViewProps } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\nexport type KeyboardChatScrollViewProps = {\n /** Custom component for `ScrollView`. Default is `ScrollView`. */\n ScrollViewComponent?: AnimatedScrollViewComponent;\n /** Whether list are using `inverted` prop. Default is `false`. */\n inverted?: boolean;\n /**\n * The distance between the bottom of the screen and the `ScrollView`.\n * When the keyboard appears, the `ScrollView` will only push content by the effective\n * distance (`keyboardHeight - offset`) instead of the full keyboard height.\n *\n * Useful when the input is not at the very bottom of the screen (e.g., above safe area, above\n * bottom tabs, etc. - in this case offset should be equal to the height of the elements between\n * `ScrollView` and bottom of the screen).\n *\n * Default is `0`.\n */\n offset?: number;\n /**\n * Determines how the chat content should behave when the keyboard appears, specifically whether\n * the scroll view should automatically lift its content to keep it visible above the keyboard.\n *\n * Possible values:\n * - `'always'`: The content always lifts along with the keyboard, ensuring the messages from the bottom part of screen\n * remain visible regardless of the current scroll position. This is the default behavior for most chat applications (used in Telegram).\n * - `'whenAtEnd'`: The content lifts only if the scroll view is at the end (i.e., the last message\n * is visible or near the bottom). This prevents unnecessary adjustments when the user is scrolling\n * through older messages (ChatGPT mobile app behavior).\n * - `'persistent'`: The content always lifts when the keyboard appears (similar to `'always'`), but\n * does not reset (lower) when the keyboard hides. This mimics behaviors where the view remains adjusted\n * after keyboard dismissal to maintain focus on the latest content without shifting back (Claude mobile app behavior).\n * - `'never'`: The content does not lift at all when the keyboard appears. Use this for scenarios\n * when you don't want to disturb user attention with animations (Perplexity mobile app behavior).\n *\n * Default is `'always'`.\n */\n keyboardLiftBehavior?: KeyboardLiftBehavior;\n /**\n * When `true`, freezes all keyboard-driven layout changes (padding, content offset, scroll position).\n * Useful when dismissing the keyboard to open a bottom sheet — prevents visual disruption\n * while the sheet is visible.\n *\n * Default is `false`.\n */\n freeze?: boolean
|
|
1
|
+
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { AnimatedScrollViewComponent } from \"../ScrollViewWithBottomPadding\";\nimport type { KeyboardLiftBehavior } from \"./useChatKeyboard/types\";\nimport type { ScrollViewProps } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\nexport type KeyboardChatScrollViewProps = {\n /** Custom component for `ScrollView`. Default is `ScrollView`. */\n ScrollViewComponent?: AnimatedScrollViewComponent;\n /** Whether list are using `inverted` prop. Default is `false`. */\n inverted?: boolean;\n /**\n * The distance between the bottom of the screen and the `ScrollView`.\n * When the keyboard appears, the `ScrollView` will only push content by the effective\n * distance (`keyboardHeight - offset`) instead of the full keyboard height.\n *\n * Useful when the input is not at the very bottom of the screen (e.g., above safe area, above\n * bottom tabs, etc. - in this case offset should be equal to the height of the elements between\n * `ScrollView` and bottom of the screen).\n *\n * Default is `0`.\n */\n offset?: number;\n /**\n * Determines how the chat content should behave when the keyboard appears, specifically whether\n * the scroll view should automatically lift its content to keep it visible above the keyboard.\n *\n * Possible values:\n * - `'always'`: The content always lifts along with the keyboard, ensuring the messages from the bottom part of screen\n * remain visible regardless of the current scroll position. This is the default behavior for most chat applications (used in Telegram).\n * - `'whenAtEnd'`: The content lifts only if the scroll view is at the end (i.e., the last message\n * is visible or near the bottom). This prevents unnecessary adjustments when the user is scrolling\n * through older messages (ChatGPT mobile app behavior).\n * - `'persistent'`: The content always lifts when the keyboard appears (similar to `'always'`), but\n * does not reset (lower) when the keyboard hides. This mimics behaviors where the view remains adjusted\n * after keyboard dismissal to maintain focus on the latest content without shifting back (Claude mobile app behavior).\n * - `'never'`: The content does not lift at all when the keyboard appears. Use this for scenarios\n * when you don't want to disturb user attention with animations (Perplexity mobile app behavior).\n *\n * Default is `'always'`.\n */\n keyboardLiftBehavior?: KeyboardLiftBehavior;\n /**\n * When `true`, freezes all keyboard-driven layout changes (padding, content offset, scroll position).\n * Useful when dismissing the keyboard to open a bottom sheet — prevents visual disruption\n * while the sheet is visible.\n *\n * Default is `false`.\n */\n freeze?: boolean | SharedValue<boolean>;\n /**\n * A shared value representing additional padding from external elements\n * (e.g., a growing multiline `TextInput` in a `KeyboardStickyView`).\n *\n * When this value changes:\n * - The scrollable range is always extended/contracted (via `contentInset`).\n * - The scroll position is conditionally adjusted based on `keyboardLiftBehavior`.\n *\n * Default is `undefined` (no extra padding).\n */\n extraContentPadding?: SharedValue<number>;\n /**\n * When `true`, applies a runtime workaround for a React Native 0.81+ bug\n * where the ScrollView's `contentInset` area does not respond to touch/scroll\n * gestures (facebook/react-native#54123).\n *\n * This uses Objective-C runtime method swizzling on the ScrollView's container\n * view, which is inherently fragile. Only enable if you are affected by the\n * upstream bug and understand the risks.\n *\n * iOS only. Default is `false`.\n */\n applyWorkaroundForContentInsetHitTestBug?: boolean;\n /**\n * A shared value representing a minimum inset floor (in pixels).\n *\n * When set, the total bottom padding is computed as:\n * `max(blankSpace, keyboardPadding + extraContentPadding)`\n *\n * This means the keyboard \"absorbs\" into the minimum padding rather than adding to it:\n * - When `blankSpace >= keyboard + extraContentPadding`: content does NOT move on keyboard open/close.\n * - When `blankSpace < keyboard + extraContentPadding`: content moves, but only by the excess amount.\n *\n * Useful in AI chat apps where a sent message needs space below it (to push it to the top\n * of the viewport) while the AI response streams in, without that space causing extra movement\n * when the keyboard opens.\n *\n * Default is `undefined` (equivalent to `0` — no minimum floor).\n */\n blankSpace?: SharedValue<number>;\n} & ScrollViewProps;\n"],"mappings":"","ignoreList":[]}
|
|
@@ -50,7 +50,7 @@ function useChatKeyboard(scrollViewRef, options) {
|
|
|
50
50
|
onStart: e => {
|
|
51
51
|
"worklet";
|
|
52
52
|
|
|
53
|
-
if (freeze) {
|
|
53
|
+
if (freeze.value) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
if (e.height > 0) {
|
|
@@ -128,13 +128,13 @@ function useChatKeyboard(scrollViewRef, options) {
|
|
|
128
128
|
onEnd: e => {
|
|
129
129
|
"worklet";
|
|
130
130
|
|
|
131
|
-
if (freeze) {
|
|
131
|
+
if (freeze.value) {
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
134
134
|
const effective = (0, _helpers.getEffectiveHeight)(e.height, targetKeyboardHeight.value, offset);
|
|
135
135
|
padding.value = effective;
|
|
136
136
|
}
|
|
137
|
-
}, [inverted, keyboardLiftBehavior,
|
|
137
|
+
}, [inverted, keyboardLiftBehavior, offset, extraContentPadding]);
|
|
138
138
|
return {
|
|
139
139
|
padding,
|
|
140
140
|
currentHeight,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNativeReanimated","require","_hooks","_useScrollState","_interopRequireDefault","_helpers","e","__esModule","default","useChatKeyboard","scrollViewRef","options","inverted","keyboardLiftBehavior","freeze","offset","blankSpace","extraContentPadding","padding","useSharedValue","currentHeight","contentOffsetY","targetKeyboardHeight","prevAbsorption","layout","size","scroll","onLayout","onContentSizeChange","useScrollState","useKeyboardHandler","onStart","height","value","effective","getEffectiveHeight","atEnd","isScrollAtEnd","visibleFraction","getVisibleMinimumPaddingFraction","visiblePadding","minimumPaddingAbsorbed","Math","max","scrollEffective","getScrollEffective","actualTotalPadding","maxScroll","min","prevScrollEffective","relativeScroll","shouldShiftContent","computeIOSContentOffset","onMove","onEnd"],"sources":["index.ios.ts"],"sourcesContent":["import { useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport useScrollState from \"../../hooks/useScrollState\";\n\nimport {\n computeIOSContentOffset,\n getEffectiveHeight,\n getScrollEffective,\n getVisibleMinimumPaddingFraction,\n isScrollAtEnd,\n shouldShiftContent,\n} from \"./helpers\";\n\nimport type { UseChatKeyboardOptions, UseChatKeyboardReturn } from \"./types\";\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\n/**\n * Hook that manages keyboard-driven scrolling for chat-style scroll views.\n * Calculates padding (extra scrollable space) and content shift values,\n * using iOS-specific strategy (contentOffset set once in onStart).\n *\n * @param scrollViewRef - Animated ref to the scroll view.\n * @param options - Configuration for inverted and keyboardLiftBehavior.\n * @returns Shared values for padding and contentOffsetY.\n * @example\n * ```tsx\n * const { padding, contentOffsetY } = useChatKeyboard(ref, {\n * inverted: false,\n * keyboardLiftBehavior: \"always\",\n * });\n * ```\n */\nfunction useChatKeyboard(\n scrollViewRef: AnimatedRef<Reanimated.ScrollView>,\n options: UseChatKeyboardOptions,\n): UseChatKeyboardReturn {\n const {\n inverted,\n keyboardLiftBehavior,\n freeze,\n offset,\n blankSpace,\n extraContentPadding,\n } = options;\n\n const padding = useSharedValue(0);\n const currentHeight = useSharedValue(0);\n const contentOffsetY = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n const prevAbsorption = useSharedValue(0);\n\n const {\n layout,\n size,\n offset: scroll,\n onLayout,\n onContentSizeChange,\n } = useScrollState(scrollViewRef);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const atEnd = isScrollAtEnd(\n scroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // Scale minimum padding absorption by how much of it is visible.\n // Fully visible → full absorption; fully off-screen → no absorption.\n const visibleFraction = getVisibleMinimumPaddingFraction(\n scroll.value,\n layout.value.height,\n size.value.height,\n blankSpace.value,\n inverted,\n );\n const visiblePadding = visibleFraction * blankSpace.value;\n const minimumPaddingAbsorbed = Math.max(\n 0,\n visiblePadding - extraContentPadding.value,\n );\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n const actualTotalPadding = Math.max(\n blankSpace.value,\n effective + extraContentPadding.value,\n );\n\n // persistent mode: when keyboard shrinks, clamp to valid range\n if (\n keyboardLiftBehavior === \"persistent\" &&\n effective < padding.value\n ) {\n padding.value = effective;\n prevAbsorption.value = minimumPaddingAbsorbed;\n\n if (inverted) {\n const maxScroll = Math.max(\n size.value.height - layout.value.height,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n -actualTotalPadding,\n Math.min(scroll.value, maxScroll),\n );\n } else {\n const maxScroll = Math.max(\n size.value.height - layout.value.height + actualTotalPadding,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n 0,\n Math.min(scroll.value, maxScroll),\n );\n }\n\n return;\n }\n\n // never mode: when keyboard shrinks, clamp to valid range\n // to avoid ghost padding\n if (\n keyboardLiftBehavior === \"never\" &&\n effective < padding.value &&\n atEnd\n ) {\n padding.value = effective;\n prevAbsorption.value = minimumPaddingAbsorbed;\n\n if (inverted) {\n const maxScroll = Math.max(\n size.value.height - layout.value.height,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n -actualTotalPadding,\n Math.min(scroll.value, maxScroll),\n );\n } else {\n const maxScroll = Math.max(\n size.value.height - layout.value.height + actualTotalPadding,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n 0,\n Math.min(scroll.value, maxScroll),\n );\n }\n\n return;\n }\n\n // Undo only the scroll displacement that was actually applied\n // (not the full padding, which includes the absorbed portion).\n // Use the stored absorption from the previous event so that\n // the unwind matches the shift that was originally applied.\n const prevScrollEffective = getScrollEffective(\n padding.value,\n prevAbsorption.value,\n );\n const relativeScroll = inverted\n ? scroll.value + prevScrollEffective\n : scroll.value - prevScrollEffective;\n\n padding.value = effective;\n prevAbsorption.value = minimumPaddingAbsorbed;\n\n if (!shouldShiftContent(keyboardLiftBehavior, atEnd)) {\n // Preserve current scroll position so animated props\n // don't re-apply a stale contentOffset when padding changes\n contentOffsetY.value = scroll.value;\n\n return;\n }\n\n // When blankSpace fully absorbs the keyboard opening, preserve current scroll position\n // (only when keyboard is open — effective > 0 — not when closing)\n if (\n scrollEffective === 0 &&\n minimumPaddingAbsorbed > 0 &&\n effective > 0\n ) {\n contentOffsetY.value = scroll.value;\n\n return;\n }\n\n contentOffsetY.value = computeIOSContentOffset(\n relativeScroll,\n scrollEffective,\n size.value.height,\n layout.value.height,\n inverted,\n actualTotalPadding,\n );\n },\n onMove: () => {\n \"worklet\";\n\n // iOS doesn't need per-frame updates (contentOffset handles it)\n },\n onEnd: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n padding.value = effective;\n },\n },\n [inverted, keyboardLiftBehavior, freeze, offset, extraContentPadding],\n );\n\n return {\n padding,\n currentHeight,\n contentOffsetY,\n scroll,\n layout,\n size,\n onLayout,\n onContentSizeChange,\n };\n}\n\nexport { useChatKeyboard };\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_reactNativeReanimated","require","_hooks","_useScrollState","_interopRequireDefault","_helpers","e","__esModule","default","useChatKeyboard","scrollViewRef","options","inverted","keyboardLiftBehavior","freeze","offset","blankSpace","extraContentPadding","padding","useSharedValue","currentHeight","contentOffsetY","targetKeyboardHeight","prevAbsorption","layout","size","scroll","onLayout","onContentSizeChange","useScrollState","useKeyboardHandler","onStart","value","height","effective","getEffectiveHeight","atEnd","isScrollAtEnd","visibleFraction","getVisibleMinimumPaddingFraction","visiblePadding","minimumPaddingAbsorbed","Math","max","scrollEffective","getScrollEffective","actualTotalPadding","maxScroll","min","prevScrollEffective","relativeScroll","shouldShiftContent","computeIOSContentOffset","onMove","onEnd"],"sources":["index.ios.ts"],"sourcesContent":["import { useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport useScrollState from \"../../hooks/useScrollState\";\n\nimport {\n computeIOSContentOffset,\n getEffectiveHeight,\n getScrollEffective,\n getVisibleMinimumPaddingFraction,\n isScrollAtEnd,\n shouldShiftContent,\n} from \"./helpers\";\n\nimport type { UseChatKeyboardOptions, UseChatKeyboardReturn } from \"./types\";\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\n/**\n * Hook that manages keyboard-driven scrolling for chat-style scroll views.\n * Calculates padding (extra scrollable space) and content shift values,\n * using iOS-specific strategy (contentOffset set once in onStart).\n *\n * @param scrollViewRef - Animated ref to the scroll view.\n * @param options - Configuration for inverted and keyboardLiftBehavior.\n * @returns Shared values for padding and contentOffsetY.\n * @example\n * ```tsx\n * const { padding, contentOffsetY } = useChatKeyboard(ref, {\n * inverted: false,\n * keyboardLiftBehavior: \"always\",\n * });\n * ```\n */\nfunction useChatKeyboard(\n scrollViewRef: AnimatedRef<Reanimated.ScrollView>,\n options: UseChatKeyboardOptions,\n): UseChatKeyboardReturn {\n const {\n inverted,\n keyboardLiftBehavior,\n freeze,\n offset,\n blankSpace,\n extraContentPadding,\n } = options;\n\n const padding = useSharedValue(0);\n const currentHeight = useSharedValue(0);\n const contentOffsetY = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n const prevAbsorption = useSharedValue(0);\n\n const {\n layout,\n size,\n offset: scroll,\n onLayout,\n onContentSizeChange,\n } = useScrollState(scrollViewRef);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (freeze.value) {\n return;\n }\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const atEnd = isScrollAtEnd(\n scroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // Scale minimum padding absorption by how much of it is visible.\n // Fully visible → full absorption; fully off-screen → no absorption.\n const visibleFraction = getVisibleMinimumPaddingFraction(\n scroll.value,\n layout.value.height,\n size.value.height,\n blankSpace.value,\n inverted,\n );\n const visiblePadding = visibleFraction * blankSpace.value;\n const minimumPaddingAbsorbed = Math.max(\n 0,\n visiblePadding - extraContentPadding.value,\n );\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n const actualTotalPadding = Math.max(\n blankSpace.value,\n effective + extraContentPadding.value,\n );\n\n // persistent mode: when keyboard shrinks, clamp to valid range\n if (\n keyboardLiftBehavior === \"persistent\" &&\n effective < padding.value\n ) {\n padding.value = effective;\n prevAbsorption.value = minimumPaddingAbsorbed;\n\n if (inverted) {\n const maxScroll = Math.max(\n size.value.height - layout.value.height,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n -actualTotalPadding,\n Math.min(scroll.value, maxScroll),\n );\n } else {\n const maxScroll = Math.max(\n size.value.height - layout.value.height + actualTotalPadding,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n 0,\n Math.min(scroll.value, maxScroll),\n );\n }\n\n return;\n }\n\n // never mode: when keyboard shrinks, clamp to valid range\n // to avoid ghost padding\n if (\n keyboardLiftBehavior === \"never\" &&\n effective < padding.value &&\n atEnd\n ) {\n padding.value = effective;\n prevAbsorption.value = minimumPaddingAbsorbed;\n\n if (inverted) {\n const maxScroll = Math.max(\n size.value.height - layout.value.height,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n -actualTotalPadding,\n Math.min(scroll.value, maxScroll),\n );\n } else {\n const maxScroll = Math.max(\n size.value.height - layout.value.height + actualTotalPadding,\n 0,\n );\n\n contentOffsetY.value = Math.max(\n 0,\n Math.min(scroll.value, maxScroll),\n );\n }\n\n return;\n }\n\n // Undo only the scroll displacement that was actually applied\n // (not the full padding, which includes the absorbed portion).\n // Use the stored absorption from the previous event so that\n // the unwind matches the shift that was originally applied.\n const prevScrollEffective = getScrollEffective(\n padding.value,\n prevAbsorption.value,\n );\n const relativeScroll = inverted\n ? scroll.value + prevScrollEffective\n : scroll.value - prevScrollEffective;\n\n padding.value = effective;\n prevAbsorption.value = minimumPaddingAbsorbed;\n\n if (!shouldShiftContent(keyboardLiftBehavior, atEnd)) {\n // Preserve current scroll position so animated props\n // don't re-apply a stale contentOffset when padding changes\n contentOffsetY.value = scroll.value;\n\n return;\n }\n\n // When blankSpace fully absorbs the keyboard opening, preserve current scroll position\n // (only when keyboard is open — effective > 0 — not when closing)\n if (\n scrollEffective === 0 &&\n minimumPaddingAbsorbed > 0 &&\n effective > 0\n ) {\n contentOffsetY.value = scroll.value;\n\n return;\n }\n\n contentOffsetY.value = computeIOSContentOffset(\n relativeScroll,\n scrollEffective,\n size.value.height,\n layout.value.height,\n inverted,\n actualTotalPadding,\n );\n },\n onMove: () => {\n \"worklet\";\n\n // iOS doesn't need per-frame updates (contentOffset handles it)\n },\n onEnd: (e) => {\n \"worklet\";\n\n if (freeze.value) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n padding.value = effective;\n },\n },\n [inverted, keyboardLiftBehavior, offset, extraContentPadding],\n );\n\n return {\n padding,\n currentHeight,\n contentOffsetY,\n scroll,\n layout,\n size,\n onLayout,\n onContentSizeChange,\n };\n}\n\nexport { useChatKeyboard };\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -58,7 +58,7 @@ function useChatKeyboard(scrollViewRef, options) {
|
|
|
58
58
|
onStart: e => {
|
|
59
59
|
"worklet";
|
|
60
60
|
|
|
61
|
-
if (freeze) {
|
|
61
|
+
if (freeze.value) {
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
if (e.height > 0) {
|
|
@@ -113,7 +113,7 @@ function useChatKeyboard(scrollViewRef, options) {
|
|
|
113
113
|
onMove: e => {
|
|
114
114
|
"worklet";
|
|
115
115
|
|
|
116
|
-
if (freeze) {
|
|
116
|
+
if (freeze.value) {
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
currentHeight.value = e.height;
|
|
@@ -214,7 +214,7 @@ function useChatKeyboard(scrollViewRef, options) {
|
|
|
214
214
|
onEnd: e => {
|
|
215
215
|
"worklet";
|
|
216
216
|
|
|
217
|
-
if (freeze) {
|
|
217
|
+
if (freeze.value) {
|
|
218
218
|
return;
|
|
219
219
|
}
|
|
220
220
|
const effective = (0, _helpers.getEffectiveHeight)(e.height, targetKeyboardHeight.value, offset);
|
|
@@ -225,7 +225,7 @@ function useChatKeyboard(scrollViewRef, options) {
|
|
|
225
225
|
actualOpenShift.value = scroll.value - offsetBeforeScroll.value;
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
-
}, [inverted, keyboardLiftBehavior,
|
|
228
|
+
}, [inverted, keyboardLiftBehavior, offset]);
|
|
229
229
|
return {
|
|
230
230
|
padding,
|
|
231
231
|
currentHeight,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNativeReanimated","require","_hooks","_useScrollState","_interopRequireDefault","_helpers","e","__esModule","default","useChatKeyboard","scrollViewRef","options","inverted","keyboardLiftBehavior","freeze","offset","blankSpace","extraContentPadding","padding","useSharedValue","currentHeight","offsetBeforeScroll","targetKeyboardHeight","closing","minimumPaddingFractionOnOpen","actualOpenShift","layout","size","scroll","onLayout","onContentSizeChange","useScrollState","clampScrollIfNeeded","effective","totalPaddingForMaxScroll","paddingForMax","undefined","maxScroll","Math","max","value","height","scrollTo","useKeyboardHandler","onStart","getEffectiveHeight","atEnd","isScrollAtEnd","visibleFraction","getVisibleMinimumPaddingFraction","minimumPaddingAbsorbed","getMinimumPaddingAbsorbed","scrollEffective","getScrollEffective","duration","onMove","actualTotalPadding","wasAtEnd","shouldShiftContent","currentShift","target","keepAt","min","clampedScrollTarget","onEnd","contentOffsetY"],"sources":["index.ts"],"sourcesContent":["import { scrollTo, useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport useScrollState from \"../../hooks/useScrollState\";\n\nimport {\n clampedScrollTarget,\n getEffectiveHeight,\n getMinimumPaddingAbsorbed,\n getScrollEffective,\n getVisibleMinimumPaddingFraction,\n isScrollAtEnd,\n shouldShiftContent,\n} from \"./helpers\";\n\nimport type { UseChatKeyboardOptions, UseChatKeyboardReturn } from \"./types\";\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\n/**\n * Hook that manages keyboard-driven scrolling for chat-style scroll views.\n * Calculates padding (extra scrollable space) and content shift values,\n * using per-frame scrollTo updates (Android and other platforms).\n *\n * @param scrollViewRef - Animated ref to the scroll view.\n * @param options - Configuration for inverted and keyboardLiftBehavior.\n * @returns Shared values for padding and contentOffsetY (always `undefined`).\n * @example\n * ```tsx\n * const { padding } = useChatKeyboard(ref, { inverted: false, keyboardLiftBehavior: \"always\" });\n * ```\n */\nfunction useChatKeyboard(\n scrollViewRef: AnimatedRef<Reanimated.ScrollView>,\n options: UseChatKeyboardOptions,\n): UseChatKeyboardReturn {\n const {\n inverted,\n keyboardLiftBehavior,\n freeze,\n offset,\n blankSpace,\n extraContentPadding,\n } = options;\n\n const padding = useSharedValue(0);\n const currentHeight = useSharedValue(0);\n const offsetBeforeScroll = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n const closing = useSharedValue(false);\n const minimumPaddingFractionOnOpen = useSharedValue(0);\n const actualOpenShift = useSharedValue(0);\n const {\n layout,\n size,\n offset: scroll,\n onLayout,\n onContentSizeChange,\n } = useScrollState(scrollViewRef);\n const clampScrollIfNeeded = (\n effective: number,\n totalPaddingForMaxScroll?: number,\n ) => {\n \"worklet\";\n\n const paddingForMax =\n totalPaddingForMaxScroll !== undefined\n ? totalPaddingForMaxScroll\n : effective;\n const maxScroll = Math.max(\n size.value.height - layout.value.height + paddingForMax,\n 0,\n );\n\n if (scroll.value > maxScroll) {\n scrollTo(scrollViewRef, 0, maxScroll, false);\n }\n };\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n closing.value = false;\n } else {\n closing.value = true;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const atEnd = isScrollAtEnd(\n scroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // Scale minimum padding absorption by how much of it is visible.\n // Fully visible → full absorption; fully off-screen → no absorption.\n const visibleFraction = getVisibleMinimumPaddingFraction(\n scroll.value,\n layout.value.height,\n size.value.height,\n blankSpace.value,\n inverted,\n );\n const minimumPaddingAbsorbed =\n visibleFraction >= 1\n ? getMinimumPaddingAbsorbed(\n blankSpace.value,\n extraContentPadding.value,\n )\n : 0;\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n\n if (inverted && e.duration === -1) {\n // Android inverted: skip post-interactive snap-back events\n // (duration === -1 means the keyboard is re-establishing its\n // position after an interactive gesture, not a real animation)\n return;\n } else if (e.height > 0) {\n // Android: keyboard opening — set padding + capture scroll position\n minimumPaddingFractionOnOpen.value = visibleFraction >= 1 ? 1 : 0;\n padding.value = effective;\n offsetBeforeScroll.value = scroll.value;\n\n if (!inverted && keyboardLiftBehavior === \"whenAtEnd\" && !atEnd) {\n // Sentinel: don't scroll in onMove (non-inverted only)\n offsetBeforeScroll.value = -1;\n } else if (!inverted && scrollEffective === 0) {\n // blankSpace fully absorbs the keyboard — prevent scroll\n offsetBeforeScroll.value = -1;\n } else if (inverted && scrollEffective === 0) {\n // blankSpace fully absorbs the keyboard — guard for inverted\n offsetBeforeScroll.value = scroll.value;\n }\n } else {\n // Android: keyboard closing — re-capture scroll position\n if (inverted) {\n offsetBeforeScroll.value = scroll.value;\n } else {\n // Preserve \"whenAtEnd\" sentinel: if open didn't shift, close shouldn't either\n if (offsetBeforeScroll.value !== -1) {\n // Use the actual displacement recorded at end of open animation\n // (not the theoretical value) so close is symmetric with open\n offsetBeforeScroll.value = scroll.value - actualOpenShift.value;\n }\n }\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n currentHeight.value = e.height;\n\n if (inverted) {\n // Skip post-interactive snap-back (duration === -1)\n if (e.duration === -1) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const minimumPaddingAbsorbed =\n getMinimumPaddingAbsorbed(\n blankSpace.value,\n extraContentPadding.value,\n ) * minimumPaddingFractionOnOpen.value;\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n const actualTotalPadding = Math.max(\n blankSpace.value,\n effective + extraContentPadding.value,\n );\n\n // Check if we should shift content based on position when keyboard started\n const wasAtEnd = isScrollAtEnd(\n offsetBeforeScroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // \"never\" at end: scroll along when keyboard closes to avoid jump\n if (\n keyboardLiftBehavior === \"never\" &&\n wasAtEnd &&\n effective < padding.value\n ) {\n padding.value = effective;\n\n if (scrollEffective === 0 && minimumPaddingAbsorbed > 0) {\n return;\n }\n\n scrollTo(scrollViewRef, 0, 0, false);\n\n return;\n }\n\n if (!shouldShiftContent(keyboardLiftBehavior, wasAtEnd)) {\n // Closing, not shifting: reduce padding to avoid gap\n if (closing.value && effective < padding.value) {\n padding.value = effective;\n clampScrollIfNeeded(effective, actualTotalPadding);\n }\n\n return;\n }\n\n // When blankSpace fully absorbs the keyboard, skip scroll\n if (scrollEffective === 0 && minimumPaddingAbsorbed > 0) {\n return;\n }\n\n // Persistent: don't let shift decrease\n if (keyboardLiftBehavior === \"persistent\") {\n const currentShift =\n offsetBeforeScroll.value + padding.value - scroll.value;\n\n if (effective < currentShift) {\n // When at end, allow scrolling back (snap to end + reduce padding)\n if (wasAtEnd) {\n padding.value = effective;\n scrollTo(scrollViewRef, 0, 0, false);\n } else if (closing.value) {\n // Not at end: reduce padding to avoid gap\n padding.value = effective;\n clampScrollIfNeeded(effective, actualTotalPadding);\n }\n\n return;\n }\n }\n\n const target =\n offsetBeforeScroll.value + padding.value - scrollEffective;\n\n scrollTo(scrollViewRef, 0, target, false);\n } else {\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const minimumPaddingAbsorbed =\n getMinimumPaddingAbsorbed(\n blankSpace.value,\n extraContentPadding.value,\n ) * minimumPaddingFractionOnOpen.value;\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n const actualTotalPadding = Math.max(\n blankSpace.value,\n effective + extraContentPadding.value,\n );\n\n // \"never\" closing: clamp scroll to valid range as inset shrinks\n if (\n keyboardLiftBehavior === \"never\" &&\n closing.value &&\n effective < padding.value\n ) {\n clampScrollIfNeeded(effective, actualTotalPadding);\n\n return;\n }\n\n if (!shouldShiftContent(keyboardLiftBehavior, true)) {\n return;\n }\n\n // \"whenAtEnd\" sentinel check (also used for blankSpace full absorption)\n if (offsetBeforeScroll.value === -1) {\n if (closing.value) {\n // Keyboard didn't shift on open; ensure valid position on close\n clampScrollIfNeeded(effective, actualTotalPadding);\n }\n\n return;\n }\n\n // \"persistent\" closing: maintain position, clamped to valid range\n if (keyboardLiftBehavior === \"persistent\" && closing.value) {\n const keepAt = offsetBeforeScroll.value + padding.value;\n const maxScroll = Math.max(\n size.value.height - layout.value.height + actualTotalPadding,\n 0,\n );\n\n scrollTo(scrollViewRef, 0, Math.min(keepAt, maxScroll), false);\n\n return;\n }\n\n const target = clampedScrollTarget(\n offsetBeforeScroll.value,\n scrollEffective,\n size.value.height,\n layout.value.height,\n actualTotalPadding,\n );\n\n scrollTo(scrollViewRef, 0, target, false);\n\n // Track actual (clamped) displacement during open for symmetric close\n if (!closing.value) {\n actualOpenShift.value = target - offsetBeforeScroll.value;\n }\n }\n },\n onEnd: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n padding.value = effective;\n\n // Record actual scroll displacement so close can be symmetric\n if (effective > 0 && offsetBeforeScroll.value !== -1) {\n actualOpenShift.value = scroll.value - offsetBeforeScroll.value;\n }\n },\n },\n [inverted, keyboardLiftBehavior, freeze, offset],\n );\n\n return {\n padding,\n currentHeight,\n contentOffsetY: undefined,\n scroll,\n layout,\n size,\n onLayout,\n onContentSizeChange,\n };\n}\n\nexport { useChatKeyboard };\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_reactNativeReanimated","require","_hooks","_useScrollState","_interopRequireDefault","_helpers","e","__esModule","default","useChatKeyboard","scrollViewRef","options","inverted","keyboardLiftBehavior","freeze","offset","blankSpace","extraContentPadding","padding","useSharedValue","currentHeight","offsetBeforeScroll","targetKeyboardHeight","closing","minimumPaddingFractionOnOpen","actualOpenShift","layout","size","scroll","onLayout","onContentSizeChange","useScrollState","clampScrollIfNeeded","effective","totalPaddingForMaxScroll","paddingForMax","undefined","maxScroll","Math","max","value","height","scrollTo","useKeyboardHandler","onStart","getEffectiveHeight","atEnd","isScrollAtEnd","visibleFraction","getVisibleMinimumPaddingFraction","minimumPaddingAbsorbed","getMinimumPaddingAbsorbed","scrollEffective","getScrollEffective","duration","onMove","actualTotalPadding","wasAtEnd","shouldShiftContent","currentShift","target","keepAt","min","clampedScrollTarget","onEnd","contentOffsetY"],"sources":["index.ts"],"sourcesContent":["import { scrollTo, useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport useScrollState from \"../../hooks/useScrollState\";\n\nimport {\n clampedScrollTarget,\n getEffectiveHeight,\n getMinimumPaddingAbsorbed,\n getScrollEffective,\n getVisibleMinimumPaddingFraction,\n isScrollAtEnd,\n shouldShiftContent,\n} from \"./helpers\";\n\nimport type { UseChatKeyboardOptions, UseChatKeyboardReturn } from \"./types\";\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\n/**\n * Hook that manages keyboard-driven scrolling for chat-style scroll views.\n * Calculates padding (extra scrollable space) and content shift values,\n * using per-frame scrollTo updates (Android and other platforms).\n *\n * @param scrollViewRef - Animated ref to the scroll view.\n * @param options - Configuration for inverted and keyboardLiftBehavior.\n * @returns Shared values for padding and contentOffsetY (always `undefined`).\n * @example\n * ```tsx\n * const { padding } = useChatKeyboard(ref, { inverted: false, keyboardLiftBehavior: \"always\" });\n * ```\n */\nfunction useChatKeyboard(\n scrollViewRef: AnimatedRef<Reanimated.ScrollView>,\n options: UseChatKeyboardOptions,\n): UseChatKeyboardReturn {\n const {\n inverted,\n keyboardLiftBehavior,\n freeze,\n offset,\n blankSpace,\n extraContentPadding,\n } = options;\n\n const padding = useSharedValue(0);\n const currentHeight = useSharedValue(0);\n const offsetBeforeScroll = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n const closing = useSharedValue(false);\n const minimumPaddingFractionOnOpen = useSharedValue(0);\n const actualOpenShift = useSharedValue(0);\n const {\n layout,\n size,\n offset: scroll,\n onLayout,\n onContentSizeChange,\n } = useScrollState(scrollViewRef);\n const clampScrollIfNeeded = (\n effective: number,\n totalPaddingForMaxScroll?: number,\n ) => {\n \"worklet\";\n\n const paddingForMax =\n totalPaddingForMaxScroll !== undefined\n ? totalPaddingForMaxScroll\n : effective;\n const maxScroll = Math.max(\n size.value.height - layout.value.height + paddingForMax,\n 0,\n );\n\n if (scroll.value > maxScroll) {\n scrollTo(scrollViewRef, 0, maxScroll, false);\n }\n };\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (freeze.value) {\n return;\n }\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n closing.value = false;\n } else {\n closing.value = true;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const atEnd = isScrollAtEnd(\n scroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // Scale minimum padding absorption by how much of it is visible.\n // Fully visible → full absorption; fully off-screen → no absorption.\n const visibleFraction = getVisibleMinimumPaddingFraction(\n scroll.value,\n layout.value.height,\n size.value.height,\n blankSpace.value,\n inverted,\n );\n const minimumPaddingAbsorbed =\n visibleFraction >= 1\n ? getMinimumPaddingAbsorbed(\n blankSpace.value,\n extraContentPadding.value,\n )\n : 0;\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n\n if (inverted && e.duration === -1) {\n // Android inverted: skip post-interactive snap-back events\n // (duration === -1 means the keyboard is re-establishing its\n // position after an interactive gesture, not a real animation)\n return;\n } else if (e.height > 0) {\n // Android: keyboard opening — set padding + capture scroll position\n minimumPaddingFractionOnOpen.value = visibleFraction >= 1 ? 1 : 0;\n padding.value = effective;\n offsetBeforeScroll.value = scroll.value;\n\n if (!inverted && keyboardLiftBehavior === \"whenAtEnd\" && !atEnd) {\n // Sentinel: don't scroll in onMove (non-inverted only)\n offsetBeforeScroll.value = -1;\n } else if (!inverted && scrollEffective === 0) {\n // blankSpace fully absorbs the keyboard — prevent scroll\n offsetBeforeScroll.value = -1;\n } else if (inverted && scrollEffective === 0) {\n // blankSpace fully absorbs the keyboard — guard for inverted\n offsetBeforeScroll.value = scroll.value;\n }\n } else {\n // Android: keyboard closing — re-capture scroll position\n if (inverted) {\n offsetBeforeScroll.value = scroll.value;\n } else {\n // Preserve \"whenAtEnd\" sentinel: if open didn't shift, close shouldn't either\n if (offsetBeforeScroll.value !== -1) {\n // Use the actual displacement recorded at end of open animation\n // (not the theoretical value) so close is symmetric with open\n offsetBeforeScroll.value = scroll.value - actualOpenShift.value;\n }\n }\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n if (freeze.value) {\n return;\n }\n\n currentHeight.value = e.height;\n\n if (inverted) {\n // Skip post-interactive snap-back (duration === -1)\n if (e.duration === -1) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const minimumPaddingAbsorbed =\n getMinimumPaddingAbsorbed(\n blankSpace.value,\n extraContentPadding.value,\n ) * minimumPaddingFractionOnOpen.value;\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n const actualTotalPadding = Math.max(\n blankSpace.value,\n effective + extraContentPadding.value,\n );\n\n // Check if we should shift content based on position when keyboard started\n const wasAtEnd = isScrollAtEnd(\n offsetBeforeScroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // \"never\" at end: scroll along when keyboard closes to avoid jump\n if (\n keyboardLiftBehavior === \"never\" &&\n wasAtEnd &&\n effective < padding.value\n ) {\n padding.value = effective;\n\n if (scrollEffective === 0 && minimumPaddingAbsorbed > 0) {\n return;\n }\n\n scrollTo(scrollViewRef, 0, 0, false);\n\n return;\n }\n\n if (!shouldShiftContent(keyboardLiftBehavior, wasAtEnd)) {\n // Closing, not shifting: reduce padding to avoid gap\n if (closing.value && effective < padding.value) {\n padding.value = effective;\n clampScrollIfNeeded(effective, actualTotalPadding);\n }\n\n return;\n }\n\n // When blankSpace fully absorbs the keyboard, skip scroll\n if (scrollEffective === 0 && minimumPaddingAbsorbed > 0) {\n return;\n }\n\n // Persistent: don't let shift decrease\n if (keyboardLiftBehavior === \"persistent\") {\n const currentShift =\n offsetBeforeScroll.value + padding.value - scroll.value;\n\n if (effective < currentShift) {\n // When at end, allow scrolling back (snap to end + reduce padding)\n if (wasAtEnd) {\n padding.value = effective;\n scrollTo(scrollViewRef, 0, 0, false);\n } else if (closing.value) {\n // Not at end: reduce padding to avoid gap\n padding.value = effective;\n clampScrollIfNeeded(effective, actualTotalPadding);\n }\n\n return;\n }\n }\n\n const target =\n offsetBeforeScroll.value + padding.value - scrollEffective;\n\n scrollTo(scrollViewRef, 0, target, false);\n } else {\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const minimumPaddingAbsorbed =\n getMinimumPaddingAbsorbed(\n blankSpace.value,\n extraContentPadding.value,\n ) * minimumPaddingFractionOnOpen.value;\n const scrollEffective = getScrollEffective(\n effective,\n minimumPaddingAbsorbed,\n );\n const actualTotalPadding = Math.max(\n blankSpace.value,\n effective + extraContentPadding.value,\n );\n\n // \"never\" closing: clamp scroll to valid range as inset shrinks\n if (\n keyboardLiftBehavior === \"never\" &&\n closing.value &&\n effective < padding.value\n ) {\n clampScrollIfNeeded(effective, actualTotalPadding);\n\n return;\n }\n\n if (!shouldShiftContent(keyboardLiftBehavior, true)) {\n return;\n }\n\n // \"whenAtEnd\" sentinel check (also used for blankSpace full absorption)\n if (offsetBeforeScroll.value === -1) {\n if (closing.value) {\n // Keyboard didn't shift on open; ensure valid position on close\n clampScrollIfNeeded(effective, actualTotalPadding);\n }\n\n return;\n }\n\n // \"persistent\" closing: maintain position, clamped to valid range\n if (keyboardLiftBehavior === \"persistent\" && closing.value) {\n const keepAt = offsetBeforeScroll.value + padding.value;\n const maxScroll = Math.max(\n size.value.height - layout.value.height + actualTotalPadding,\n 0,\n );\n\n scrollTo(scrollViewRef, 0, Math.min(keepAt, maxScroll), false);\n\n return;\n }\n\n const target = clampedScrollTarget(\n offsetBeforeScroll.value,\n scrollEffective,\n size.value.height,\n layout.value.height,\n actualTotalPadding,\n );\n\n scrollTo(scrollViewRef, 0, target, false);\n\n // Track actual (clamped) displacement during open for symmetric close\n if (!closing.value) {\n actualOpenShift.value = target - offsetBeforeScroll.value;\n }\n }\n },\n onEnd: (e) => {\n \"worklet\";\n\n if (freeze.value) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n padding.value = effective;\n\n // Record actual scroll displacement so close can be symmetric\n if (effective > 0 && offsetBeforeScroll.value !== -1) {\n actualOpenShift.value = scroll.value - offsetBeforeScroll.value;\n }\n },\n },\n [inverted, keyboardLiftBehavior, offset],\n );\n\n return {\n padding,\n currentHeight,\n contentOffsetY: undefined,\n scroll,\n layout,\n size,\n onLayout,\n onContentSizeChange,\n };\n}\n\nexport { useChatKeyboard };\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { LayoutChangeEvent } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\ntype KeyboardLiftBehavior = \"always\" | \"whenAtEnd\" | \"persistent\" | \"never\";\n\ntype UseChatKeyboardOptions = {\n inverted: boolean;\n keyboardLiftBehavior: KeyboardLiftBehavior;\n freeze: boolean
|
|
1
|
+
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { LayoutChangeEvent } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\ntype KeyboardLiftBehavior = \"always\" | \"whenAtEnd\" | \"persistent\" | \"never\";\n\ntype UseChatKeyboardOptions = {\n inverted: boolean;\n keyboardLiftBehavior: KeyboardLiftBehavior;\n freeze: SharedValue<boolean>;\n offset: number;\n blankSpace: SharedValue<number>;\n /** Extra content padding shared value — needed on iOS to correctly clamp contentOffset. */\n extraContentPadding: SharedValue<number>;\n};\n\ntype UseChatKeyboardReturn = {\n /** Extra scrollable space (= keyboard height). Used as contentInset on iOS, contentInsetBottom/contentInsetTop on Android. */\n padding: SharedValue<number>;\n /** Raw keyboard height updated every frame in onMove. Used to force Reanimated commits on Fabric. */\n currentHeight: SharedValue<number>;\n /** Absolute Y content offset for iOS (set once in onStart). `undefined` on Android. */\n contentOffsetY: SharedValue<number> | undefined;\n /** Current vertical scroll offset. */\n scroll: SharedValue<number>;\n /** Visible viewport dimensions. */\n layout: SharedValue<{ width: number; height: number }>;\n /** Total content dimensions. */\n size: SharedValue<{ width: number; height: number }>;\n /** Callback to attach to ScrollView's onLayout prop to capture initial viewport dimensions. */\n onLayout: (e: LayoutChangeEvent) => void;\n /** Callback to attach to ScrollView's onContentSizeChange prop to capture initial content dimensions. */\n onContentSizeChange: (w: number, h: number) => void;\n};\n\nexport type {\n KeyboardLiftBehavior,\n UseChatKeyboardOptions,\n UseChatKeyboardReturn,\n};\n"],"mappings":"","ignoreList":[]}
|
|
@@ -54,7 +54,7 @@ function useExtraContentPadding(options) {
|
|
|
54
54
|
}
|
|
55
55
|
}, [scrollViewRef, contentOffsetY]);
|
|
56
56
|
(0, _reactNativeReanimated.useAnimatedReaction)(() => extraContentPadding.value, (current, previous) => {
|
|
57
|
-
if (freeze || previous === null) {
|
|
57
|
+
if (freeze.value || previous === null) {
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
const rawDelta = current - previous;
|
|
@@ -87,6 +87,6 @@ function useExtraContentPadding(options) {
|
|
|
87
87
|
const target = Math.min(scroll.value + effectiveDelta, maxScroll);
|
|
88
88
|
scrollToTarget(target);
|
|
89
89
|
}
|
|
90
|
-
}, [inverted, keyboardLiftBehavior
|
|
90
|
+
}, [inverted, keyboardLiftBehavior]);
|
|
91
91
|
}
|
|
92
92
|
//# sourceMappingURL=index.js.map
|