react-native-keyboard-controller 1.21.13 → 1.21.14

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.
@@ -337,6 +337,12 @@ internal class KeyboardAnimationController {
337
337
  currentSpringAnimation = null
338
338
 
339
339
  pendingRequestOnReady = null
340
+
341
+ // `animateToFinish` clears this flag before finishing the controller, but gestures that
342
+ // end via `cancel()`/`onFinished`/`onCancelled` never pass through it. A stranded `true`
343
+ // makes `KeyboardAnimationCallback` treat the keyboard as moving forever, which disables
344
+ // its desynchronized-state recovery for the rest of the process lifetime.
345
+ InteractiveKeyboardProvider.isInteractive = false
340
346
  }
341
347
 
342
348
  /**
@@ -5,6 +5,7 @@ import android.view.MotionEvent
5
5
  import android.view.View
6
6
  import android.view.ViewGroup
7
7
  import android.widget.ScrollView
8
+ import androidx.core.widget.NestedScrollView
8
9
  import com.facebook.react.uimanager.ThemedReactContext
9
10
  import com.facebook.react.views.view.ReactViewGroup
10
11
  import com.reactnativekeyboardcontroller.extensions.px
@@ -100,7 +101,7 @@ class ClippingScrollViewDecoratorView(
100
101
  }
101
102
 
102
103
  private fun shouldUsePaddingScrollWorkaround(
103
- scrollView: ScrollView,
104
+ scrollView: ViewGroup,
104
105
  event: MotionEvent,
105
106
  ): Boolean {
106
107
  val contentView = scrollView.getChildAt(0) ?: return false
@@ -115,7 +116,7 @@ class ClippingScrollViewDecoratorView(
115
116
  }
116
117
 
117
118
  private fun dispatchWithExpandedContentRange(
118
- scrollView: ScrollView,
119
+ scrollView: ViewGroup,
119
120
  event: MotionEvent,
120
121
  ): Boolean {
121
122
  val contentView = scrollView.getChildAt(0)
@@ -136,7 +137,7 @@ class ClippingScrollViewDecoratorView(
136
137
  }
137
138
 
138
139
  private fun isTouchInScrollContent(
139
- scrollView: ScrollView,
140
+ scrollView: ViewGroup,
140
141
  event: MotionEvent,
141
142
  ): Boolean {
142
143
  val contentView = scrollView.getChildAt(0) ?: return false
@@ -158,11 +159,15 @@ class ClippingScrollViewDecoratorView(
158
159
  )
159
160
  }
160
161
 
161
- private fun findScrollView(view: View?): ScrollView? {
162
- var result: ScrollView? = null
162
+ private fun findScrollView(view: View?): ViewGroup? {
163
+ var result: ViewGroup? = null
163
164
 
164
- if (view is ScrollView) {
165
- result = view
165
+ // Match NestedScrollView too: with React Native's `useNestedScrollViewAndroid`
166
+ // feature flag (RN 0.85+), ScrollView renders as a NestedScrollView subclass
167
+ // (a FrameLayout, not an android.widget.ScrollView). Both extend the scroll
168
+ // range via bottom padding + clipToPadding=false the same way.
169
+ if (view is ScrollView || view is NestedScrollView) {
170
+ result = view as ViewGroup
166
171
  } else if (view is ViewGroup) {
167
172
  var i = 0
168
173
  while (i < view.childCount && result == null) {
@@ -14,7 +14,7 @@ public extension UIWindow {
14
14
  static let sharedKeyboardWindowObserver = KeyboardWindowObserver()
15
15
 
16
16
  class KeyboardWindowObserver: NSObject {
17
- private weak var keyboardWindow: UIWindow?
17
+ weak var keyboardWindow: UIWindow?
18
18
 
19
19
  override init() {
20
20
  super.init()
@@ -45,6 +45,10 @@ public extension UIWindow {
45
45
  }
46
46
  }
47
47
 
48
+ static var keyboardWindow: UIWindow? {
49
+ return sharedKeyboardWindowObserver.keyboardWindow
50
+ }
51
+
48
52
  static var topWindow: UIWindow? {
49
53
  return sharedKeyboardWindowObserver.getTopWindow()
50
54
  }
@@ -12,6 +12,7 @@ var _ScrollViewWithBottomPadding = _interopRequireDefault(require("../ScrollView
12
12
  var _useChatKeyboard = require("./useChatKeyboard");
13
13
  var _useEndVisible = require("./useEndVisible");
14
14
  var _useExtraContentPadding = require("./useExtraContentPadding");
15
+ var _useFrozenPadding = require("./useFrozenPadding");
15
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
17
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
17
18
  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); }
@@ -65,6 +66,11 @@ const KeyboardChatScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
65
66
  keyboardLiftBehavior,
66
67
  freeze: freezeSV
67
68
  });
69
+ (0, _useFrozenPadding.useFrozenPadding)({
70
+ freeze: freezeSV,
71
+ offset,
72
+ padding
73
+ });
68
74
  (0, _useEndVisible.useEndVisible)({
69
75
  scroll,
70
76
  layout,
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_useCombinedRef","_interopRequireDefault","_ScrollViewWithBottomPadding","_useChatKeyboard","_useEndVisible","_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","onEndVisible","rest","ref","scrollViewRef","useAnimatedRef","onRef","useCombinedRef","freezeSV","useDerivedValue","value","padding","currentHeight","contentOffsetY","scroll","layout","size","onLayoutInternal","onContentSizeChangeInternal","useChatKeyboard","useExtraContentPadding","keyboardPadding","useEndVisible","totalPadding","Math","min","height","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 { useEndVisible } from \"./useEndVisible\";\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 onEndVisible,\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 useEndVisible({\n scroll,\n layout,\n size,\n inverted,\n onEndVisible,\n });\n\n // intentionally clamp `blankSpace` at one ScrollView viewport. The Android\n // `ClippingScrollView` workaround temporarily substitutes padding/range\n // during touch handling, and oversized blank ranges can de-sync during fast\n // momentum gestures. One viewport is enough for the short-content case;\n // larger values only allow scrolling to a fully blank screen which is not\n // the use case for this library. If you found this comment and it causes\n // a bug for you, please open an issue.\n const totalPadding = useDerivedValue(() =>\n Math.min(\n layout.value.height,\n Math.max(blankSpace.value, padding.value + extraContentPadding.value),\n ),\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","_useEndVisible","_useExtraContentPadding","_useFrozenPadding","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","onEndVisible","rest","ref","scrollViewRef","useAnimatedRef","onRef","useCombinedRef","freezeSV","useDerivedValue","value","padding","currentHeight","contentOffsetY","scroll","layout","size","onLayoutInternal","onContentSizeChangeInternal","useChatKeyboard","useExtraContentPadding","keyboardPadding","useFrozenPadding","useEndVisible","totalPadding","Math","min","height","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 { useEndVisible } from \"./useEndVisible\";\nimport { useExtraContentPadding } from \"./useExtraContentPadding\";\nimport { useFrozenPadding } from \"./useFrozenPadding\";\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 onEndVisible,\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 useFrozenPadding({\n freeze: freezeSV,\n offset,\n padding,\n });\n\n useEndVisible({\n scroll,\n layout,\n size,\n inverted,\n onEndVisible,\n });\n\n // intentionally clamp `blankSpace` at one ScrollView viewport. The Android\n // `ClippingScrollView` workaround temporarily substitutes padding/range\n // during touch handling, and oversized blank ranges can de-sync during fast\n // momentum gestures. One viewport is enough for the short-content case;\n // larger values only allow scrolling to a fully blank screen which is not\n // the use case for this library. If you found this comment and it causes\n // a bug for you, please open an issue.\n const totalPadding = useDerivedValue(() =>\n Math.min(\n layout.value.height,\n Math.max(blankSpace.value, padding.value + extraContentPadding.value),\n ),\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":[]}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useFrozenPadding = useFrozenPadding;
7
+ var _reactNativeReanimated = require("react-native-reanimated");
8
+ var _hooks = require("../../../hooks");
9
+ var _helpers = require("../useChatKeyboard/helpers");
10
+ /**
11
+ * Hook that reconciles keyboard padding after a frozen interval.
12
+ *
13
+ * `useChatKeyboard` handlers skip all writes while `freeze` is enabled, so if
14
+ * the keyboard opens or closes during the frozen interval `padding` keeps a
15
+ * stale value (e.g. the open-keyboard height after a frozen dismissal). This
16
+ * hook observes keyboard events independently of `freeze` and recomputes the
17
+ * padding from the latest observed keyboard height as soon as `freeze`
18
+ * transitions back to `false`.
19
+ *
20
+ * @param options - Keyboard padding shared values plus the scroll view `offset`.
21
+ * @param options.freeze - When `true`, keyboard-driven layout writes are skipped.
22
+ * @param options.offset - The distance between the bottom of the screen and the `ScrollView`.
23
+ * @param options.padding - Keyboard-driven padding managed by `useChatKeyboard`.
24
+ * @example
25
+ * ```ts
26
+ * useFrozenPadding({ freeze, offset, padding });
27
+ * ```
28
+ */
29
+ function useFrozenPadding({
30
+ freeze,
31
+ offset,
32
+ padding
33
+ }) {
34
+ const lastHeight = (0, _reactNativeReanimated.useSharedValue)(0);
35
+ const targetKeyboardHeight = (0, _reactNativeReanimated.useSharedValue)(0);
36
+ (0, _hooks.useKeyboardHandler)({
37
+ onStart: e => {
38
+ "worklet";
39
+
40
+ if (e.height > 0) {
41
+ // eslint-disable-next-line react-compiler/react-compiler
42
+ targetKeyboardHeight.value = e.height;
43
+ }
44
+ },
45
+ onMove: e => {
46
+ "worklet";
47
+
48
+ lastHeight.value = e.height;
49
+ },
50
+ onEnd: e => {
51
+ "worklet";
52
+
53
+ lastHeight.value = e.height;
54
+ }
55
+ }, []);
56
+ (0, _reactNativeReanimated.useAnimatedReaction)(() => freeze.value, (isFrozen, wasFrozen) => {
57
+ if (!isFrozen && wasFrozen === true) {
58
+ padding.value = (0, _helpers.getEffectiveHeight)(lastHeight.value, targetKeyboardHeight.value, offset);
59
+ }
60
+ }, [offset]);
61
+ }
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNativeReanimated","require","_hooks","_helpers","useFrozenPadding","freeze","offset","padding","lastHeight","useSharedValue","targetKeyboardHeight","useKeyboardHandler","onStart","e","height","value","onMove","onEnd","useAnimatedReaction","isFrozen","wasFrozen","getEffectiveHeight"],"sources":["index.ts"],"sourcesContent":["import { useAnimatedReaction, useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport { getEffectiveHeight } from \"../useChatKeyboard/helpers\";\n\nimport type { SharedValue } from \"react-native-reanimated\";\n\ntype UseFrozenPaddingOptions = {\n /** When `true`, keyboard-driven layout writes are skipped. */\n freeze: SharedValue<boolean>;\n /** The distance between the bottom of the screen and the `ScrollView`. */\n offset: number;\n /** Keyboard-driven padding managed by `useChatKeyboard`. */\n padding: SharedValue<number>;\n};\n\n/**\n * Hook that reconciles keyboard padding after a frozen interval.\n *\n * `useChatKeyboard` handlers skip all writes while `freeze` is enabled, so if\n * the keyboard opens or closes during the frozen interval `padding` keeps a\n * stale value (e.g. the open-keyboard height after a frozen dismissal). This\n * hook observes keyboard events independently of `freeze` and recomputes the\n * padding from the latest observed keyboard height as soon as `freeze`\n * transitions back to `false`.\n *\n * @param options - Keyboard padding shared values plus the scroll view `offset`.\n * @param options.freeze - When `true`, keyboard-driven layout writes are skipped.\n * @param options.offset - The distance between the bottom of the screen and the `ScrollView`.\n * @param options.padding - Keyboard-driven padding managed by `useChatKeyboard`.\n * @example\n * ```ts\n * useFrozenPadding({ freeze, offset, padding });\n * ```\n */\nfunction useFrozenPadding({\n freeze,\n offset,\n padding,\n}: UseFrozenPaddingOptions): void {\n const lastHeight = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n lastHeight.value = e.height;\n },\n onEnd: (e) => {\n \"worklet\";\n\n lastHeight.value = e.height;\n },\n },\n [],\n );\n\n useAnimatedReaction(\n () => freeze.value,\n (isFrozen, wasFrozen) => {\n if (!isFrozen && wasFrozen === true) {\n padding.value = getEffectiveHeight(\n lastHeight.value,\n targetKeyboardHeight.value,\n offset,\n );\n }\n },\n [offset],\n );\n}\n\nexport { useFrozenPadding };\n"],"mappings":";;;;;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAEA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,QAAA,GAAAF,OAAA;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASG,gBAAgBA,CAAC;EACxBC,MAAM;EACNC,MAAM;EACNC;AACuB,CAAC,EAAQ;EAChC,MAAMC,UAAU,GAAG,IAAAC,qCAAc,EAAC,CAAC,CAAC;EACpC,MAAMC,oBAAoB,GAAG,IAAAD,qCAAc,EAAC,CAAC,CAAC;EAE9C,IAAAE,yBAAkB,EAChB;IACEC,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACC,MAAM,GAAG,CAAC,EAAE;QAChB;QACAJ,oBAAoB,CAACK,KAAK,GAAGF,CAAC,CAACC,MAAM;MACvC;IACF,CAAC;IACDE,MAAM,EAAGH,CAAC,IAAK;MACb,SAAS;;MAETL,UAAU,CAACO,KAAK,GAAGF,CAAC,CAACC,MAAM;IAC7B,CAAC;IACDG,KAAK,EAAGJ,CAAC,IAAK;MACZ,SAAS;;MAETL,UAAU,CAACO,KAAK,GAAGF,CAAC,CAACC,MAAM;IAC7B;EACF,CAAC,EACD,EACF,CAAC;EAED,IAAAI,0CAAmB,EACjB,MAAMb,MAAM,CAACU,KAAK,EAClB,CAACI,QAAQ,EAAEC,SAAS,KAAK;IACvB,IAAI,CAACD,QAAQ,IAAIC,SAAS,KAAK,IAAI,EAAE;MACnCb,OAAO,CAACQ,KAAK,GAAG,IAAAM,2BAAkB,EAChCb,UAAU,CAACO,KAAK,EAChBL,oBAAoB,CAACK,KAAK,EAC1BT,MACF,CAAC;IACH;EACF,CAAC,EACD,CAACA,MAAM,CACT,CAAC;AACH","ignoreList":[]}
@@ -8,6 +8,7 @@ import ScrollViewWithBottomPadding from "../ScrollViewWithBottomPadding";
8
8
  import { useChatKeyboard } from "./useChatKeyboard";
9
9
  import { useEndVisible } from "./useEndVisible";
10
10
  import { useExtraContentPadding } from "./useExtraContentPadding";
11
+ import { useFrozenPadding } from "./useFrozenPadding";
11
12
  const ZERO_CONTENT_PADDING = makeMutable(0);
12
13
  const ZERO_BLANK_SPACE = makeMutable(0);
13
14
  const KeyboardChatScrollView = /*#__PURE__*/forwardRef(({
@@ -58,6 +59,11 @@ const KeyboardChatScrollView = /*#__PURE__*/forwardRef(({
58
59
  keyboardLiftBehavior,
59
60
  freeze: freezeSV
60
61
  });
62
+ useFrozenPadding({
63
+ freeze: freezeSV,
64
+ offset,
65
+ padding
66
+ });
61
67
  useEndVisible({
62
68
  scroll,
63
69
  layout,
@@ -1 +1 @@
1
- {"version":3,"names":["React","forwardRef","useCallback","useMemo","StyleSheet","makeMutable","useAnimatedRef","useAnimatedStyle","useDerivedValue","Reanimated","useCombinedRef","ScrollViewWithBottomPadding","useChatKeyboard","useEndVisible","useExtraContentPadding","ZERO_CONTENT_PADDING","ZERO_BLANK_SPACE","KeyboardChatScrollView","children","ScrollViewComponent","ScrollView","inverted","keyboardLiftBehavior","freeze","offset","extraContentPadding","blankSpace","applyWorkaroundForContentInsetHitTestBug","onLayout","onLayoutProp","onContentSizeChange","onContentSizeChangeProp","onEndVisible","rest","ref","scrollViewRef","onRef","freezeSV","value","padding","currentHeight","contentOffsetY","scroll","layout","size","onLayoutInternal","onContentSizeChangeInternal","keyboardPadding","totalPadding","Math","min","height","max","indicatorPadding","e","w","h","commitStyle","transform","translateY","commit","styles","commitView","createElement","Fragment","_extends","bottomPadding","scrollIndicatorPadding","View","style","create","display","position"],"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 { useEndVisible } from \"./useEndVisible\";\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 onEndVisible,\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 useEndVisible({\n scroll,\n layout,\n size,\n inverted,\n onEndVisible,\n });\n\n // intentionally clamp `blankSpace` at one ScrollView viewport. The Android\n // `ClippingScrollView` workaround temporarily substitutes padding/range\n // during touch handling, and oversized blank ranges can de-sync during fast\n // momentum gestures. One viewport is enough for the short-content case;\n // larger values only allow scrolling to a fully blank screen which is not\n // the use case for this library. If you found this comment and it causes\n // a bug for you, please open an issue.\n const totalPadding = useDerivedValue(() =>\n Math.min(\n layout.value.height,\n Math.max(blankSpace.value, padding.value + extraContentPadding.value),\n ),\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","forwardRef","useCallback","useMemo","StyleSheet","makeMutable","useAnimatedRef","useAnimatedStyle","useDerivedValue","Reanimated","useCombinedRef","ScrollViewWithBottomPadding","useChatKeyboard","useEndVisible","useExtraContentPadding","useFrozenPadding","ZERO_CONTENT_PADDING","ZERO_BLANK_SPACE","KeyboardChatScrollView","children","ScrollViewComponent","ScrollView","inverted","keyboardLiftBehavior","freeze","offset","extraContentPadding","blankSpace","applyWorkaroundForContentInsetHitTestBug","onLayout","onLayoutProp","onContentSizeChange","onContentSizeChangeProp","onEndVisible","rest","ref","scrollViewRef","onRef","freezeSV","value","padding","currentHeight","contentOffsetY","scroll","layout","size","onLayoutInternal","onContentSizeChangeInternal","keyboardPadding","totalPadding","Math","min","height","max","indicatorPadding","e","w","h","commitStyle","transform","translateY","commit","styles","commitView","createElement","Fragment","_extends","bottomPadding","scrollIndicatorPadding","View","style","create","display","position"],"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 { useEndVisible } from \"./useEndVisible\";\nimport { useExtraContentPadding } from \"./useExtraContentPadding\";\nimport { useFrozenPadding } from \"./useFrozenPadding\";\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 onEndVisible,\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 useFrozenPadding({\n freeze: freezeSV,\n offset,\n padding,\n });\n\n useEndVisible({\n scroll,\n layout,\n size,\n inverted,\n onEndVisible,\n });\n\n // intentionally clamp `blankSpace` at one ScrollView viewport. The Android\n // `ClippingScrollView` workaround temporarily substitutes padding/range\n // during touch handling, and oversized blank ranges can de-sync during fast\n // momentum gestures. One viewport is enough for the short-content case;\n // larger values only allow scrolling to a fully blank screen which is not\n // the use case for this library. If you found this comment and it causes\n // a bug for you, please open an issue.\n const totalPadding = useDerivedValue(() =>\n Math.min(\n layout.value.height,\n Math.max(blankSpace.value, padding.value + extraContentPadding.value),\n ),\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":[]}
@@ -0,0 +1,57 @@
1
+ import { useAnimatedReaction, useSharedValue } from "react-native-reanimated";
2
+ import { useKeyboardHandler } from "../../../hooks";
3
+ import { getEffectiveHeight } from "../useChatKeyboard/helpers";
4
+ /**
5
+ * Hook that reconciles keyboard padding after a frozen interval.
6
+ *
7
+ * `useChatKeyboard` handlers skip all writes while `freeze` is enabled, so if
8
+ * the keyboard opens or closes during the frozen interval `padding` keeps a
9
+ * stale value (e.g. the open-keyboard height after a frozen dismissal). This
10
+ * hook observes keyboard events independently of `freeze` and recomputes the
11
+ * padding from the latest observed keyboard height as soon as `freeze`
12
+ * transitions back to `false`.
13
+ *
14
+ * @param options - Keyboard padding shared values plus the scroll view `offset`.
15
+ * @param options.freeze - When `true`, keyboard-driven layout writes are skipped.
16
+ * @param options.offset - The distance between the bottom of the screen and the `ScrollView`.
17
+ * @param options.padding - Keyboard-driven padding managed by `useChatKeyboard`.
18
+ * @example
19
+ * ```ts
20
+ * useFrozenPadding({ freeze, offset, padding });
21
+ * ```
22
+ */
23
+ function useFrozenPadding({
24
+ freeze,
25
+ offset,
26
+ padding
27
+ }) {
28
+ const lastHeight = useSharedValue(0);
29
+ const targetKeyboardHeight = useSharedValue(0);
30
+ useKeyboardHandler({
31
+ onStart: e => {
32
+ "worklet";
33
+
34
+ if (e.height > 0) {
35
+ // eslint-disable-next-line react-compiler/react-compiler
36
+ targetKeyboardHeight.value = e.height;
37
+ }
38
+ },
39
+ onMove: e => {
40
+ "worklet";
41
+
42
+ lastHeight.value = e.height;
43
+ },
44
+ onEnd: e => {
45
+ "worklet";
46
+
47
+ lastHeight.value = e.height;
48
+ }
49
+ }, []);
50
+ useAnimatedReaction(() => freeze.value, (isFrozen, wasFrozen) => {
51
+ if (!isFrozen && wasFrozen === true) {
52
+ padding.value = getEffectiveHeight(lastHeight.value, targetKeyboardHeight.value, offset);
53
+ }
54
+ }, [offset]);
55
+ }
56
+ export { useFrozenPadding };
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useAnimatedReaction","useSharedValue","useKeyboardHandler","getEffectiveHeight","useFrozenPadding","freeze","offset","padding","lastHeight","targetKeyboardHeight","onStart","e","height","value","onMove","onEnd","isFrozen","wasFrozen"],"sources":["index.ts"],"sourcesContent":["import { useAnimatedReaction, useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport { getEffectiveHeight } from \"../useChatKeyboard/helpers\";\n\nimport type { SharedValue } from \"react-native-reanimated\";\n\ntype UseFrozenPaddingOptions = {\n /** When `true`, keyboard-driven layout writes are skipped. */\n freeze: SharedValue<boolean>;\n /** The distance between the bottom of the screen and the `ScrollView`. */\n offset: number;\n /** Keyboard-driven padding managed by `useChatKeyboard`. */\n padding: SharedValue<number>;\n};\n\n/**\n * Hook that reconciles keyboard padding after a frozen interval.\n *\n * `useChatKeyboard` handlers skip all writes while `freeze` is enabled, so if\n * the keyboard opens or closes during the frozen interval `padding` keeps a\n * stale value (e.g. the open-keyboard height after a frozen dismissal). This\n * hook observes keyboard events independently of `freeze` and recomputes the\n * padding from the latest observed keyboard height as soon as `freeze`\n * transitions back to `false`.\n *\n * @param options - Keyboard padding shared values plus the scroll view `offset`.\n * @param options.freeze - When `true`, keyboard-driven layout writes are skipped.\n * @param options.offset - The distance between the bottom of the screen and the `ScrollView`.\n * @param options.padding - Keyboard-driven padding managed by `useChatKeyboard`.\n * @example\n * ```ts\n * useFrozenPadding({ freeze, offset, padding });\n * ```\n */\nfunction useFrozenPadding({\n freeze,\n offset,\n padding,\n}: UseFrozenPaddingOptions): void {\n const lastHeight = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n lastHeight.value = e.height;\n },\n onEnd: (e) => {\n \"worklet\";\n\n lastHeight.value = e.height;\n },\n },\n [],\n );\n\n useAnimatedReaction(\n () => freeze.value,\n (isFrozen, wasFrozen) => {\n if (!isFrozen && wasFrozen === true) {\n padding.value = getEffectiveHeight(\n lastHeight.value,\n targetKeyboardHeight.value,\n offset,\n );\n }\n },\n [offset],\n );\n}\n\nexport { useFrozenPadding };\n"],"mappings":"AAAA,SAASA,mBAAmB,EAAEC,cAAc,QAAQ,yBAAyB;AAE7E,SAASC,kBAAkB,QAAQ,gBAAgB;AACnD,SAASC,kBAAkB,QAAQ,4BAA4B;AAa/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,gBAAgBA,CAAC;EACxBC,MAAM;EACNC,MAAM;EACNC;AACuB,CAAC,EAAQ;EAChC,MAAMC,UAAU,GAAGP,cAAc,CAAC,CAAC,CAAC;EACpC,MAAMQ,oBAAoB,GAAGR,cAAc,CAAC,CAAC,CAAC;EAE9CC,kBAAkB,CAChB;IACEQ,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIA,CAAC,CAACC,MAAM,GAAG,CAAC,EAAE;QAChB;QACAH,oBAAoB,CAACI,KAAK,GAAGF,CAAC,CAACC,MAAM;MACvC;IACF,CAAC;IACDE,MAAM,EAAGH,CAAC,IAAK;MACb,SAAS;;MAETH,UAAU,CAACK,KAAK,GAAGF,CAAC,CAACC,MAAM;IAC7B,CAAC;IACDG,KAAK,EAAGJ,CAAC,IAAK;MACZ,SAAS;;MAETH,UAAU,CAACK,KAAK,GAAGF,CAAC,CAACC,MAAM;IAC7B;EACF,CAAC,EACD,EACF,CAAC;EAEDZ,mBAAmB,CACjB,MAAMK,MAAM,CAACQ,KAAK,EAClB,CAACG,QAAQ,EAAEC,SAAS,KAAK;IACvB,IAAI,CAACD,QAAQ,IAAIC,SAAS,KAAK,IAAI,EAAE;MACnCV,OAAO,CAACM,KAAK,GAAGV,kBAAkB,CAChCK,UAAU,CAACK,KAAK,EAChBJ,oBAAoB,CAACI,KAAK,EAC1BP,MACF,CAAC;IACH;EACF,CAAC,EACD,CAACA,MAAM,CACT,CAAC;AACH;AAEA,SAASF,gBAAgB","ignoreList":[]}
@@ -0,0 +1,30 @@
1
+ import type { SharedValue } from "react-native-reanimated";
2
+ type UseFrozenPaddingOptions = {
3
+ /** When `true`, keyboard-driven layout writes are skipped. */
4
+ freeze: SharedValue<boolean>;
5
+ /** The distance between the bottom of the screen and the `ScrollView`. */
6
+ offset: number;
7
+ /** Keyboard-driven padding managed by `useChatKeyboard`. */
8
+ padding: SharedValue<number>;
9
+ };
10
+ /**
11
+ * Hook that reconciles keyboard padding after a frozen interval.
12
+ *
13
+ * `useChatKeyboard` handlers skip all writes while `freeze` is enabled, so if
14
+ * the keyboard opens or closes during the frozen interval `padding` keeps a
15
+ * stale value (e.g. the open-keyboard height after a frozen dismissal). This
16
+ * hook observes keyboard events independently of `freeze` and recomputes the
17
+ * padding from the latest observed keyboard height as soon as `freeze`
18
+ * transitions back to `false`.
19
+ *
20
+ * @param options - Keyboard padding shared values plus the scroll view `offset`.
21
+ * @param options.freeze - When `true`, keyboard-driven layout writes are skipped.
22
+ * @param options.offset - The distance between the bottom of the screen and the `ScrollView`.
23
+ * @param options.padding - Keyboard-driven padding managed by `useChatKeyboard`.
24
+ * @example
25
+ * ```ts
26
+ * useFrozenPadding({ freeze, offset, padding });
27
+ * ```
28
+ */
29
+ declare function useFrozenPadding({ freeze, offset, padding, }: UseFrozenPaddingOptions): void;
30
+ export { useFrozenPadding };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-keyboard-controller",
3
- "version": "1.21.13",
3
+ "version": "1.21.14",
4
4
  "description": "Keyboard manager which works in identical way on both iOS and Android",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -14,6 +14,7 @@ import ScrollViewWithBottomPadding from "../ScrollViewWithBottomPadding";
14
14
  import { useChatKeyboard } from "./useChatKeyboard";
15
15
  import { useEndVisible } from "./useEndVisible";
16
16
  import { useExtraContentPadding } from "./useExtraContentPadding";
17
+ import { useFrozenPadding } from "./useFrozenPadding";
17
18
 
18
19
  import type { KeyboardChatScrollViewProps } from "./types";
19
20
  import type { LayoutChangeEvent } from "react-native";
@@ -80,6 +81,12 @@ const KeyboardChatScrollView = forwardRef<
80
81
  freeze: freezeSV,
81
82
  });
82
83
 
84
+ useFrozenPadding({
85
+ freeze: freezeSV,
86
+ offset,
87
+ padding,
88
+ });
89
+
83
90
  useEndVisible({
84
91
  scroll,
85
92
  layout,
@@ -0,0 +1,83 @@
1
+ import { useAnimatedReaction, useSharedValue } from "react-native-reanimated";
2
+
3
+ import { useKeyboardHandler } from "../../../hooks";
4
+ import { getEffectiveHeight } from "../useChatKeyboard/helpers";
5
+
6
+ import type { SharedValue } from "react-native-reanimated";
7
+
8
+ type UseFrozenPaddingOptions = {
9
+ /** When `true`, keyboard-driven layout writes are skipped. */
10
+ freeze: SharedValue<boolean>;
11
+ /** The distance between the bottom of the screen and the `ScrollView`. */
12
+ offset: number;
13
+ /** Keyboard-driven padding managed by `useChatKeyboard`. */
14
+ padding: SharedValue<number>;
15
+ };
16
+
17
+ /**
18
+ * Hook that reconciles keyboard padding after a frozen interval.
19
+ *
20
+ * `useChatKeyboard` handlers skip all writes while `freeze` is enabled, so if
21
+ * the keyboard opens or closes during the frozen interval `padding` keeps a
22
+ * stale value (e.g. the open-keyboard height after a frozen dismissal). This
23
+ * hook observes keyboard events independently of `freeze` and recomputes the
24
+ * padding from the latest observed keyboard height as soon as `freeze`
25
+ * transitions back to `false`.
26
+ *
27
+ * @param options - Keyboard padding shared values plus the scroll view `offset`.
28
+ * @param options.freeze - When `true`, keyboard-driven layout writes are skipped.
29
+ * @param options.offset - The distance between the bottom of the screen and the `ScrollView`.
30
+ * @param options.padding - Keyboard-driven padding managed by `useChatKeyboard`.
31
+ * @example
32
+ * ```ts
33
+ * useFrozenPadding({ freeze, offset, padding });
34
+ * ```
35
+ */
36
+ function useFrozenPadding({
37
+ freeze,
38
+ offset,
39
+ padding,
40
+ }: UseFrozenPaddingOptions): void {
41
+ const lastHeight = useSharedValue(0);
42
+ const targetKeyboardHeight = useSharedValue(0);
43
+
44
+ useKeyboardHandler(
45
+ {
46
+ onStart: (e) => {
47
+ "worklet";
48
+
49
+ if (e.height > 0) {
50
+ // eslint-disable-next-line react-compiler/react-compiler
51
+ targetKeyboardHeight.value = e.height;
52
+ }
53
+ },
54
+ onMove: (e) => {
55
+ "worklet";
56
+
57
+ lastHeight.value = e.height;
58
+ },
59
+ onEnd: (e) => {
60
+ "worklet";
61
+
62
+ lastHeight.value = e.height;
63
+ },
64
+ },
65
+ [],
66
+ );
67
+
68
+ useAnimatedReaction(
69
+ () => freeze.value,
70
+ (isFrozen, wasFrozen) => {
71
+ if (!isFrozen && wasFrozen === true) {
72
+ padding.value = getEffectiveHeight(
73
+ lastHeight.value,
74
+ targetKeyboardHeight.value,
75
+ offset,
76
+ );
77
+ }
78
+ },
79
+ [offset],
80
+ );
81
+ }
82
+
83
+ export { useFrozenPadding };