1diff --git a/lib/commonjs/components/KeyboardChatScrollView/index.js b/lib/commonjs/components/KeyboardChatScrollView/index.js
2index 0b78ff3..98b3b6c 100644
3--- a/lib/commonjs/components/KeyboardChatScrollView/index.js
4+++ b/lib/commonjs/components/KeyboardChatScrollView/index.js
5@@ -28,9 +28,12 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
6 offset = 0,
7 extraContentPadding = ZERO_CONTENT_PADDING,
8 blankSpace = ZERO_BLANK_SPACE,
9+ adjustedInsetCompensation = 0,
10+ adjustedStartInsetCompensation = 0,
11 applyWorkaroundForContentInsetHitTestBug = false,
12 onLayout: onLayoutProp,
13 onContentSizeChange: onContentSizeChangeProp,
14+ onContentInsetChange,
15 onEndVisible,
16 ...rest
17 }, ref) => {
18@@ -54,6 +57,8 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
19 offset,
20 blankSpace,
21 extraContentPadding,
22+ adjustedInsetCompensation,
23+ adjustedStartInsetCompensation,
24 initialContentOffsetY: (_rest$contentOffset = rest.contentOffset) === null || _rest$contentOffset === void 0 ? void 0 : _rest$contentOffset.y
25 });
26 (0, _useExtraContentPadding.useExtraContentPadding)({
27@@ -61,6 +66,8 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
28 extraContentPadding,
29 keyboardPadding: padding,
30 blankSpace,
31+ adjustedInsetCompensation,
32+ adjustedStartInsetCompensation,
33 scroll,
34 layout,
35 size,
36@@ -91,10 +98,26 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
37 // a bug for you, please open an issue.
38 const totalPadding = (0, _reanimated.useDerivedValue)(() => Math.min(layout.value.height, Math.max(blankSpace.value, padding.value + extraContentPadding.value)));
39
40+ // iOS applies the destination contentInset and contentOffset together at
41+ // keyboard-animation start. Keep that native target behavior, but report
42+ // the presentation height so virtualized-list layout follows the keyboard.
43+ const reportedPadding = (0, _reanimated.useDerivedValue)(() => _reactNative.Platform.OS === "ios" ? Math.min(layout.value.height, Math.max(blankSpace.value, currentHeight.value + extraContentPadding.value)) : totalPadding.value);
44+
45+ // Mirror the effective bottom padding (keyboard + composer + blank floor)
46+ // to the consumer - a virtualized list needs it in its own scroll math or
47+ // its end/maintain targets point at the under-the-keyboard resting offset.
48+ (0, _reanimated.useAnimatedReaction)(() => reportedPadding.value, (current, previous) => {
49+ if (onContentInsetChange && current !== previous) {
50+ (0, _reactNativeReanimated.runOnJS)(onContentInsetChange)({
51+ bottom: current
52+ });
53+ }
54+ }, [onContentInsetChange]);
55+
56 // Scroll indicator inset = keyboard + extraContentPadding (excludes blankSpace).
57 // Apps that render into the unsafe area can supply a negative
58 // scrollIndicatorInsets adjustment at the application layer.
59- const indicatorPadding = (0, _reanimated.useDerivedValue)(() => padding.value + extraContentPadding.value);
60+ const indicatorPadding = (0, _reanimated.useDerivedValue)(() => padding.value);
61 const onLayout = (0, _react.useCallback)(e => {
62 onLayoutInternal(e);
63 onLayoutProp === null || onLayoutProp === void 0 || onLayoutProp(e);
64diff --git a/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js b/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js
65index 4d33b3f..6a787d3 100644
66--- a/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js
67+++ b/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js
68@@ -206,7 +206,7 @@ const clampedScrollTarget = (offsetBeforeScroll, keyboardHeight, contentHeight,
69 * ```
70 */
71 exports.clampedScrollTarget = clampedScrollTarget;
72-const computeIOSContentOffset = (relativeScroll, keyboardHeight, contentHeight, layoutHeight, inverted, totalPaddingForMaxScroll) => {
73+const computeIOSContentOffset = (relativeScroll, keyboardHeight, contentHeight, layoutHeight, inverted, totalPaddingForMaxScroll, startInsetCompensation = 0) => {
74 "worklet";
75
76 const paddingForMax = totalPaddingForMaxScroll !== undefined ? totalPaddingForMaxScroll : keyboardHeight;
77@@ -214,8 +214,9 @@ const computeIOSContentOffset = (relativeScroll, keyboardHeight, contentHeight,
78 const maxScroll = Math.max(contentHeight - layoutHeight, 0);
79 return Math.max(Math.min(relativeScroll - keyboardHeight, maxScroll), -paddingForMax);
80 }
81- const maxScroll = Math.max(contentHeight - layoutHeight + paddingForMax, 0);
82- return Math.min(Math.max(keyboardHeight + relativeScroll, 0), maxScroll);
83+ const minScroll = -startInsetCompensation;
84+ const maxScroll = Math.max(contentHeight - layoutHeight + paddingForMax, minScroll);
85+ return Math.min(Math.max(keyboardHeight + relativeScroll, minScroll), maxScroll);
86 };
87 exports.computeIOSContentOffset = computeIOSContentOffset;
88 //# sourceMappingURL=helpers.js.map
89\ No newline at end of file
90diff --git a/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js b/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js
91index 6481228..0dc5dd1 100644
92--- a/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js
93+++ b/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js
94@@ -32,7 +32,9 @@ function useChatKeyboard(scrollViewRef, options) {
95 freeze,
96 offset,
97 blankSpace,
98- extraContentPadding
99+ extraContentPadding,
100+ adjustedInsetCompensation,
101+ adjustedStartInsetCompensation
102 } = options;
103 const padding = (0, _reactNativeReanimated.useSharedValue)(0);
104 const currentHeight = (0, _reactNativeReanimated.useSharedValue)(0);
105@@ -59,6 +61,9 @@ function useChatKeyboard(scrollViewRef, options) {
106 targetKeyboardHeight.value = e.height;
107 }
108 const effective = (0, _helpers.getEffectiveHeight)(e.height, targetKeyboardHeight.value, offset);
109+ if (e.duration === 0) {
110+ currentHeight.value = effective;
111+ }
112 const atEnd = (0, _helpers.isScrollAtEnd)(scroll.value, layout.value.height, size.value.height, inverted);
113
114 // Scale minimum padding absorption by how much of it is visible.
115@@ -67,7 +72,7 @@ function useChatKeyboard(scrollViewRef, options) {
116 const visiblePadding = visibleFraction * blankSpace.value;
117 const minimumPaddingAbsorbed = Math.max(0, visiblePadding - extraContentPadding.value);
118 const scrollEffective = (0, _helpers.getScrollEffective)(effective, minimumPaddingAbsorbed);
119- const actualTotalPadding = Math.max(blankSpace.value, effective + extraContentPadding.value);
120+ const actualTotalPadding = Math.max(blankSpace.value, effective + extraContentPadding.value) + adjustedInsetCompensation;
121
122 // `onInteractive` owns the native scroll offset. When its final
123 // keyboardWillHide event arrives, consume the marker so this
124@@ -87,8 +92,8 @@ function useChatKeyboard(scrollViewRef, options) {
125 const maxScroll = Math.max(size.value.height - layout.value.height, 0);
126 contentOffsetY.value = Math.max(-actualTotalPadding, Math.min(scroll.value, maxScroll));
127 } else {
128- const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, 0);
129- contentOffsetY.value = Math.max(0, Math.min(scroll.value, maxScroll));
130+ const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, -adjustedStartInsetCompensation);
131+ contentOffsetY.value = Math.max(-adjustedStartInsetCompensation, Math.min(scroll.value, maxScroll));
132 }
133 return;
134 }
135@@ -102,8 +107,8 @@ function useChatKeyboard(scrollViewRef, options) {
136 const maxScroll = Math.max(size.value.height - layout.value.height, 0);
137 contentOffsetY.value = Math.max(-actualTotalPadding, Math.min(scroll.value, maxScroll));
138 } else {
139- const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, 0);
140- contentOffsetY.value = Math.max(0, Math.min(scroll.value, maxScroll));
141+ const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, -adjustedStartInsetCompensation);
142+ contentOffsetY.value = Math.max(-adjustedStartInsetCompensation, Math.min(scroll.value, maxScroll));
143 }
144 return;
145 }
146@@ -129,17 +134,25 @@ function useChatKeyboard(scrollViewRef, options) {
147 contentOffsetY.value = scroll.value;
148 return;
149 }
150- contentOffsetY.value = (0, _helpers.computeIOSContentOffset)(relativeScroll, scrollEffective, size.value.height, layout.value.height, inverted, actualTotalPadding);
151+ contentOffsetY.value = (0, _helpers.computeIOSContentOffset)(relativeScroll, scrollEffective, size.value.height, layout.value.height, inverted, actualTotalPadding, adjustedStartInsetCompensation);
152 },
153- onInteractive: () => {
154+ onMove: e => {
155 "worklet";
156
157- isInteractiveDismissal.value = true;
158+ if (freeze.value) {
159+ return;
160+ }
161+ currentHeight.value = (0, _helpers.getEffectiveHeight)(e.height, targetKeyboardHeight.value, offset);
162 },
163- onMove: () => {
164+ onInteractive: e => {
165 "worklet";
166
167- // iOS doesn't need per-frame updates (contentOffset handles it)
168+ isInteractiveDismissal.value = true;
169+
170+ if (freeze.value) {
171+ return;
172+ }
173+ currentHeight.value = (0, _helpers.getEffectiveHeight)(e.height, targetKeyboardHeight.value, offset);
174 },
175 onEnd: e => {
176 "worklet";
177@@ -148,9 +161,10 @@ function useChatKeyboard(scrollViewRef, options) {
178 return;
179 }
180 const effective = (0, _helpers.getEffectiveHeight)(e.height, targetKeyboardHeight.value, offset);
181+ currentHeight.value = effective;
182 padding.value = effective;
183 }
184- }, [inverted, keyboardLiftBehavior, offset, extraContentPadding]);
185+ }, [inverted, keyboardLiftBehavior, offset, extraContentPadding, adjustedInsetCompensation, adjustedStartInsetCompensation]);
186 return {
187 padding,
188 currentHeight,
189diff --git a/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js b/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js
190index 0215bef..5307446 100644
191--- a/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js
192+++ b/lib/commonjs/components/KeyboardChatScrollView/useExtraContentPadding/index.js
193@@ -32,6 +32,8 @@ function useExtraContentPadding(options) {
194 extraContentPadding,
195 keyboardPadding,
196 blankSpace,
197+ adjustedInsetCompensation,
198+ adjustedStartInsetCompensation,
199 scroll,
200 layout,
201 size,
202@@ -51,8 +53,13 @@ function useExtraContentPadding(options) {
203 // otherwise the native ScrollView clamps to the old range.
204 requestAnimationFrame(() => {
205 // check that view is still mounted and ref is actual
206- // otherwise it may lead to a crash
207- if (!scrollViewRef()) {
208+ // otherwise it may lead to a crash. Reanimated 4.7+ passes the
209+ // ref to the UI runtime as a shareable holding the node in `.value`.
210+ const node =
211+ typeof scrollViewRef === "function"
212+ ? scrollViewRef()
213+ : scrollViewRef.value;
214+ if (!node) {
215 return;
216 }
217 (0, _reactNativeReanimated.scrollTo)(scrollViewRef, 0, target, false);
218@@ -71,8 +78,8 @@ function useExtraContentPadding(options) {
219 }
220
221 // Compute effective delta considering blankSpace floor
222- const previousTotal = Math.max(blankSpace.value, keyboardPadding.value + previous);
223- const currentTotal = Math.max(blankSpace.value, keyboardPadding.value + current);
224+ const previousTotal = Math.max(blankSpace.value, keyboardPadding.value + previous) + adjustedInsetCompensation;
225+ const currentTotal = Math.max(blankSpace.value, keyboardPadding.value + current) + adjustedInsetCompensation;
226 const effectiveDelta = currentTotal - previousTotal;
227 if (effectiveDelta === 0) {
228 // blankSpace absorbed the change
229@@ -91,13 +98,11 @@ function useExtraContentPadding(options) {
230 const target = Math.max(scroll.value - effectiveDelta, -currentTotal);
231 scrollToTarget(target);
232 } else {
233- const maxScroll = Math.max(size.value.height - layout.value.height + currentTotal, 0);
234- // Clamp at 0 as well: when the content is shorter than the viewport a
235- // shrinking padding makes `effectiveDelta` negative while `scroll.value`
236- // is already 0, so the target would go below the top of the content.
237- const target = Math.max(Math.min(scroll.value + effectiveDelta, maxScroll), 0);
238+ const minScroll = -adjustedStartInsetCompensation;
239+ const maxScroll = Math.max(size.value.height - layout.value.height + currentTotal, minScroll);
240+ const target = Math.max(minScroll, Math.min(scroll.value + effectiveDelta, maxScroll));
241 scrollToTarget(target);
242 }
243- }, [inverted, keyboardLiftBehavior]);
244+ }, [inverted, keyboardLiftBehavior, adjustedInsetCompensation, adjustedStartInsetCompensation]);
245 }
246 //# sourceMappingURL=index.js.map
247\ No newline at end of file
248diff --git a/lib/module/components/KeyboardChatScrollView/index.js b/lib/module/components/KeyboardChatScrollView/index.js
249index e0c8391..8df802a 100644
250--- a/lib/module/components/KeyboardChatScrollView/index.js
251+++ b/lib/module/components/KeyboardChatScrollView/index.js
252@@ -1,9 +1,9 @@
253 function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
254 import React, { forwardRef, useCallback, useMemo } from "react";
255-import { StyleSheet } from "react-native";
256-import { makeMutable, useAnimatedRef } from "react-native-reanimated";
257+import { Platform, StyleSheet } from "react-native";
258+import { makeMutable, runOnJS, useAnimatedRef } from "react-native-reanimated";
259 import Reanimated from "react-native-reanimated";
260-import { useAnimatedStyle, useDerivedValue } from "../../reanimated";
261+import { useAnimatedReaction, useAnimatedStyle, useDerivedValue } from "../../reanimated";
262 import useCombinedRef from "../hooks/useCombinedRef";
263 import ScrollViewWithBottomPadding from "../ScrollViewWithBottomPadding";
264 import { useChatKeyboard } from "./useChatKeyboard";
265@@ -21,9 +21,12 @@ const KeyboardChatScrollView = /*#__PURE__*/forwardRef(({
266 offset = 0,
267 extraContentPadding = ZERO_CONTENT_PADDING,
268 blankSpace = ZERO_BLANK_SPACE,
269+ adjustedInsetCompensation = 0,
270+ adjustedStartInsetCompensation = 0,
271 applyWorkaroundForContentInsetHitTestBug = false,
272 onLayout: onLayoutProp,
273 onContentSizeChange: onContentSizeChangeProp,
274+ onContentInsetChange,
275 onEndVisible,
276 ...rest
277 }, ref) => {
278@@ -47,6 +50,8 @@ const KeyboardChatScrollView = /*#__PURE__*/forwardRef(({
279 offset,
280 blankSpace,
281 extraContentPadding,
282+ adjustedInsetCompensation,
283+ adjustedStartInsetCompensation,
284 initialContentOffsetY: (_rest$contentOffset = rest.contentOffset) === null || _rest$contentOffset === void 0 ? void 0 : _rest$contentOffset.y
285 });
286 useExtraContentPadding({
287@@ -54,6 +59,8 @@ const KeyboardChatScrollView = /*#__PURE__*/forwardRef(({
288 extraContentPadding,
289 keyboardPadding: padding,
290 blankSpace,
291+ adjustedInsetCompensation,
292+ adjustedStartInsetCompensation,
293 scroll,
294 layout,
295 size,
296@@ -84,10 +91,26 @@ const KeyboardChatScrollView = /*#__PURE__*/forwardRef(({
297 // a bug for you, please open an issue.
298 const totalPadding = useDerivedValue(() => Math.min(layout.value.height, Math.max(blankSpace.value, padding.value + extraContentPadding.value)));
299
300+ // iOS applies the destination contentInset and contentOffset together at
301+ // keyboard-animation start. Keep that native target behavior, but report
302+ // the presentation height so virtualized-list layout follows the keyboard.
303+ const reportedPadding = useDerivedValue(() => Platform.OS === "ios" ? Math.min(layout.value.height, Math.max(blankSpace.value, currentHeight.value + extraContentPadding.value)) : totalPadding.value);
304+
305+ // Mirror the effective bottom padding (keyboard + composer + blank floor)
306+ // to the consumer - a virtualized list needs it in its own scroll math or
307+ // its end/maintain targets point at the under-the-keyboard resting offset.
308+ useAnimatedReaction(() => reportedPadding.value, (current, previous) => {
309+ if (onContentInsetChange && current !== previous) {
310+ runOnJS(onContentInsetChange)({
311+ bottom: current
312+ });
313+ }
314+ }, [onContentInsetChange]);
315+
316 // Scroll indicator inset = keyboard + extraContentPadding (excludes blankSpace).
317 // Apps that render into the unsafe area can supply a negative
318 // scrollIndicatorInsets adjustment at the application layer.
319- const indicatorPadding = useDerivedValue(() => padding.value + extraContentPadding.value);
320+ const indicatorPadding = useDerivedValue(() => padding.value);
321 const onLayout = useCallback(e => {
322 onLayoutInternal(e);
323 onLayoutProp === null || onLayoutProp === void 0 || onLayoutProp(e);
324diff --git a/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js b/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js
325index 295e221..2f7b87e 100644
326--- a/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js
327+++ b/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js
328@@ -193,7 +193,7 @@ export const clampedScrollTarget = (offsetBeforeScroll, keyboardHeight, contentH
329 * computeIOSContentOffset(100, 300, 1000, 800, false); // 400
330 * ```
331 */
332-export const computeIOSContentOffset = (relativeScroll, keyboardHeight, contentHeight, layoutHeight, inverted, totalPaddingForMaxScroll) => {
333+export const computeIOSContentOffset = (relativeScroll, keyboardHeight, contentHeight, layoutHeight, inverted, totalPaddingForMaxScroll, startInsetCompensation = 0) => {
334 "worklet";
335
336 const paddingForMax = totalPaddingForMaxScroll !== undefined ? totalPaddingForMaxScroll : keyboardHeight;
337@@ -201,7 +201,8 @@ export const computeIOSContentOffset = (relativeScroll, keyboardHeight, contentH
338 const maxScroll = Math.max(contentHeight - layoutHeight, 0);
339 return Math.max(Math.min(relativeScroll - keyboardHeight, maxScroll), -paddingForMax);
340 }
341- const maxScroll = Math.max(contentHeight - layoutHeight + paddingForMax, 0);
342- return Math.min(Math.max(keyboardHeight + relativeScroll, 0), maxScroll);
343+ const minScroll = -startInsetCompensation;
344+ const maxScroll = Math.max(contentHeight - layoutHeight + paddingForMax, minScroll);
345+ return Math.min(Math.max(keyboardHeight + relativeScroll, minScroll), maxScroll);
346 };
347 //# sourceMappingURL=helpers.js.map
348\ No newline at end of file
349diff --git a/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js b/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js
350index 043b973..df5a408 100644
351--- a/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js
352+++ b/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js
353@@ -25,7 +25,9 @@ function useChatKeyboard(scrollViewRef, options) {
354 freeze,
355 offset,
356 blankSpace,
357- extraContentPadding
358+ extraContentPadding,
359+ adjustedInsetCompensation,
360+ adjustedStartInsetCompensation
361 } = options;
362 const padding = useSharedValue(0);
363 const currentHeight = useSharedValue(0);
364@@ -52,6 +54,9 @@ function useChatKeyboard(scrollViewRef, options) {
365 targetKeyboardHeight.value = e.height;
366 }
367 const effective = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
368+ if (e.duration === 0) {
369+ currentHeight.value = effective;
370+ }
371 const atEnd = isScrollAtEnd(scroll.value, layout.value.height, size.value.height, inverted);
372
373 // Scale minimum padding absorption by how much of it is visible.
374@@ -60,7 +65,7 @@ function useChatKeyboard(scrollViewRef, options) {
375 const visiblePadding = visibleFraction * blankSpace.value;
376 const minimumPaddingAbsorbed = Math.max(0, visiblePadding - extraContentPadding.value);
377 const scrollEffective = getScrollEffective(effective, minimumPaddingAbsorbed);
378- const actualTotalPadding = Math.max(blankSpace.value, effective + extraContentPadding.value);
379+ const actualTotalPadding = Math.max(blankSpace.value, effective + extraContentPadding.value) + adjustedInsetCompensation;
380
381 // `onInteractive` owns the native scroll offset. When its final
382 // keyboardWillHide event arrives, consume the marker so this
383@@ -80,8 +85,8 @@ function useChatKeyboard(scrollViewRef, options) {
384 const maxScroll = Math.max(size.value.height - layout.value.height, 0);
385 contentOffsetY.value = Math.max(-actualTotalPadding, Math.min(scroll.value, maxScroll));
386 } else {
387- const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, 0);
388- contentOffsetY.value = Math.max(0, Math.min(scroll.value, maxScroll));
389+ const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, -adjustedStartInsetCompensation);
390+ contentOffsetY.value = Math.max(-adjustedStartInsetCompensation, Math.min(scroll.value, maxScroll));
391 }
392 return;
393 }
394@@ -95,8 +100,8 @@ function useChatKeyboard(scrollViewRef, options) {
395 const maxScroll = Math.max(size.value.height - layout.value.height, 0);
396 contentOffsetY.value = Math.max(-actualTotalPadding, Math.min(scroll.value, maxScroll));
397 } else {
398- const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, 0);
399- contentOffsetY.value = Math.max(0, Math.min(scroll.value, maxScroll));
400+ const maxScroll = Math.max(size.value.height - layout.value.height + actualTotalPadding, -adjustedStartInsetCompensation);
401+ contentOffsetY.value = Math.max(-adjustedStartInsetCompensation, Math.min(scroll.value, maxScroll));
402 }
403 return;
404 }
405@@ -122,17 +127,25 @@ function useChatKeyboard(scrollViewRef, options) {
406 contentOffsetY.value = scroll.value;
407 return;
408 }
409- contentOffsetY.value = computeIOSContentOffset(relativeScroll, scrollEffective, size.value.height, layout.value.height, inverted, actualTotalPadding);
410+ contentOffsetY.value = computeIOSContentOffset(relativeScroll, scrollEffective, size.value.height, layout.value.height, inverted, actualTotalPadding, adjustedStartInsetCompensation);
411 },
412- onInteractive: () => {
413+ onMove: e => {
414 "worklet";
415
416- isInteractiveDismissal.value = true;
417+ if (freeze.value) {
418+ return;
419+ }
420+ currentHeight.value = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
421 },
422- onMove: () => {
423+ onInteractive: e => {
424 "worklet";
425
426- // iOS doesn't need per-frame updates (contentOffset handles it)
427+ isInteractiveDismissal.value = true;
428+
429+ if (freeze.value) {
430+ return;
431+ }
432+ currentHeight.value = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
433 },
434 onEnd: e => {
435 "worklet";
436@@ -141,9 +154,10 @@ function useChatKeyboard(scrollViewRef, options) {
437 return;
438 }
439 const effective = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
440+ currentHeight.value = effective;
441 padding.value = effective;
442 }
443- }, [inverted, keyboardLiftBehavior, offset, extraContentPadding]);
444+ }, [inverted, keyboardLiftBehavior, offset, extraContentPadding, adjustedInsetCompensation, adjustedStartInsetCompensation]);
445 return {
446 padding,
447 currentHeight,
448diff --git a/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js b/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js
449index 5a9b91d..a11bfdb 100644
450--- a/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js
451+++ b/lib/module/components/KeyboardChatScrollView/useExtraContentPadding/index.js
452@@ -26,6 +26,8 @@ function useExtraContentPadding(options) {
453 extraContentPadding,
454 keyboardPadding,
455 blankSpace,
456+ adjustedInsetCompensation,
457+ adjustedStartInsetCompensation,
458 scroll,
459 layout,
460 size,
461@@ -45,8 +47,13 @@ function useExtraContentPadding(options) {
462 // otherwise the native ScrollView clamps to the old range.
463 requestAnimationFrame(() => {
464 // check that view is still mounted and ref is actual
465- // otherwise it may lead to a crash
466- if (!scrollViewRef()) {
467+ // otherwise it may lead to a crash. Reanimated 4.7+ passes the
468+ // ref to the UI runtime as a shareable holding the node in `.value`.
469+ const node =
470+ typeof scrollViewRef === "function"
471+ ? scrollViewRef()
472+ : scrollViewRef.value;
473+ if (!node) {
474 return;
475 }
476 scrollTo(scrollViewRef, 0, target, false);
477@@ -65,8 +72,8 @@ function useExtraContentPadding(options) {
478 }
479
480 // Compute effective delta considering blankSpace floor
481- const previousTotal = Math.max(blankSpace.value, keyboardPadding.value + previous);
482- const currentTotal = Math.max(blankSpace.value, keyboardPadding.value + current);
483+ const previousTotal = Math.max(blankSpace.value, keyboardPadding.value + previous) + adjustedInsetCompensation;
484+ const currentTotal = Math.max(blankSpace.value, keyboardPadding.value + current) + adjustedInsetCompensation;
485 const effectiveDelta = currentTotal - previousTotal;
486 if (effectiveDelta === 0) {
487 // blankSpace absorbed the change
488@@ -85,14 +92,12 @@ function useExtraContentPadding(options) {
489 const target = Math.max(scroll.value - effectiveDelta, -currentTotal);
490 scrollToTarget(target);
491 } else {
492- const maxScroll = Math.max(size.value.height - layout.value.height + currentTotal, 0);
493- // Clamp at 0 as well: when the content is shorter than the viewport a
494- // shrinking padding makes `effectiveDelta` negative while `scroll.value`
495- // is already 0, so the target would go below the top of the content.
496- const target = Math.max(Math.min(scroll.value + effectiveDelta, maxScroll), 0);
497+ const minScroll = -adjustedStartInsetCompensation;
498+ const maxScroll = Math.max(size.value.height - layout.value.height + currentTotal, minScroll);
499+ const target = Math.max(minScroll, Math.min(scroll.value + effectiveDelta, maxScroll));
500 scrollToTarget(target);
501 }
502- }, [inverted, keyboardLiftBehavior]);
503+ }, [inverted, keyboardLiftBehavior, adjustedInsetCompensation, adjustedStartInsetCompensation]);
504 }
505 export { useExtraContentPadding };
506 //# sourceMappingURL=index.js.map
507\ No newline at end of file
508diff --git a/lib/typescript/components/KeyboardChatScrollView/types.d.ts b/lib/typescript/components/KeyboardChatScrollView/types.d.ts
509index eba1514..6597d80 100644
510--- a/lib/typescript/components/KeyboardChatScrollView/types.d.ts
511+++ b/lib/typescript/components/KeyboardChatScrollView/types.d.ts
512@@ -88,6 +88,10 @@ export type KeyboardChatScrollViewProps = {
513 * Default is `undefined` (equivalent to `0` — no minimum floor).
514 */
515 blankSpace?: SharedValue<number>;
516+ /** Extra bottom inset UIKit adds beyond the raw contentInset (safe area). Offset math only. */
517+ adjustedInsetCompensation?: number;
518+ /** Leading inset UIKit adds outside raw contentInset. Offset math only. */
519+ adjustedStartInsetCompensation?: number;
520 /**
521 * Fires whenever the effective content inset changes — the static `contentInset`
522 * prop combined with the dynamic keyboard-driven padding.
523diff --git a/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/helpers.d.ts b/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/helpers.d.ts
524index 2b51cc4..3acec1f 100644
525--- a/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/helpers.d.ts
526+++ b/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/helpers.d.ts
527@@ -129,4 +129,4 @@ export declare const clampedScrollTarget: (offsetBeforeScroll: number, keyboardH
528 * computeIOSContentOffset(100, 300, 1000, 800, false); // 400
529 * ```
530 */
531-export declare const computeIOSContentOffset: (relativeScroll: number, keyboardHeight: number, contentHeight: number, layoutHeight: number, inverted: boolean, totalPaddingForMaxScroll?: number) => number;
532+export declare const computeIOSContentOffset: (relativeScroll: number, keyboardHeight: number, contentHeight: number, layoutHeight: number, inverted: boolean, totalPaddingForMaxScroll?: number, startInsetCompensation?: number) => number;
533diff --git a/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts b/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts
534index 8d358bc..911f3d9 100644
535--- a/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts
536+++ b/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts
537@@ -11,6 +11,10 @@ type UseChatKeyboardOptions = {
538 blankSpace: SharedValue<number>;
539 /** Extra content padding shared value — needed on iOS to correctly clamp contentOffset. */
540 extraContentPadding: SharedValue<number>;
541+ /** Safe-area extra beyond raw contentInset. Offset math only. */
542+ adjustedInsetCompensation: number;
543+ /** Leading inset UIKit adds beyond the raw contentInset. Offset math only. */
544+ adjustedStartInsetCompensation: number;
545 };
546 type UseChatKeyboardReturn = {
547 /** Extra scrollable space (= keyboard height). Used as contentInset on iOS, contentInsetBottom/contentInsetTop on Android. */
548diff --git a/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts b/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts
549index ec73f70..45b3874 100644
550--- a/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts
551+++ b/lib/typescript/components/KeyboardChatScrollView/useExtraContentPadding/index.d.ts
552@@ -8,6 +8,10 @@ type UseExtraContentPaddingOptions = {
553 keyboardPadding: SharedValue<number>;
554 /** Minimum inset floor — used to absorb keyboard and extraContentPadding changes. */
555 blankSpace: SharedValue<number>;
556+ /** Safe-area extra beyond raw contentInset. Offset math only. */
557+ adjustedInsetCompensation: number;
558+ /** Leading inset UIKit adds beyond raw contentInset. Offset math only. */
559+ adjustedStartInsetCompensation: number;
560 /** Current vertical scroll offset. */
561 scroll: SharedValue<number>;
562 /** Visible viewport dimensions. */
563diff --git a/src/components/KeyboardChatScrollView/index.tsx b/src/components/KeyboardChatScrollView/index.tsx
564index 935bc71..d411dc4 100644
565--- a/src/components/KeyboardChatScrollView/index.tsx
566+++ b/src/components/KeyboardChatScrollView/index.tsx
567@@ -1,9 +1,13 @@
568 import React, { forwardRef, useCallback, useMemo } from "react";
569-import { StyleSheet } from "react-native";
570-import { makeMutable, useAnimatedRef } from "react-native-reanimated";
571+import { Platform, StyleSheet } from "react-native";
572+import { makeMutable, runOnJS, useAnimatedRef } from "react-native-reanimated";
573 import Reanimated from "react-native-reanimated";
574
575-import { useAnimatedStyle, useDerivedValue } from "../../reanimated";
576+import {
577+ useAnimatedReaction,
578+ useAnimatedStyle,
579+ useDerivedValue,
580+} from "../../reanimated";
581 import useCombinedRef from "../hooks/useCombinedRef";
582 import ScrollViewWithBottomPadding from "../ScrollViewWithBottomPadding";
583
584@@ -35,9 +39,12 @@ const KeyboardChatScrollView: React.ForwardRefExoticComponent<
585 offset = 0,
586 extraContentPadding = ZERO_CONTENT_PADDING,
587 blankSpace = ZERO_BLANK_SPACE,
588+ adjustedInsetCompensation = 0,
589+ adjustedStartInsetCompensation = 0,
590 applyWorkaroundForContentInsetHitTestBug = false,
591 onLayout: onLayoutProp,
592 onContentSizeChange: onContentSizeChangeProp,
593+ onContentInsetChange,
594 onEndVisible,
595 ...rest
596 },
597@@ -64,6 +71,8 @@ const KeyboardChatScrollView: React.ForwardRefExoticComponent<
598 offset,
599 blankSpace,
600 extraContentPadding,
601+ adjustedInsetCompensation,
602+ adjustedStartInsetCompensation,
603 initialContentOffsetY: rest.contentOffset?.y,
604 });
605
606@@ -72,6 +81,8 @@ const KeyboardChatScrollView: React.ForwardRefExoticComponent<
607 extraContentPadding,
608 keyboardPadding: padding,
609 blankSpace,
610+ adjustedInsetCompensation,
611+ adjustedStartInsetCompensation,
612 scroll,
613 layout,
614 size,
615@@ -109,13 +120,40 @@ const KeyboardChatScrollView: React.ForwardRefExoticComponent<
616 ),
617 );
618
619- // Scroll indicator inset = keyboard + extraContentPadding (excludes blankSpace).
620- // Apps that render into the unsafe area can supply a negative
621- // scrollIndicatorInsets adjustment at the application layer.
622- const indicatorPadding = useDerivedValue(
623- () => padding.value + extraContentPadding.value,
624+ // iOS applies the destination contentInset and contentOffset together at
625+ // keyboard-animation start. Keep that native target behavior, but report
626+ // the presentation height so virtualized-list layout follows the keyboard.
627+ const reportedPadding = useDerivedValue(() =>
628+ Platform.OS === "ios"
629+ ? Math.min(
630+ layout.value.height,
631+ Math.max(
632+ blankSpace.value,
633+ currentHeight.value + extraContentPadding.value,
634+ ),
635+ )
636+ : totalPadding.value,
637 );
638
639+ // Mirror the effective bottom padding (keyboard + composer + blank floor)
640+ // to the consumer — a virtualized list needs it in its own scroll math or
641+ // its end/maintain targets point at the under-the-keyboard resting offset.
642+ useAnimatedReaction(
643+ () => reportedPadding.value,
644+ (current, previous) => {
645+ if (onContentInsetChange && current !== previous) {
646+ runOnJS(onContentInsetChange)({ bottom: current });
647+ }
648+ },
649+ [onContentInsetChange],
650+ );
651+
652+ // Scroll indicator inset = keyboard only (excludes extraContentPadding and
653+ // blankSpace): with a floating composer the indicator track should run the
654+ // full height of the scroll view, behind the composer, like iOS Messages.
655+ // The keyboard still lifts it so it never disappears under the keyboard.
656+ const indicatorPadding = useDerivedValue(() => padding.value);
657+
658 const onLayout = useCallback(
659 (e: LayoutChangeEvent) => {
660 onLayoutInternal(e);
661diff --git a/src/components/KeyboardChatScrollView/types.ts b/src/components/KeyboardChatScrollView/types.ts
662index b7c98c8..e1012a8 100644
663--- a/src/components/KeyboardChatScrollView/types.ts
664+++ b/src/components/KeyboardChatScrollView/types.ts
665@@ -93,6 +93,17 @@ export type KeyboardChatScrollViewProps = {
666 * Default is `undefined` (equivalent to `0` — no minimum floor).
667 */
668 blankSpace?: SharedValue<number>;
669+ /**
670+ * Extra bottom inset UIKit adds on top of the raw `contentInset` this
671+ * component writes (e.g. the home-indicator safe area under
672+ * `contentInsetAdjustmentBehavior="automatic"`). Used ONLY in scroll-offset
673+ * math (max scroll / end pinning) — never written into `contentInset`.
674+ *
675+ * Default is `0`.
676+ */
677+ adjustedInsetCompensation?: number;
678+ /** Leading inset UIKit adds outside raw contentInset. Offset math only. */
679+ adjustedStartInsetCompensation?: number;
680 /**
681 * Fires whenever the effective content inset changes — the static `contentInset`
682 * prop combined with the dynamic keyboard-driven padding.
683diff --git a/src/components/KeyboardChatScrollView/useChatKeyboard/helpers.ts b/src/components/KeyboardChatScrollView/useChatKeyboard/helpers.ts
684index 37eacd1..3d77ab2 100644
685--- a/src/components/KeyboardChatScrollView/useChatKeyboard/helpers.ts
686+++ b/src/components/KeyboardChatScrollView/useChatKeyboard/helpers.ts
687@@ -245,6 +245,7 @@ export const computeIOSContentOffset = (
688 layoutHeight: number,
689 inverted: boolean,
690 totalPaddingForMaxScroll?: number,
691+ startInsetCompensation: number = 0,
692 ): number => {
693 "worklet";
694
695@@ -262,7 +263,14 @@ export const computeIOSContentOffset = (
696 );
697 }
698
699- const maxScroll = Math.max(contentHeight - layoutHeight + paddingForMax, 0);
700+ const minScroll = -startInsetCompensation;
701+ const maxScroll = Math.max(
702+ contentHeight - layoutHeight + paddingForMax,
703+ minScroll,
704+ );
705
706- return Math.min(Math.max(keyboardHeight + relativeScroll, 0), maxScroll);
707+ return Math.min(
708+ Math.max(keyboardHeight + relativeScroll, minScroll),
709+ maxScroll,
710+ );
711 };
712diff --git a/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts b/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts
713index 1ae9b81..208505b 100644
714--- a/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts
715+++ b/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts
716@@ -43,6 +43,8 @@ function useChatKeyboard(
717 offset,
718 blankSpace,
719 extraContentPadding,
720+ adjustedInsetCompensation,
721+ adjustedStartInsetCompensation,
722 } = options;
723
724 const padding = useSharedValue(0);
725@@ -80,6 +82,10 @@ function useChatKeyboard(
726 offset,
727 );
728
729+ if (e.duration === 0) {
730+ currentHeight.value = effective;
731+ }
732+
733 const atEnd = isScrollAtEnd(
734 scroll.value,
735 layout.value.height,
736@@ -105,10 +111,12 @@ function useChatKeyboard(
737 effective,
738 minimumPaddingAbsorbed,
739 );
740- const actualTotalPadding = Math.max(
741- blankSpace.value,
742- effective + extraContentPadding.value,
743- );
744+ // UIKit adds adjustedInsetCompensation (safe area) on top of the raw
745+ // inset; include it here so end/max-scroll targets match the real
746+ // resting offsets.
747+ const actualTotalPadding =
748+ Math.max(blankSpace.value, effective + extraContentPadding.value) +
749+ adjustedInsetCompensation;
750
751 // `onInteractive` owns the native scroll offset. When its final
752 // keyboardWillHide event arrives, consume the marker so this
753@@ -142,11 +150,11 @@ function useChatKeyboard(
754 } else {
755 const maxScroll = Math.max(
756 size.value.height - layout.value.height + actualTotalPadding,
757- 0,
758+ -adjustedStartInsetCompensation,
759 );
760
761 contentOffsetY.value = Math.max(
762- 0,
763+ -adjustedStartInsetCompensation,
764 Math.min(scroll.value, maxScroll),
765 );
766 }
767@@ -177,11 +185,11 @@ function useChatKeyboard(
768 } else {
769 const maxScroll = Math.max(
770 size.value.height - layout.value.height + actualTotalPadding,
771- 0,
772+ -adjustedStartInsetCompensation,
773 );
774
775 contentOffsetY.value = Math.max(
776- 0,
777+ -adjustedStartInsetCompensation,
778 Math.min(scroll.value, maxScroll),
779 );
780 }
781@@ -231,17 +239,36 @@ function useChatKeyboard(
782 layout.value.height,
783 inverted,
784 actualTotalPadding,
785+ adjustedStartInsetCompensation,
786 );
787 },
788- onInteractive: () => {
789+ onMove: (e) => {
790 "worklet";
791
792- isInteractiveDismissal.value = true;
793+ if (freeze.value) {
794+ return;
795+ }
796+
797+ currentHeight.value = getEffectiveHeight(
798+ e.height,
799+ targetKeyboardHeight.value,
800+ offset,
801+ );
802 },
803- onMove: () => {
804+ onInteractive: (e) => {
805 "worklet";
806
807- // iOS doesn't need per-frame updates (contentOffset handles it)
808+ isInteractiveDismissal.value = true;
809+
810+ if (freeze.value) {
811+ return;
812+ }
813+
814+ currentHeight.value = getEffectiveHeight(
815+ e.height,
816+ targetKeyboardHeight.value,
817+ offset,
818+ );
819 },
820 onEnd: (e) => {
821 "worklet";
822@@ -256,10 +283,18 @@ function useChatKeyboard(
823 offset,
824 );
825
826+ currentHeight.value = effective;
827 padding.value = effective;
828 },
829 },
830- [inverted, keyboardLiftBehavior, offset, extraContentPadding],
831+ [
832+ inverted,
833+ keyboardLiftBehavior,
834+ offset,
835+ extraContentPadding,
836+ adjustedInsetCompensation,
837+ adjustedStartInsetCompensation,
838+ ],
839 );
840
841 return {
842diff --git a/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts b/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts
843index f89b7c8..02e0e19 100644
844--- a/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts
845+++ b/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts
846@@ -13,6 +13,10 @@ type UseChatKeyboardOptions = {
847 blankSpace: SharedValue<number>;
848 /** Extra content padding shared value — needed on iOS to correctly clamp contentOffset. */
849 extraContentPadding: SharedValue<number>;
850+ /** Extra bottom inset UIKit adds beyond the raw contentInset (safe area). Offset math only. */
851+ adjustedInsetCompensation: number;
852+ /** Leading inset UIKit adds beyond the raw contentInset. Offset math only. */
853+ adjustedStartInsetCompensation: number;
854 };
855
856 type UseChatKeyboardReturn = {
857diff --git a/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts b/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts
858index de7d6f7..631cdfb 100644
859--- a/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts
860+++ b/src/components/KeyboardChatScrollView/useExtraContentPadding/index.ts
861@@ -17,6 +17,10 @@ type UseExtraContentPaddingOptions = {
862 keyboardPadding: SharedValue<number>;
863 /** Minimum inset floor — used to absorb keyboard and extraContentPadding changes. */
864 blankSpace: SharedValue<number>;
865+ /** Extra bottom inset UIKit adds beyond the raw contentInset (safe area). Offset math only. */
866+ adjustedInsetCompensation: number;
867+ /** Leading inset UIKit adds beyond raw contentInset. Offset math only. */
868+ adjustedStartInsetCompensation: number;
869 /** Current vertical scroll offset. */
870 scroll: SharedValue<number>;
871 /** Visible viewport dimensions. */
872@@ -52,6 +56,8 @@ function useExtraContentPadding(options: UseExtraContentPaddingOptions): void {
873 extraContentPadding,
874 keyboardPadding,
875 blankSpace,
876+ adjustedInsetCompensation,
877+ adjustedStartInsetCompensation,
878 scroll,
879 layout,
880 size,
881@@ -73,8 +79,13 @@ function useExtraContentPadding(options: UseExtraContentPaddingOptions): void {
882 // otherwise the native ScrollView clamps to the old range.
883 requestAnimationFrame(() => {
884 // check that view is still mounted and ref is actual
885- // otherwise it may lead to a crash
886- if (!scrollViewRef()) {
887+ // otherwise it may lead to a crash. Reanimated 4.7+ passes the
888+ // ref to the UI runtime as a shareable holding the node in `.value`.
889+ const node =
890+ typeof scrollViewRef === "function"
891+ ? scrollViewRef()
892+ : (scrollViewRef as unknown as { value: unknown }).value;
893+ if (!node) {
894 return;
895 }
896 scrollTo(scrollViewRef, 0, target, false);
897@@ -100,14 +111,12 @@ function useExtraContentPadding(options: UseExtraContentPaddingOptions): void {
898 }
899
900 // Compute effective delta considering blankSpace floor
901- const previousTotal = Math.max(
902- blankSpace.value,
903- keyboardPadding.value + previous,
904- );
905- const currentTotal = Math.max(
906- blankSpace.value,
907- keyboardPadding.value + current,
908- );
909+ const previousTotal =
910+ Math.max(blankSpace.value, keyboardPadding.value + previous) +
911+ adjustedInsetCompensation;
912+ const currentTotal =
913+ Math.max(blankSpace.value, keyboardPadding.value + current) +
914+ adjustedInsetCompensation;
915 const effectiveDelta = currentTotal - previousTotal;
916
917 if (effectiveDelta === 0) {
918@@ -140,22 +149,28 @@ function useExtraContentPadding(options: UseExtraContentPaddingOptions): void {
919
920 scrollToTarget(target);
921 } else {
922+ const minScroll = -adjustedStartInsetCompensation;
923 const maxScroll = Math.max(
924 size.value.height - layout.value.height + currentTotal,
925- 0,
926+ minScroll,
927 );
928- // Clamp at 0 as well: when the content is shorter than the viewport a
929- // shrinking padding makes `effectiveDelta` negative while `scroll.value`
930- // is already 0, so the target would go below the top of the content.
931+ // Clamp at the top as well: when the content is shorter than the
932+ // viewport a shrinking padding makes `effectiveDelta` negative while
933+ // `scroll.value` is already at the top.
934 const target = Math.max(
935+ minScroll,
936 Math.min(scroll.value + effectiveDelta, maxScroll),
937- 0,
938 );
939
940 scrollToTarget(target);
941 }
942 },
943- [inverted, keyboardLiftBehavior],
944+ [
945+ inverted,
946+ keyboardLiftBehavior,
947+ adjustedInsetCompensation,
948+ adjustedStartInsetCompensation,
949+ ],
950 );
951 }
952