react-native-keyboard-controller 1.21.0-beta.2 → 1.21.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/android/src/fabric/java/com/reactnativekeyboardcontroller/ClippingScrollViewDecoratorViewManager.kt +7 -0
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/views/ClippingScrollViewDecoratorView.kt +28 -1
  3. package/android/src/paper/java/com/reactnativekeyboardcontroller/ClippingScrollViewDecoratorViewManager.kt +8 -0
  4. package/ios/animations/KeyboardAnimation.swift +2 -2
  5. package/ios/animations/SpringAnimation.swift +1 -1
  6. package/ios/animations/TimingAnimation.swift +1 -3
  7. package/ios/delegates/KCTextInputCompositeDelegate.swift +2 -2
  8. package/ios/extensions/CGFloat.swift +1 -3
  9. package/ios/interactive/KeyboardAreaExtender.swift +2 -1
  10. package/ios/observers/FocusedInputObserver.swift +4 -2
  11. package/ios/observers/movement/KeyboardTrackingView.swift +4 -1
  12. package/ios/observers/movement/observer/KeyboardMovementObserver+Interactive.swift +2 -0
  13. package/ios/observers/movement/observer/KeyboardMovementObserver+Listeners.swift +30 -7
  14. package/ios/observers/movement/observer/KeyboardMovementObserver.swift +2 -48
  15. package/ios/protocols/TextInput.swift +1 -1
  16. package/ios/swizzling/UIResponderSwizzle.swift +2 -4
  17. package/ios/traversal/FocusedInputHolder.swift +3 -3
  18. package/ios/traversal/KeyboardView.swift +1 -1
  19. package/ios/traversal/ViewHierarchyNavigator.swift +2 -2
  20. package/ios/views/KeyboardControllerViewManager.swift +5 -5
  21. package/jest/index.js +1 -3
  22. package/lib/commonjs/components/KeyboardAwareScrollView/index.js +43 -11
  23. package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
  24. package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/hooks.js.map +1 -1
  25. package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/index.js +37 -12
  26. package/lib/commonjs/components/KeyboardChatScrollView/index.js.map +1 -0
  27. package/lib/commonjs/components/KeyboardChatScrollView/types.js.map +1 -0
  28. package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/useChatKeyboard/helpers.js +35 -1
  29. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/helpers.js.map +1 -0
  30. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +121 -0
  31. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -0
  32. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js +205 -0
  33. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -0
  34. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js +6 -0
  35. package/lib/commonjs/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -0
  36. package/lib/commonjs/components/KeyboardStickyView/index.js +3 -1
  37. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  38. package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js +18 -9
  39. package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js.map +1 -1
  40. package/lib/commonjs/components/hooks/useScrollState.js +20 -1
  41. package/lib/commonjs/components/hooks/useScrollState.js.map +1 -1
  42. package/lib/commonjs/components/index.js +7 -7
  43. package/lib/commonjs/components/index.js.map +1 -1
  44. package/lib/commonjs/index.js +7 -7
  45. package/lib/commonjs/index.js.map +1 -1
  46. package/lib/commonjs/specs/ClippingScrollViewDecoratorViewNativeComponent.js.map +1 -1
  47. package/lib/commonjs/types/views.js.map +1 -1
  48. package/lib/module/components/KeyboardAwareScrollView/index.js +43 -11
  49. package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
  50. package/lib/module/components/{ChatKit → KeyboardChatScrollView}/hooks.js.map +1 -1
  51. package/lib/module/components/KeyboardChatScrollView/index.js +73 -0
  52. package/lib/module/components/KeyboardChatScrollView/index.js.map +1 -0
  53. package/lib/module/components/KeyboardChatScrollView/types.js.map +1 -0
  54. package/lib/module/components/{ChatKit → KeyboardChatScrollView}/useChatKeyboard/helpers.js +34 -1
  55. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/helpers.js.map +1 -0
  56. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js +115 -0
  57. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.ios.js.map +1 -0
  58. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js +199 -0
  59. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/index.js.map +1 -0
  60. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js +2 -0
  61. package/lib/module/components/KeyboardChatScrollView/useChatKeyboard/types.js.map +1 -0
  62. package/lib/module/components/KeyboardStickyView/index.js +3 -1
  63. package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
  64. package/lib/module/components/ScrollViewWithBottomPadding/index.js +19 -10
  65. package/lib/module/components/ScrollViewWithBottomPadding/index.js.map +1 -1
  66. package/lib/module/components/hooks/useScrollState.js +21 -2
  67. package/lib/module/components/hooks/useScrollState.js.map +1 -1
  68. package/lib/module/components/index.js +1 -1
  69. package/lib/module/components/index.js.map +1 -1
  70. package/lib/module/index.js +1 -1
  71. package/lib/module/index.js.map +1 -1
  72. package/lib/module/specs/ClippingScrollViewDecoratorViewNativeComponent.js.map +1 -1
  73. package/lib/module/types/views.js.map +1 -1
  74. package/lib/typescript/components/KeyboardChatScrollView/hooks.d.ts +2 -0
  75. package/lib/typescript/components/KeyboardChatScrollView/index.d.ts +12 -0
  76. package/lib/typescript/components/{ChatKit → KeyboardChatScrollView}/types.d.ts +5 -6
  77. package/lib/typescript/components/{ChatKit → KeyboardChatScrollView}/useChatKeyboard/helpers.d.ts +23 -3
  78. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/index.d.ts +21 -0
  79. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/index.ios.d.ts +21 -0
  80. package/lib/typescript/components/KeyboardChatScrollView/useChatKeyboard/types.d.ts +22 -0
  81. package/lib/typescript/components/ScrollViewWithBottomPadding/index.d.ts +2 -4
  82. package/lib/typescript/components/hooks/useScrollState.d.ts +3 -0
  83. package/lib/typescript/components/index.d.ts +2 -2
  84. package/lib/typescript/index.d.ts +2 -2
  85. package/lib/typescript/specs/ClippingScrollViewDecoratorViewNativeComponent.d.ts +1 -0
  86. package/lib/typescript/types/views.d.ts +2 -0
  87. package/package.json +1 -1
  88. package/src/components/KeyboardAwareScrollView/index.tsx +53 -10
  89. package/src/components/KeyboardChatScrollView/hooks.ts +2 -0
  90. package/src/components/KeyboardChatScrollView/index.tsx +106 -0
  91. package/src/components/{ChatKit → KeyboardChatScrollView}/types.ts +5 -6
  92. package/src/components/{ChatKit → KeyboardChatScrollView}/useChatKeyboard/helpers.ts +46 -1
  93. package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ios.ts +180 -0
  94. package/src/components/KeyboardChatScrollView/useChatKeyboard/index.ts +300 -0
  95. package/src/components/KeyboardChatScrollView/useChatKeyboard/types.ts +30 -0
  96. package/src/components/KeyboardStickyView/index.tsx +4 -3
  97. package/src/components/ScrollViewWithBottomPadding/index.tsx +22 -25
  98. package/src/components/hooks/useScrollState.ts +24 -2
  99. package/src/components/index.ts +2 -2
  100. package/src/index.ts +2 -2
  101. package/src/specs/ClippingScrollViewDecoratorViewNativeComponent.ts +1 -0
  102. package/src/types/views.ts +2 -0
  103. package/lib/commonjs/components/ChatKit/TODO.md +0 -20
  104. package/lib/commonjs/components/ChatKit/index.js.map +0 -1
  105. package/lib/commonjs/components/ChatKit/types.js.map +0 -1
  106. package/lib/commonjs/components/ChatKit/useChatKeyboard/helpers.js.map +0 -1
  107. package/lib/commonjs/components/ChatKit/useChatKeyboard/index.js +0 -147
  108. package/lib/commonjs/components/ChatKit/useChatKeyboard/index.js.map +0 -1
  109. package/lib/module/components/ChatKit/TODO.md +0 -20
  110. package/lib/module/components/ChatKit/index.js +0 -48
  111. package/lib/module/components/ChatKit/index.js.map +0 -1
  112. package/lib/module/components/ChatKit/types.js.map +0 -1
  113. package/lib/module/components/ChatKit/useChatKeyboard/helpers.js.map +0 -1
  114. package/lib/module/components/ChatKit/useChatKeyboard/index.js +0 -141
  115. package/lib/module/components/ChatKit/useChatKeyboard/index.js.map +0 -1
  116. package/lib/typescript/components/ChatKit/hooks.d.ts +0 -2
  117. package/lib/typescript/components/ChatKit/index.d.ts +0 -14
  118. package/lib/typescript/components/ChatKit/useChatKeyboard/index.d.ts +0 -36
  119. package/src/components/ChatKit/TODO.md +0 -20
  120. package/src/components/ChatKit/hooks.ts +0 -2
  121. package/src/components/ChatKit/index.tsx +0 -63
  122. package/src/components/ChatKit/useChatKeyboard/index.ts +0 -228
  123. /package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/hooks.js +0 -0
  124. /package/lib/commonjs/components/{ChatKit → KeyboardChatScrollView}/types.js +0 -0
  125. /package/lib/module/components/{ChatKit → KeyboardChatScrollView}/hooks.js +0 -0
  126. /package/lib/module/components/{ChatKit → KeyboardChatScrollView}/types.js +0 -0
@@ -0,0 +1,199 @@
1
+ import { scrollTo, useSharedValue } from "react-native-reanimated";
2
+ import { useKeyboardHandler } from "../../../hooks";
3
+ import useScrollState from "../../hooks/useScrollState";
4
+ import { clampedScrollTarget, getEffectiveHeight, isScrollAtEnd, shouldShiftContent } from "./helpers";
5
+ /**
6
+ * Hook that manages keyboard-driven scrolling for chat-style scroll views.
7
+ * Calculates padding (extra scrollable space) and content shift values,
8
+ * using per-frame scrollTo updates (Android and other platforms).
9
+ *
10
+ * @param scrollViewRef - Animated ref to the scroll view.
11
+ * @param options - Configuration for inverted and keyboardLiftBehavior.
12
+ * @returns Shared values for padding and contentOffsetY (always `undefined`).
13
+ * @example
14
+ * ```tsx
15
+ * const { padding, contentOffsetY } = useChatKeyboard(ref, {
16
+ * inverted: false,
17
+ * keyboardLiftBehavior: "always",
18
+ * });
19
+ * ```
20
+ */
21
+ function useChatKeyboard(scrollViewRef, options) {
22
+ const {
23
+ inverted,
24
+ keyboardLiftBehavior,
25
+ freeze,
26
+ offset
27
+ } = options;
28
+ const padding = useSharedValue(0);
29
+ const currentHeight = useSharedValue(0);
30
+ const offsetBeforeScroll = useSharedValue(0);
31
+ const targetKeyboardHeight = useSharedValue(0);
32
+ const closing = useSharedValue(false);
33
+ const {
34
+ layout,
35
+ size,
36
+ offset: scroll,
37
+ onLayout,
38
+ onContentSizeChange
39
+ } = useScrollState(scrollViewRef);
40
+ const clampScrollIfNeeded = effective => {
41
+ "worklet";
42
+
43
+ const maxScroll = Math.max(size.value.height - layout.value.height + effective, 0);
44
+ if (scroll.value > maxScroll) {
45
+ scrollTo(scrollViewRef, 0, maxScroll, false);
46
+ }
47
+ };
48
+ useKeyboardHandler({
49
+ onStart: e => {
50
+ "worklet";
51
+
52
+ if (freeze) {
53
+ return;
54
+ }
55
+ if (e.height > 0) {
56
+ // eslint-disable-next-line react-compiler/react-compiler
57
+ targetKeyboardHeight.value = e.height;
58
+ closing.value = false;
59
+ } else {
60
+ closing.value = true;
61
+ }
62
+ const effective = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
63
+ const atEnd = isScrollAtEnd(scroll.value, layout.value.height, size.value.height, inverted);
64
+ if (inverted && e.duration === -1) {
65
+ // Android inverted: skip post-interactive snap-back events
66
+ // (duration === -1 means the keyboard is re-establishing its
67
+ // position after an interactive gesture, not a real animation)
68
+ return;
69
+ } else if (e.height > 0) {
70
+ // Android: keyboard opening — set padding + capture scroll position
71
+ padding.value = effective;
72
+ offsetBeforeScroll.value = scroll.value;
73
+ if (!inverted && keyboardLiftBehavior === "whenAtEnd" && !atEnd) {
74
+ // Sentinel: don't scroll in onMove (non-inverted only)
75
+ offsetBeforeScroll.value = -1;
76
+ }
77
+ } else {
78
+ // Android: keyboard closing — re-capture scroll position
79
+ if (inverted) {
80
+ offsetBeforeScroll.value = scroll.value;
81
+ } else {
82
+ // Preserve "whenAtEnd" sentinel: if open didn't shift, close shouldn't either
83
+ if (offsetBeforeScroll.value !== -1) {
84
+ // Non-inverted: subtract padding to get the "natural" position
85
+ // so onMove smoothly scrolls back from where the user is now
86
+ offsetBeforeScroll.value = scroll.value - padding.value;
87
+ }
88
+ }
89
+ }
90
+ },
91
+ onMove: e => {
92
+ "worklet";
93
+
94
+ if (freeze) {
95
+ return;
96
+ }
97
+ currentHeight.value = e.height;
98
+ if (inverted) {
99
+ // Skip post-interactive snap-back (duration === -1)
100
+ if (e.duration === -1) {
101
+ return;
102
+ }
103
+ const effective = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
104
+
105
+ // Check if we should shift content based on position when keyboard started
106
+ const wasAtEnd = isScrollAtEnd(offsetBeforeScroll.value, layout.value.height, size.value.height, inverted);
107
+
108
+ // "never" at end: scroll along when keyboard closes to avoid jump
109
+ if (keyboardLiftBehavior === "never" && wasAtEnd && effective < padding.value) {
110
+ padding.value = effective;
111
+ scrollTo(scrollViewRef, 0, 0, false);
112
+ return;
113
+ }
114
+ if (!shouldShiftContent(keyboardLiftBehavior, wasAtEnd)) {
115
+ // Closing, not shifting: reduce padding to avoid gap
116
+ if (closing.value && effective < padding.value) {
117
+ padding.value = effective;
118
+ clampScrollIfNeeded(effective);
119
+ }
120
+ return;
121
+ }
122
+
123
+ // Persistent: don't let shift decrease
124
+ if (keyboardLiftBehavior === "persistent") {
125
+ const currentShift = offsetBeforeScroll.value + padding.value - scroll.value;
126
+ if (effective < currentShift) {
127
+ // When at end, allow scrolling back (snap to end + reduce padding)
128
+ if (wasAtEnd) {
129
+ padding.value = effective;
130
+ scrollTo(scrollViewRef, 0, 0, false);
131
+ } else if (closing.value) {
132
+ // Not at end: reduce padding to avoid gap
133
+ padding.value = effective;
134
+ clampScrollIfNeeded(effective);
135
+ }
136
+ return;
137
+ }
138
+ }
139
+ const target = offsetBeforeScroll.value + padding.value - effective;
140
+ scrollTo(scrollViewRef, 0, target, false);
141
+ } else {
142
+ const effective = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
143
+
144
+ // "never" closing: scroll along when at end to avoid jump
145
+ if (keyboardLiftBehavior === "never" && closing.value && effective < padding.value) {
146
+ const wasAtEnd = isScrollAtEnd(offsetBeforeScroll.value + padding.value, layout.value.height, size.value.height, false);
147
+ if (wasAtEnd) {
148
+ const target = clampedScrollTarget(offsetBeforeScroll.value, effective, size.value.height, layout.value.height);
149
+ scrollTo(scrollViewRef, 0, target, false);
150
+ } else {
151
+ // Clamp to valid range as padding shrinks
152
+ clampScrollIfNeeded(effective);
153
+ }
154
+ return;
155
+ }
156
+ if (!shouldShiftContent(keyboardLiftBehavior, true)) {
157
+ return;
158
+ }
159
+
160
+ // "whenAtEnd" sentinel check
161
+ if (offsetBeforeScroll.value === -1) {
162
+ if (closing.value) {
163
+ // Keyboard didn't shift on open; ensure valid position on close
164
+ clampScrollIfNeeded(effective);
165
+ }
166
+ return;
167
+ }
168
+
169
+ // "persistent" closing: maintain position, clamped to valid range
170
+ if (keyboardLiftBehavior === "persistent" && closing.value) {
171
+ const keepAt = offsetBeforeScroll.value + padding.value;
172
+ const maxScroll = Math.max(size.value.height - layout.value.height + effective, 0);
173
+ scrollTo(scrollViewRef, 0, Math.min(keepAt, maxScroll), false);
174
+ return;
175
+ }
176
+ const target = clampedScrollTarget(offsetBeforeScroll.value, effective, size.value.height, layout.value.height);
177
+ scrollTo(scrollViewRef, 0, target, false);
178
+ }
179
+ },
180
+ onEnd: e => {
181
+ "worklet";
182
+
183
+ if (freeze) {
184
+ return;
185
+ }
186
+ const effective = getEffectiveHeight(e.height, targetKeyboardHeight.value, offset);
187
+ padding.value = effective;
188
+ }
189
+ }, [inverted, keyboardLiftBehavior, freeze, offset]);
190
+ return {
191
+ padding,
192
+ currentHeight,
193
+ contentOffsetY: undefined,
194
+ onLayout,
195
+ onContentSizeChange
196
+ };
197
+ }
198
+ export { useChatKeyboard };
199
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["scrollTo","useSharedValue","useKeyboardHandler","useScrollState","clampedScrollTarget","getEffectiveHeight","isScrollAtEnd","shouldShiftContent","useChatKeyboard","scrollViewRef","options","inverted","keyboardLiftBehavior","freeze","offset","padding","currentHeight","offsetBeforeScroll","targetKeyboardHeight","closing","layout","size","scroll","onLayout","onContentSizeChange","clampScrollIfNeeded","effective","maxScroll","Math","max","value","height","onStart","e","atEnd","duration","onMove","wasAtEnd","currentShift","target","keepAt","min","onEnd","contentOffsetY","undefined"],"sources":["index.ts"],"sourcesContent":["import { scrollTo, useSharedValue } from \"react-native-reanimated\";\n\nimport { useKeyboardHandler } from \"../../../hooks\";\nimport useScrollState from \"../../hooks/useScrollState\";\n\nimport {\n clampedScrollTarget,\n getEffectiveHeight,\n isScrollAtEnd,\n shouldShiftContent,\n} from \"./helpers\";\n\nimport type { UseChatKeyboardOptions, UseChatKeyboardReturn } from \"./types\";\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\n/**\n * Hook that manages keyboard-driven scrolling for chat-style scroll views.\n * Calculates padding (extra scrollable space) and content shift values,\n * using per-frame scrollTo updates (Android and other platforms).\n *\n * @param scrollViewRef - Animated ref to the scroll view.\n * @param options - Configuration for inverted and keyboardLiftBehavior.\n * @returns Shared values for padding and contentOffsetY (always `undefined`).\n * @example\n * ```tsx\n * const { padding, contentOffsetY } = useChatKeyboard(ref, {\n * inverted: false,\n * keyboardLiftBehavior: \"always\",\n * });\n * ```\n */\nfunction useChatKeyboard(\n scrollViewRef: AnimatedRef<Reanimated.ScrollView>,\n options: UseChatKeyboardOptions,\n): UseChatKeyboardReturn {\n const { inverted, keyboardLiftBehavior, freeze, offset } = options;\n\n const padding = useSharedValue(0);\n const currentHeight = useSharedValue(0);\n const offsetBeforeScroll = useSharedValue(0);\n const targetKeyboardHeight = useSharedValue(0);\n const closing = useSharedValue(false);\n\n const {\n layout,\n size,\n offset: scroll,\n onLayout,\n onContentSizeChange,\n } = useScrollState(scrollViewRef);\n\n const clampScrollIfNeeded = (effective: number) => {\n \"worklet\";\n\n const maxScroll = Math.max(\n size.value.height - layout.value.height + effective,\n 0,\n );\n\n if (scroll.value > maxScroll) {\n scrollTo(scrollViewRef, 0, maxScroll, false);\n }\n };\n\n useKeyboardHandler(\n {\n onStart: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n if (e.height > 0) {\n // eslint-disable-next-line react-compiler/react-compiler\n targetKeyboardHeight.value = e.height;\n closing.value = false;\n } else {\n closing.value = true;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n const atEnd = isScrollAtEnd(\n scroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n if (inverted && e.duration === -1) {\n // Android inverted: skip post-interactive snap-back events\n // (duration === -1 means the keyboard is re-establishing its\n // position after an interactive gesture, not a real animation)\n return;\n } else if (e.height > 0) {\n // Android: keyboard opening — set padding + capture scroll position\n padding.value = effective;\n offsetBeforeScroll.value = scroll.value;\n\n if (!inverted && keyboardLiftBehavior === \"whenAtEnd\" && !atEnd) {\n // Sentinel: don't scroll in onMove (non-inverted only)\n offsetBeforeScroll.value = -1;\n }\n } else {\n // Android: keyboard closing — re-capture scroll position\n if (inverted) {\n offsetBeforeScroll.value = scroll.value;\n } else {\n // Preserve \"whenAtEnd\" sentinel: if open didn't shift, close shouldn't either\n if (offsetBeforeScroll.value !== -1) {\n // Non-inverted: subtract padding to get the \"natural\" position\n // so onMove smoothly scrolls back from where the user is now\n offsetBeforeScroll.value = scroll.value - padding.value;\n }\n }\n }\n },\n onMove: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n currentHeight.value = e.height;\n\n if (inverted) {\n // Skip post-interactive snap-back (duration === -1)\n if (e.duration === -1) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n // Check if we should shift content based on position when keyboard started\n const wasAtEnd = isScrollAtEnd(\n offsetBeforeScroll.value,\n layout.value.height,\n size.value.height,\n inverted,\n );\n\n // \"never\" at end: scroll along when keyboard closes to avoid jump\n if (\n keyboardLiftBehavior === \"never\" &&\n wasAtEnd &&\n effective < padding.value\n ) {\n padding.value = effective;\n scrollTo(scrollViewRef, 0, 0, false);\n\n return;\n }\n\n if (!shouldShiftContent(keyboardLiftBehavior, wasAtEnd)) {\n // Closing, not shifting: reduce padding to avoid gap\n if (closing.value && effective < padding.value) {\n padding.value = effective;\n clampScrollIfNeeded(effective);\n }\n\n return;\n }\n\n // Persistent: don't let shift decrease\n if (keyboardLiftBehavior === \"persistent\") {\n const currentShift =\n offsetBeforeScroll.value + padding.value - scroll.value;\n\n if (effective < currentShift) {\n // When at end, allow scrolling back (snap to end + reduce padding)\n if (wasAtEnd) {\n padding.value = effective;\n scrollTo(scrollViewRef, 0, 0, false);\n } else if (closing.value) {\n // Not at end: reduce padding to avoid gap\n padding.value = effective;\n clampScrollIfNeeded(effective);\n }\n\n return;\n }\n }\n\n const target = offsetBeforeScroll.value + padding.value - effective;\n\n scrollTo(scrollViewRef, 0, target, false);\n } else {\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n // \"never\" closing: scroll along when at end to avoid jump\n if (\n keyboardLiftBehavior === \"never\" &&\n closing.value &&\n effective < padding.value\n ) {\n const wasAtEnd = isScrollAtEnd(\n offsetBeforeScroll.value + padding.value,\n layout.value.height,\n size.value.height,\n false,\n );\n\n if (wasAtEnd) {\n const target = clampedScrollTarget(\n offsetBeforeScroll.value,\n effective,\n size.value.height,\n layout.value.height,\n );\n\n scrollTo(scrollViewRef, 0, target, false);\n } else {\n // Clamp to valid range as padding shrinks\n clampScrollIfNeeded(effective);\n }\n\n return;\n }\n\n if (!shouldShiftContent(keyboardLiftBehavior, true)) {\n return;\n }\n\n // \"whenAtEnd\" sentinel check\n if (offsetBeforeScroll.value === -1) {\n if (closing.value) {\n // Keyboard didn't shift on open; ensure valid position on close\n clampScrollIfNeeded(effective);\n }\n\n return;\n }\n\n // \"persistent\" closing: maintain position, clamped to valid range\n if (keyboardLiftBehavior === \"persistent\" && closing.value) {\n const keepAt = offsetBeforeScroll.value + padding.value;\n const maxScroll = Math.max(\n size.value.height - layout.value.height + effective,\n 0,\n );\n\n scrollTo(scrollViewRef, 0, Math.min(keepAt, maxScroll), false);\n\n return;\n }\n\n const target = clampedScrollTarget(\n offsetBeforeScroll.value,\n effective,\n size.value.height,\n layout.value.height,\n );\n\n scrollTo(scrollViewRef, 0, target, false);\n }\n },\n onEnd: (e) => {\n \"worklet\";\n\n if (freeze) {\n return;\n }\n\n const effective = getEffectiveHeight(\n e.height,\n targetKeyboardHeight.value,\n offset,\n );\n\n padding.value = effective;\n },\n },\n [inverted, keyboardLiftBehavior, freeze, offset],\n );\n\n return {\n padding,\n currentHeight,\n contentOffsetY: undefined,\n onLayout,\n onContentSizeChange,\n };\n}\n\nexport { useChatKeyboard };\n"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,cAAc,QAAQ,yBAAyB;AAElE,SAASC,kBAAkB,QAAQ,gBAAgB;AACnD,OAAOC,cAAc,MAAM,4BAA4B;AAEvD,SACEC,mBAAmB,EACnBC,kBAAkB,EAClBC,aAAa,EACbC,kBAAkB,QACb,WAAW;AAMlB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,eAAeA,CACtBC,aAAiD,EACjDC,OAA+B,EACR;EACvB,MAAM;IAAEC,QAAQ;IAAEC,oBAAoB;IAAEC,MAAM;IAAEC;EAAO,CAAC,GAAGJ,OAAO;EAElE,MAAMK,OAAO,GAAGd,cAAc,CAAC,CAAC,CAAC;EACjC,MAAMe,aAAa,GAAGf,cAAc,CAAC,CAAC,CAAC;EACvC,MAAMgB,kBAAkB,GAAGhB,cAAc,CAAC,CAAC,CAAC;EAC5C,MAAMiB,oBAAoB,GAAGjB,cAAc,CAAC,CAAC,CAAC;EAC9C,MAAMkB,OAAO,GAAGlB,cAAc,CAAC,KAAK,CAAC;EAErC,MAAM;IACJmB,MAAM;IACNC,IAAI;IACJP,MAAM,EAAEQ,MAAM;IACdC,QAAQ;IACRC;EACF,CAAC,GAAGrB,cAAc,CAACM,aAAa,CAAC;EAEjC,MAAMgB,mBAAmB,GAAIC,SAAiB,IAAK;IACjD,SAAS;;IAET,MAAMC,SAAS,GAAGC,IAAI,CAACC,GAAG,CACxBR,IAAI,CAACS,KAAK,CAACC,MAAM,GAAGX,MAAM,CAACU,KAAK,CAACC,MAAM,GAAGL,SAAS,EACnD,CACF,CAAC;IAED,IAAIJ,MAAM,CAACQ,KAAK,GAAGH,SAAS,EAAE;MAC5B3B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAEkB,SAAS,EAAE,KAAK,CAAC;IAC9C;EACF,CAAC;EAEDzB,kBAAkB,CAChB;IACE8B,OAAO,EAAGC,CAAC,IAAK;MACd,SAAS;;MAET,IAAIpB,MAAM,EAAE;QACV;MACF;MAEA,IAAIoB,CAAC,CAACF,MAAM,GAAG,CAAC,EAAE;QAChB;QACAb,oBAAoB,CAACY,KAAK,GAAGG,CAAC,CAACF,MAAM;QACrCZ,OAAO,CAACW,KAAK,GAAG,KAAK;MACvB,CAAC,MAAM;QACLX,OAAO,CAACW,KAAK,GAAG,IAAI;MACtB;MAEA,MAAMJ,SAAS,GAAGrB,kBAAkB,CAClC4B,CAAC,CAACF,MAAM,EACRb,oBAAoB,CAACY,KAAK,EAC1BhB,MACF,CAAC;MAED,MAAMoB,KAAK,GAAG5B,aAAa,CACzBgB,MAAM,CAACQ,KAAK,EACZV,MAAM,CAACU,KAAK,CAACC,MAAM,EACnBV,IAAI,CAACS,KAAK,CAACC,MAAM,EACjBpB,QACF,CAAC;MAED,IAAIA,QAAQ,IAAIsB,CAAC,CAACE,QAAQ,KAAK,CAAC,CAAC,EAAE;QACjC;QACA;QACA;QACA;MACF,CAAC,MAAM,IAAIF,CAAC,CAACF,MAAM,GAAG,CAAC,EAAE;QACvB;QACAhB,OAAO,CAACe,KAAK,GAAGJ,SAAS;QACzBT,kBAAkB,CAACa,KAAK,GAAGR,MAAM,CAACQ,KAAK;QAEvC,IAAI,CAACnB,QAAQ,IAAIC,oBAAoB,KAAK,WAAW,IAAI,CAACsB,KAAK,EAAE;UAC/D;UACAjB,kBAAkB,CAACa,KAAK,GAAG,CAAC,CAAC;QAC/B;MACF,CAAC,MAAM;QACL;QACA,IAAInB,QAAQ,EAAE;UACZM,kBAAkB,CAACa,KAAK,GAAGR,MAAM,CAACQ,KAAK;QACzC,CAAC,MAAM;UACL;UACA,IAAIb,kBAAkB,CAACa,KAAK,KAAK,CAAC,CAAC,EAAE;YACnC;YACA;YACAb,kBAAkB,CAACa,KAAK,GAAGR,MAAM,CAACQ,KAAK,GAAGf,OAAO,CAACe,KAAK;UACzD;QACF;MACF;IACF,CAAC;IACDM,MAAM,EAAGH,CAAC,IAAK;MACb,SAAS;;MAET,IAAIpB,MAAM,EAAE;QACV;MACF;MAEAG,aAAa,CAACc,KAAK,GAAGG,CAAC,CAACF,MAAM;MAE9B,IAAIpB,QAAQ,EAAE;QACZ;QACA,IAAIsB,CAAC,CAACE,QAAQ,KAAK,CAAC,CAAC,EAAE;UACrB;QACF;QAEA,MAAMT,SAAS,GAAGrB,kBAAkB,CAClC4B,CAAC,CAACF,MAAM,EACRb,oBAAoB,CAACY,KAAK,EAC1BhB,MACF,CAAC;;QAED;QACA,MAAMuB,QAAQ,GAAG/B,aAAa,CAC5BW,kBAAkB,CAACa,KAAK,EACxBV,MAAM,CAACU,KAAK,CAACC,MAAM,EACnBV,IAAI,CAACS,KAAK,CAACC,MAAM,EACjBpB,QACF,CAAC;;QAED;QACA,IACEC,oBAAoB,KAAK,OAAO,IAChCyB,QAAQ,IACRX,SAAS,GAAGX,OAAO,CAACe,KAAK,EACzB;UACAf,OAAO,CAACe,KAAK,GAAGJ,SAAS;UACzB1B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;UAEpC;QACF;QAEA,IAAI,CAACF,kBAAkB,CAACK,oBAAoB,EAAEyB,QAAQ,CAAC,EAAE;UACvD;UACA,IAAIlB,OAAO,CAACW,KAAK,IAAIJ,SAAS,GAAGX,OAAO,CAACe,KAAK,EAAE;YAC9Cf,OAAO,CAACe,KAAK,GAAGJ,SAAS;YACzBD,mBAAmB,CAACC,SAAS,CAAC;UAChC;UAEA;QACF;;QAEA;QACA,IAAId,oBAAoB,KAAK,YAAY,EAAE;UACzC,MAAM0B,YAAY,GAChBrB,kBAAkB,CAACa,KAAK,GAAGf,OAAO,CAACe,KAAK,GAAGR,MAAM,CAACQ,KAAK;UAEzD,IAAIJ,SAAS,GAAGY,YAAY,EAAE;YAC5B;YACA,IAAID,QAAQ,EAAE;cACZtB,OAAO,CAACe,KAAK,GAAGJ,SAAS;cACzB1B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;YACtC,CAAC,MAAM,IAAIU,OAAO,CAACW,KAAK,EAAE;cACxB;cACAf,OAAO,CAACe,KAAK,GAAGJ,SAAS;cACzBD,mBAAmB,CAACC,SAAS,CAAC;YAChC;YAEA;UACF;QACF;QAEA,MAAMa,MAAM,GAAGtB,kBAAkB,CAACa,KAAK,GAAGf,OAAO,CAACe,KAAK,GAAGJ,SAAS;QAEnE1B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAE8B,MAAM,EAAE,KAAK,CAAC;MAC3C,CAAC,MAAM;QACL,MAAMb,SAAS,GAAGrB,kBAAkB,CAClC4B,CAAC,CAACF,MAAM,EACRb,oBAAoB,CAACY,KAAK,EAC1BhB,MACF,CAAC;;QAED;QACA,IACEF,oBAAoB,KAAK,OAAO,IAChCO,OAAO,CAACW,KAAK,IACbJ,SAAS,GAAGX,OAAO,CAACe,KAAK,EACzB;UACA,MAAMO,QAAQ,GAAG/B,aAAa,CAC5BW,kBAAkB,CAACa,KAAK,GAAGf,OAAO,CAACe,KAAK,EACxCV,MAAM,CAACU,KAAK,CAACC,MAAM,EACnBV,IAAI,CAACS,KAAK,CAACC,MAAM,EACjB,KACF,CAAC;UAED,IAAIM,QAAQ,EAAE;YACZ,MAAME,MAAM,GAAGnC,mBAAmB,CAChCa,kBAAkB,CAACa,KAAK,EACxBJ,SAAS,EACTL,IAAI,CAACS,KAAK,CAACC,MAAM,EACjBX,MAAM,CAACU,KAAK,CAACC,MACf,CAAC;YAED/B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAE8B,MAAM,EAAE,KAAK,CAAC;UAC3C,CAAC,MAAM;YACL;YACAd,mBAAmB,CAACC,SAAS,CAAC;UAChC;UAEA;QACF;QAEA,IAAI,CAACnB,kBAAkB,CAACK,oBAAoB,EAAE,IAAI,CAAC,EAAE;UACnD;QACF;;QAEA;QACA,IAAIK,kBAAkB,CAACa,KAAK,KAAK,CAAC,CAAC,EAAE;UACnC,IAAIX,OAAO,CAACW,KAAK,EAAE;YACjB;YACAL,mBAAmB,CAACC,SAAS,CAAC;UAChC;UAEA;QACF;;QAEA;QACA,IAAId,oBAAoB,KAAK,YAAY,IAAIO,OAAO,CAACW,KAAK,EAAE;UAC1D,MAAMU,MAAM,GAAGvB,kBAAkB,CAACa,KAAK,GAAGf,OAAO,CAACe,KAAK;UACvD,MAAMH,SAAS,GAAGC,IAAI,CAACC,GAAG,CACxBR,IAAI,CAACS,KAAK,CAACC,MAAM,GAAGX,MAAM,CAACU,KAAK,CAACC,MAAM,GAAGL,SAAS,EACnD,CACF,CAAC;UAED1B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAEmB,IAAI,CAACa,GAAG,CAACD,MAAM,EAAEb,SAAS,CAAC,EAAE,KAAK,CAAC;UAE9D;QACF;QAEA,MAAMY,MAAM,GAAGnC,mBAAmB,CAChCa,kBAAkB,CAACa,KAAK,EACxBJ,SAAS,EACTL,IAAI,CAACS,KAAK,CAACC,MAAM,EACjBX,MAAM,CAACU,KAAK,CAACC,MACf,CAAC;QAED/B,QAAQ,CAACS,aAAa,EAAE,CAAC,EAAE8B,MAAM,EAAE,KAAK,CAAC;MAC3C;IACF,CAAC;IACDG,KAAK,EAAGT,CAAC,IAAK;MACZ,SAAS;;MAET,IAAIpB,MAAM,EAAE;QACV;MACF;MAEA,MAAMa,SAAS,GAAGrB,kBAAkB,CAClC4B,CAAC,CAACF,MAAM,EACRb,oBAAoB,CAACY,KAAK,EAC1BhB,MACF,CAAC;MAEDC,OAAO,CAACe,KAAK,GAAGJ,SAAS;IAC3B;EACF,CAAC,EACD,CAACf,QAAQ,EAAEC,oBAAoB,EAAEC,MAAM,EAAEC,MAAM,CACjD,CAAC;EAED,OAAO;IACLC,OAAO;IACPC,aAAa;IACb2B,cAAc,EAAEC,SAAS;IACzBrB,QAAQ;IACRC;EACF,CAAC;AACH;AAEA,SAAShB,eAAe","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { LayoutChangeEvent } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\ntype KeyboardLiftBehavior = \"always\" | \"whenAtEnd\" | \"persistent\" | \"never\";\n\ntype UseChatKeyboardOptions = {\n inverted: boolean;\n keyboardLiftBehavior: KeyboardLiftBehavior;\n freeze: boolean;\n offset: number;\n};\n\ntype UseChatKeyboardReturn = {\n /** Extra scrollable space (= keyboard height). Used as contentInset on iOS, contentInsetBottom/contentInsetTop on Android. */\n padding: SharedValue<number>;\n /** Raw keyboard height updated every frame in onMove. Used to force Reanimated commits on Fabric. */\n currentHeight: SharedValue<number>;\n /** Absolute Y content offset for iOS (set once in onStart). `undefined` on Android. */\n contentOffsetY: SharedValue<number> | undefined;\n /** Callback to attach to ScrollView's onLayout prop to capture initial viewport dimensions. */\n onLayout: (e: LayoutChangeEvent) => void;\n /** Callback to attach to ScrollView's onContentSizeChange prop to capture initial content dimensions. */\n onContentSizeChange: (w: number, h: number) => void;\n};\n\nexport type {\n KeyboardLiftBehavior,\n UseChatKeyboardOptions,\n UseChatKeyboardReturn,\n};\n"],"mappings":"","ignoreList":[]}
@@ -34,9 +34,11 @@ const KeyboardStickyView = /*#__PURE__*/forwardRef(({
34
34
  outputRange: [closed, opened]
35
35
  });
36
36
  const styles = useMemo(() => {
37
+ const disabled = Animated.add(Animated.multiply(height, 0), closed);
38
+ const active = Animated.add(height, offset);
37
39
  return [{
38
40
  transform: [{
39
- translateY: enabled ? Animated.add(height, offset) : closed
41
+ translateY: enabled ? active : disabled
40
42
  }]
41
43
  }, style];
42
44
  }, [closed, enabled, height, offset, style]);
@@ -1 +1 @@
1
- {"version":3,"names":["React","forwardRef","useMemo","Animated","useKeyboardAnimation","KeyboardStickyView","children","offset","closed","opened","style","enabled","props","ref","height","progress","interpolate","inputRange","outputRange","styles","transform","translateY","add","createElement","View","_extends"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useMemo } from \"react\";\nimport { Animated } from \"react-native\";\n\nimport { useKeyboardAnimation } from \"../../hooks\";\n\nimport type { View, ViewProps } from \"react-native\";\n\nexport type KeyboardStickyViewProps = {\n /**\n * Specify additional offset to the view for given keyboard state.\n */\n offset?: {\n /**\n * Adds additional `translateY` when keyboard is close. By default `0`.\n */\n closed?: number;\n /**\n * Adds additional `translateY` when keyboard is open. By default `0`.\n */\n opened?: number;\n };\n\n /** Controls whether this `KeyboardStickyView` instance should take effect. Default is `true`. */\n enabled?: boolean;\n} & ViewProps;\n\n/**\n * A View component that sticks to the keyboard and moves with it when it appears or disappears.\n * The view can be configured with custom offsets for both closed and open keyboard states.\n *\n * @returns An animated View component that sticks to the keyboard.\n * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-sticky-view|Documentation} page for more details.\n * @example\n * ```tsx\n * <KeyboardStickyView offset={{ closed: 0, opened: 20 }}>\n * <Button title=\"Submit\" />\n * </KeyboardStickyView>\n * ```\n */\nconst KeyboardStickyView = forwardRef<\n View,\n React.PropsWithChildren<KeyboardStickyViewProps>\n>(\n (\n {\n children,\n offset: { closed = 0, opened = 0 } = {},\n style,\n enabled = true,\n ...props\n },\n ref,\n ) => {\n const { height, progress } = useKeyboardAnimation();\n\n const offset = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [closed, opened],\n });\n\n const styles = useMemo(() => {\n return [\n {\n transform: [\n { translateY: enabled ? Animated.add(height, offset) : closed },\n ],\n },\n style,\n ];\n }, [closed, enabled, height, offset, style]);\n\n return (\n <Animated.View ref={ref} style={styles} {...props}>\n {children}\n </Animated.View>\n );\n },\n);\n\nexport default KeyboardStickyView;\n"],"mappings":";AAAA,OAAOA,KAAK,IAAIC,UAAU,EAAEC,OAAO,QAAQ,OAAO;AAClD,SAASC,QAAQ,QAAQ,cAAc;AAEvC,SAASC,oBAAoB,QAAQ,aAAa;AAuBlD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,gBAAGJ,UAAU,CAInC,CACE;EACEK,QAAQ;EACRC,MAAM,EAAE;IAAEC,MAAM,GAAG,CAAC;IAAEC,MAAM,GAAG;EAAE,CAAC,GAAG,CAAC,CAAC;EACvCC,KAAK;EACLC,OAAO,GAAG,IAAI;EACd,GAAGC;AACL,CAAC,EACDC,GAAG,KACA;EACH,MAAM;IAAEC,MAAM;IAAEC;EAAS,CAAC,GAAGX,oBAAoB,CAAC,CAAC;EAEnD,MAAMG,MAAM,GAAGQ,QAAQ,CAACC,WAAW,CAAC;IAClCC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAClBC,WAAW,EAAE,CAACV,MAAM,EAAEC,MAAM;EAC9B,CAAC,CAAC;EAEF,MAAMU,MAAM,GAAGjB,OAAO,CAAC,MAAM;IAC3B,OAAO,CACL;MACEkB,SAAS,EAAE,CACT;QAAEC,UAAU,EAAEV,OAAO,GAAGR,QAAQ,CAACmB,GAAG,CAACR,MAAM,EAAEP,MAAM,CAAC,GAAGC;MAAO,CAAC;IAEnE,CAAC,EACDE,KAAK,CACN;EACH,CAAC,EAAE,CAACF,MAAM,EAAEG,OAAO,EAAEG,MAAM,EAAEP,MAAM,EAAEG,KAAK,CAAC,CAAC;EAE5C,oBACEV,KAAA,CAAAuB,aAAA,CAACpB,QAAQ,CAACqB,IAAI,EAAAC,QAAA;IAACZ,GAAG,EAAEA,GAAI;IAACH,KAAK,EAAES;EAAO,GAAKP,KAAK,GAC9CN,QACY,CAAC;AAEpB,CACF,CAAC;AAED,eAAeD,kBAAkB","ignoreList":[]}
1
+ {"version":3,"names":["React","forwardRef","useMemo","Animated","useKeyboardAnimation","KeyboardStickyView","children","offset","closed","opened","style","enabled","props","ref","height","progress","interpolate","inputRange","outputRange","styles","disabled","add","multiply","active","transform","translateY","createElement","View","_extends"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useMemo } from \"react\";\nimport { Animated } from \"react-native\";\n\nimport { useKeyboardAnimation } from \"../../hooks\";\n\nimport type { View, ViewProps } from \"react-native\";\n\nexport type KeyboardStickyViewProps = {\n /**\n * Specify additional offset to the view for given keyboard state.\n */\n offset?: {\n /**\n * Adds additional `translateY` when keyboard is close. By default `0`.\n */\n closed?: number;\n /**\n * Adds additional `translateY` when keyboard is open. By default `0`.\n */\n opened?: number;\n };\n\n /** Controls whether this `KeyboardStickyView` instance should take effect. Default is `true`. */\n enabled?: boolean;\n} & ViewProps;\n\n/**\n * A View component that sticks to the keyboard and moves with it when it appears or disappears.\n * The view can be configured with custom offsets for both closed and open keyboard states.\n *\n * @returns An animated View component that sticks to the keyboard.\n * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-sticky-view|Documentation} page for more details.\n * @example\n * ```tsx\n * <KeyboardStickyView offset={{ closed: 0, opened: 20 }}>\n * <Button title=\"Submit\" />\n * </KeyboardStickyView>\n * ```\n */\nconst KeyboardStickyView = forwardRef<\n View,\n React.PropsWithChildren<KeyboardStickyViewProps>\n>(\n (\n {\n children,\n offset: { closed = 0, opened = 0 } = {},\n style,\n enabled = true,\n ...props\n },\n ref,\n ) => {\n const { height, progress } = useKeyboardAnimation();\n\n const offset = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [closed, opened],\n });\n\n const styles = useMemo(() => {\n const disabled = Animated.add(Animated.multiply(height, 0), closed);\n const active = Animated.add(height, offset);\n\n return [\n {\n transform: [{ translateY: enabled ? active : disabled }],\n },\n style,\n ];\n }, [closed, enabled, height, offset, style]);\n\n return (\n <Animated.View ref={ref} style={styles} {...props}>\n {children}\n </Animated.View>\n );\n },\n);\n\nexport default KeyboardStickyView;\n"],"mappings":";AAAA,OAAOA,KAAK,IAAIC,UAAU,EAAEC,OAAO,QAAQ,OAAO;AAClD,SAASC,QAAQ,QAAQ,cAAc;AAEvC,SAASC,oBAAoB,QAAQ,aAAa;AAuBlD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,gBAAGJ,UAAU,CAInC,CACE;EACEK,QAAQ;EACRC,MAAM,EAAE;IAAEC,MAAM,GAAG,CAAC;IAAEC,MAAM,GAAG;EAAE,CAAC,GAAG,CAAC,CAAC;EACvCC,KAAK;EACLC,OAAO,GAAG,IAAI;EACd,GAAGC;AACL,CAAC,EACDC,GAAG,KACA;EACH,MAAM;IAAEC,MAAM;IAAEC;EAAS,CAAC,GAAGX,oBAAoB,CAAC,CAAC;EAEnD,MAAMG,MAAM,GAAGQ,QAAQ,CAACC,WAAW,CAAC;IAClCC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAClBC,WAAW,EAAE,CAACV,MAAM,EAAEC,MAAM;EAC9B,CAAC,CAAC;EAEF,MAAMU,MAAM,GAAGjB,OAAO,CAAC,MAAM;IAC3B,MAAMkB,QAAQ,GAAGjB,QAAQ,CAACkB,GAAG,CAAClB,QAAQ,CAACmB,QAAQ,CAACR,MAAM,EAAE,CAAC,CAAC,EAAEN,MAAM,CAAC;IACnE,MAAMe,MAAM,GAAGpB,QAAQ,CAACkB,GAAG,CAACP,MAAM,EAAEP,MAAM,CAAC;IAE3C,OAAO,CACL;MACEiB,SAAS,EAAE,CAAC;QAAEC,UAAU,EAAEd,OAAO,GAAGY,MAAM,GAAGH;MAAS,CAAC;IACzD,CAAC,EACDV,KAAK,CACN;EACH,CAAC,EAAE,CAACF,MAAM,EAAEG,OAAO,EAAEG,MAAM,EAAEP,MAAM,EAAEG,KAAK,CAAC,CAAC;EAE5C,oBACEV,KAAA,CAAA0B,aAAA,CAACvB,QAAQ,CAACwB,IAAI,EAAAC,QAAA;IAACf,GAAG,EAAEA,GAAI;IAACH,KAAK,EAAES;EAAO,GAAKP,KAAK,GAC9CN,QACY,CAAC;AAEpB,CACF,CAAC;AAED,eAAeD,kBAAkB","ignoreList":[]}
@@ -1,6 +1,6 @@
1
1
  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); }
2
2
  import React, { forwardRef } from "react";
3
- import { Platform } from "react-native";
3
+ import { Platform, View } from "react-native";
4
4
  import Reanimated, { useAnimatedProps } from "react-native-reanimated";
5
5
  import { ClippingScrollView } from "../../bindings";
6
6
  import styles from "./styles";
@@ -13,14 +13,14 @@ const ScrollViewWithBottomPadding = /*#__PURE__*/forwardRef(({
13
13
  scrollIndicatorInsets,
14
14
  inverted,
15
15
  contentOffsetY,
16
- containerStyle,
17
16
  children,
18
- style,
19
17
  ...rest
20
18
  }, ref) => {
21
19
  const animatedProps = useAnimatedProps(() => {
22
- const bottom = inverted ? 0 : bottomPadding.value + ((contentInset === null || contentInset === void 0 ? void 0 : contentInset.bottom) || 0);
23
- const top = !inverted ? 0 : bottomPadding.value + ((contentInset === null || contentInset === void 0 ? void 0 : contentInset.top) || 0);
20
+ const insetTop = inverted ? bottomPadding.value : 0;
21
+ const insetBottom = !inverted ? bottomPadding.value : 0;
22
+ const bottom = insetBottom + ((contentInset === null || contentInset === void 0 ? void 0 : contentInset.bottom) || 0);
23
+ const top = insetTop + ((contentInset === null || contentInset === void 0 ? void 0 : contentInset.top) || 0);
24
24
  const result = {
25
25
  // iOS prop
26
26
  contentInset: {
@@ -36,7 +36,8 @@ const ScrollViewWithBottomPadding = /*#__PURE__*/forwardRef(({
36
36
  left: scrollIndicatorInsets === null || scrollIndicatorInsets === void 0 ? void 0 : scrollIndicatorInsets.left
37
37
  },
38
38
  // Android prop
39
- contentInsetBottom: bottomPadding.value
39
+ contentInsetBottom: insetBottom,
40
+ contentInsetTop: insetTop
40
41
  };
41
42
  if (contentOffsetY) {
42
43
  result.contentOffset = {
@@ -48,12 +49,20 @@ const ScrollViewWithBottomPadding = /*#__PURE__*/forwardRef(({
48
49
  }, [contentInset === null || contentInset === void 0 ? void 0 : contentInset.bottom, contentInset === null || contentInset === void 0 ? void 0 : contentInset.top, contentInset === null || contentInset === void 0 ? void 0 : contentInset.right, contentInset === null || contentInset === void 0 ? void 0 : contentInset.left, scrollIndicatorInsets === null || scrollIndicatorInsets === void 0 ? void 0 : scrollIndicatorInsets.bottom, scrollIndicatorInsets === null || scrollIndicatorInsets === void 0 ? void 0 : scrollIndicatorInsets.top, scrollIndicatorInsets === null || scrollIndicatorInsets === void 0 ? void 0 : scrollIndicatorInsets.right, scrollIndicatorInsets === null || scrollIndicatorInsets === void 0 ? void 0 : scrollIndicatorInsets.left, inverted, contentOffsetY]);
49
50
  return /*#__PURE__*/React.createElement(ReanimatedClippingScrollView, {
50
51
  animatedProps: animatedProps,
51
- style: [styles.container, OS === "android" ? containerStyle : undefined]
52
+ style: styles.container
52
53
  }, /*#__PURE__*/React.createElement(ScrollViewComponent, _extends({
53
54
  ref: ref,
54
- animatedProps: animatedProps,
55
- style: style
56
- }, rest), children));
55
+ animatedProps: animatedProps
56
+ }, rest), inverted ?
57
+ /*#__PURE__*/
58
+ // The only thing it can break is `StickyHeader`, but it's already broken in FlatList and other lists
59
+ // don't support this functionality, so we can add additional view here
60
+ // The correct fix would be to add a new prop in ScrollView that allows
61
+ // to customize children extraction logic and skip custom view
62
+ React.createElement(View, {
63
+ collapsable: false,
64
+ nativeID: "container"
65
+ }, children) : children));
57
66
  });
58
67
  export default ScrollViewWithBottomPadding;
59
68
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","forwardRef","Platform","Reanimated","useAnimatedProps","ClippingScrollView","styles","OS","ReanimatedClippingScrollView","createAnimatedComponent","ScrollViewWithBottomPadding","ScrollViewComponent","bottomPadding","contentInset","scrollIndicatorInsets","inverted","contentOffsetY","containerStyle","children","style","rest","ref","animatedProps","bottom","value","top","result","right","left","contentInsetBottom","contentOffset","x","y","createElement","container","undefined","_extends"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef } from \"react\";\nimport { Platform } from \"react-native\";\nimport Reanimated, { useAnimatedProps } from \"react-native-reanimated\";\n\nimport { ClippingScrollView } from \"../../bindings\";\n\nimport styles from \"./styles\";\n\nimport type { ScrollViewProps, StyleProp, ViewStyle } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\nconst OS = Platform.OS;\nconst ReanimatedClippingScrollView =\n OS === \"android\"\n ? Reanimated.createAnimatedComponent(ClippingScrollView)\n : ClippingScrollView;\n\ntype AnimatedScrollViewProps = React.ComponentProps<\n typeof Reanimated.ScrollView\n>;\n\nexport type AnimatedScrollViewComponent = React.ForwardRefExoticComponent<\n AnimatedScrollViewProps & React.RefAttributes<Reanimated.ScrollView>\n>;\n\ntype ScrollViewWithBottomPaddingProps = {\n ScrollViewComponent: AnimatedScrollViewComponent;\n children?: React.ReactNode;\n inverted?: boolean;\n bottomPadding: SharedValue<number>;\n /** Absolute Y content offset (iOS only, for ChatKit). */\n contentOffsetY?: SharedValue<number>;\n /** Style applied to the container wrapper (Android only, for ChatKit translateY). */\n containerStyle?: StyleProp<ViewStyle>;\n} & ScrollViewProps;\n\nconst ScrollViewWithBottomPadding = forwardRef<\n Reanimated.ScrollView,\n ScrollViewWithBottomPaddingProps\n>(\n (\n {\n ScrollViewComponent,\n bottomPadding,\n contentInset,\n scrollIndicatorInsets,\n inverted,\n contentOffsetY,\n containerStyle,\n children,\n style,\n ...rest\n },\n ref,\n ) => {\n const animatedProps = useAnimatedProps(() => {\n const bottom = inverted\n ? 0\n : bottomPadding.value + (contentInset?.bottom || 0);\n const top = !inverted\n ? 0\n : bottomPadding.value + (contentInset?.top || 0);\n\n const result: Record<string, unknown> = {\n // iOS prop\n contentInset: {\n bottom: bottom,\n top: top,\n right: contentInset?.right,\n left: contentInset?.left,\n },\n scrollIndicatorInsets: {\n bottom: bottom,\n top: top,\n right: scrollIndicatorInsets?.right,\n left: scrollIndicatorInsets?.left,\n },\n // Android prop\n contentInsetBottom: bottomPadding.value,\n };\n\n if (contentOffsetY) {\n result.contentOffset = { x: 0, y: contentOffsetY.value };\n }\n\n return result;\n }, [\n contentInset?.bottom,\n contentInset?.top,\n contentInset?.right,\n contentInset?.left,\n scrollIndicatorInsets?.bottom,\n scrollIndicatorInsets?.top,\n scrollIndicatorInsets?.right,\n scrollIndicatorInsets?.left,\n inverted,\n contentOffsetY,\n ]);\n\n return (\n <ReanimatedClippingScrollView\n animatedProps={animatedProps}\n style={[\n styles.container,\n OS === \"android\" ? containerStyle : undefined,\n ]}\n >\n <ScrollViewComponent\n ref={ref}\n animatedProps={animatedProps}\n style={style}\n {...rest}\n >\n {children}\n </ScrollViewComponent>\n </ReanimatedClippingScrollView>\n );\n },\n);\n\nexport default ScrollViewWithBottomPadding;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","forwardRef","Platform","View","Reanimated","useAnimatedProps","ClippingScrollView","styles","OS","ReanimatedClippingScrollView","createAnimatedComponent","ScrollViewWithBottomPadding","ScrollViewComponent","bottomPadding","contentInset","scrollIndicatorInsets","inverted","contentOffsetY","children","rest","ref","animatedProps","insetTop","value","insetBottom","bottom","top","result","right","left","contentInsetBottom","contentInsetTop","contentOffset","x","y","createElement","style","container","_extends","collapsable","nativeID"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef } from \"react\";\nimport { Platform, View } from \"react-native\";\nimport Reanimated, { useAnimatedProps } from \"react-native-reanimated\";\n\nimport { ClippingScrollView } from \"../../bindings\";\n\nimport styles from \"./styles\";\n\nimport type { ScrollViewProps } from \"react-native\";\nimport type { SharedValue } from \"react-native-reanimated\";\n\nconst OS = Platform.OS;\nconst ReanimatedClippingScrollView =\n OS === \"android\"\n ? Reanimated.createAnimatedComponent(ClippingScrollView)\n : ClippingScrollView;\n\ntype AnimatedScrollViewProps = React.ComponentProps<\n typeof Reanimated.ScrollView\n>;\n\nexport type AnimatedScrollViewComponent = React.ForwardRefExoticComponent<\n AnimatedScrollViewProps & React.RefAttributes<Reanimated.ScrollView>\n>;\n\ntype ScrollViewWithBottomPaddingProps = {\n ScrollViewComponent: AnimatedScrollViewComponent;\n children?: React.ReactNode;\n inverted?: boolean;\n bottomPadding: SharedValue<number>;\n /** Absolute Y content offset (iOS only, for KeyboardChatScrollView). */\n contentOffsetY?: SharedValue<number>;\n} & ScrollViewProps;\n\nconst ScrollViewWithBottomPadding = forwardRef<\n Reanimated.ScrollView,\n ScrollViewWithBottomPaddingProps\n>(\n (\n {\n ScrollViewComponent,\n bottomPadding,\n contentInset,\n scrollIndicatorInsets,\n inverted,\n contentOffsetY,\n children,\n ...rest\n },\n ref,\n ) => {\n const animatedProps = useAnimatedProps(() => {\n const insetTop = inverted ? bottomPadding.value : 0;\n const insetBottom = !inverted ? bottomPadding.value : 0;\n const bottom = insetBottom + (contentInset?.bottom || 0);\n const top = insetTop + (contentInset?.top || 0);\n\n const result: Record<string, unknown> = {\n // iOS prop\n contentInset: {\n bottom: bottom,\n top: top,\n right: contentInset?.right,\n left: contentInset?.left,\n },\n scrollIndicatorInsets: {\n bottom: bottom,\n top: top,\n right: scrollIndicatorInsets?.right,\n left: scrollIndicatorInsets?.left,\n },\n // Android prop\n contentInsetBottom: insetBottom,\n contentInsetTop: insetTop,\n };\n\n if (contentOffsetY) {\n result.contentOffset = { x: 0, y: contentOffsetY.value };\n }\n\n return result;\n }, [\n contentInset?.bottom,\n contentInset?.top,\n contentInset?.right,\n contentInset?.left,\n scrollIndicatorInsets?.bottom,\n scrollIndicatorInsets?.top,\n scrollIndicatorInsets?.right,\n scrollIndicatorInsets?.left,\n inverted,\n contentOffsetY,\n ]);\n\n return (\n <ReanimatedClippingScrollView\n animatedProps={animatedProps}\n style={styles.container}\n >\n <ScrollViewComponent ref={ref} animatedProps={animatedProps} {...rest}>\n {inverted ? (\n // The only thing it can break is `StickyHeader`, but it's already broken in FlatList and other lists\n // don't support this functionality, so we can add additional view here\n // The correct fix would be to add a new prop in ScrollView that allows\n // to customize children extraction logic and skip custom view\n <View collapsable={false} nativeID=\"container\">\n {children}\n </View>\n ) : (\n children\n )}\n </ScrollViewComponent>\n </ReanimatedClippingScrollView>\n );\n },\n);\n\nexport default ScrollViewWithBottomPadding;\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import { useEffect } from "react";
1
+ import { useCallback, useEffect } from "react";
2
2
  import { useEvent, useSharedValue } from "react-native-reanimated";
3
3
  import { useEventHandlerRegistration } from "../../internal";
4
4
  const NATIVE_SCROLL_EVENT_NAMES = ["onScroll", "onScrollBeginDrag", "onScrollEndDrag", "onMomentumScrollBegin", "onMomentumScrollEnd"];
@@ -27,10 +27,29 @@ const useScrollState = ref => {
27
27
  cleanup();
28
28
  };
29
29
  }, []);
30
+
31
+ // `onContentSizeChange` is synthesized in JS (from the content container's
32
+ // onLayout) and `onLayout` has a different payload shape than scroll events,
33
+ // so neither can be reliably captured via native event registration.
34
+ // Instead we expose callbacks for the consumer to attach as props.
35
+ const onLayout = useCallback(e => {
36
+ layout.value = {
37
+ width: e.nativeEvent.layout.width,
38
+ height: e.nativeEvent.layout.height
39
+ };
40
+ }, [layout]);
41
+ const onContentSizeChange = useCallback((w, h) => {
42
+ size.value = {
43
+ width: w,
44
+ height: h
45
+ };
46
+ }, [size]);
30
47
  return {
31
48
  offset,
32
49
  layout,
33
- size
50
+ size,
51
+ onLayout,
52
+ onContentSizeChange
34
53
  };
35
54
  };
36
55
  export default useScrollState;
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useEvent","useSharedValue","useEventHandlerRegistration","NATIVE_SCROLL_EVENT_NAMES","useScrollState","ref","offset","layout","width","height","size","register","eventHandler","event","value","contentOffset","y","layoutMeasurement","contentSize","cleanup"],"sources":["useScrollState.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useEvent, useSharedValue } from \"react-native-reanimated\";\n\nimport { useEventHandlerRegistration } from \"../../internal\";\n\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\nconst NATIVE_SCROLL_EVENT_NAMES = [\n \"onScroll\",\n \"onScrollBeginDrag\",\n \"onScrollEndDrag\",\n \"onMomentumScrollBegin\",\n \"onMomentumScrollEnd\",\n];\n\ntype ScrollEvent = {\n contentOffset: {\n x: number;\n y: number;\n };\n layoutMeasurement: {\n width: number;\n height: number;\n };\n contentSize: {\n width: number;\n height: number;\n };\n};\n\nconst useScrollState = (ref: AnimatedRef<Reanimated.ScrollView>) => {\n const offset = useSharedValue(0);\n const layout = useSharedValue({ width: 0, height: 0 });\n const size = useSharedValue({ width: 0, height: 0 });\n\n const register = useEventHandlerRegistration(ref);\n\n const eventHandler = useEvent((event: ScrollEvent) => {\n \"worklet\";\n\n // eslint-disable-next-line react-compiler/react-compiler\n offset.value = event.contentOffset.y;\n layout.value = event.layoutMeasurement;\n size.value = event.contentSize;\n }, NATIVE_SCROLL_EVENT_NAMES);\n\n useEffect(() => {\n const cleanup = register(eventHandler);\n\n return () => {\n cleanup();\n };\n }, []);\n\n return { offset, layout, size };\n};\n\nexport default useScrollState;\n"],"mappings":"AAAA,SAASA,SAAS,QAAQ,OAAO;AACjC,SAASC,QAAQ,EAAEC,cAAc,QAAQ,yBAAyB;AAElE,SAASC,2BAA2B,QAAQ,gBAAgB;AAK5D,MAAMC,yBAAyB,GAAG,CAChC,UAAU,EACV,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,CACtB;AAiBD,MAAMC,cAAc,GAAIC,GAAuC,IAAK;EAClE,MAAMC,MAAM,GAAGL,cAAc,CAAC,CAAC,CAAC;EAChC,MAAMM,MAAM,GAAGN,cAAc,CAAC;IAAEO,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC,CAAC;EACtD,MAAMC,IAAI,GAAGT,cAAc,CAAC;IAAEO,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC,CAAC;EAEpD,MAAME,QAAQ,GAAGT,2BAA2B,CAACG,GAAG,CAAC;EAEjD,MAAMO,YAAY,GAAGZ,QAAQ,CAAEa,KAAkB,IAAK;IACpD,SAAS;;IAET;IACAP,MAAM,CAACQ,KAAK,GAAGD,KAAK,CAACE,aAAa,CAACC,CAAC;IACpCT,MAAM,CAACO,KAAK,GAAGD,KAAK,CAACI,iBAAiB;IACtCP,IAAI,CAACI,KAAK,GAAGD,KAAK,CAACK,WAAW;EAChC,CAAC,EAAEf,yBAAyB,CAAC;EAE7BJ,SAAS,CAAC,MAAM;IACd,MAAMoB,OAAO,GAAGR,QAAQ,CAACC,YAAY,CAAC;IAEtC,OAAO,MAAM;MACXO,OAAO,CAAC,CAAC;IACX,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAO;IAAEb,MAAM;IAAEC,MAAM;IAAEG;EAAK,CAAC;AACjC,CAAC;AAED,eAAeN,cAAc","ignoreList":[]}
1
+ {"version":3,"names":["useCallback","useEffect","useEvent","useSharedValue","useEventHandlerRegistration","NATIVE_SCROLL_EVENT_NAMES","useScrollState","ref","offset","layout","width","height","size","register","eventHandler","event","value","contentOffset","y","layoutMeasurement","contentSize","cleanup","onLayout","e","nativeEvent","onContentSizeChange","w","h"],"sources":["useScrollState.ts"],"sourcesContent":["import { useCallback, useEffect } from \"react\";\nimport { useEvent, useSharedValue } from \"react-native-reanimated\";\n\nimport { useEventHandlerRegistration } from \"../../internal\";\n\nimport type { LayoutChangeEvent } from \"react-native\";\nimport type { AnimatedRef } from \"react-native-reanimated\";\nimport type Reanimated from \"react-native-reanimated\";\n\nconst NATIVE_SCROLL_EVENT_NAMES = [\n \"onScroll\",\n \"onScrollBeginDrag\",\n \"onScrollEndDrag\",\n \"onMomentumScrollBegin\",\n \"onMomentumScrollEnd\",\n];\n\ntype ScrollEvent = {\n contentOffset: {\n x: number;\n y: number;\n };\n layoutMeasurement: {\n width: number;\n height: number;\n };\n contentSize: {\n width: number;\n height: number;\n };\n};\n\nconst useScrollState = (ref: AnimatedRef<Reanimated.ScrollView>) => {\n const offset = useSharedValue(0);\n const layout = useSharedValue({ width: 0, height: 0 });\n const size = useSharedValue({ width: 0, height: 0 });\n\n const register = useEventHandlerRegistration(ref);\n\n const eventHandler = useEvent((event: ScrollEvent) => {\n \"worklet\";\n\n // eslint-disable-next-line react-compiler/react-compiler\n offset.value = event.contentOffset.y;\n layout.value = event.layoutMeasurement;\n size.value = event.contentSize;\n }, NATIVE_SCROLL_EVENT_NAMES);\n\n useEffect(() => {\n const cleanup = register(eventHandler);\n\n return () => {\n cleanup();\n };\n }, []);\n\n // `onContentSizeChange` is synthesized in JS (from the content container's\n // onLayout) and `onLayout` has a different payload shape than scroll events,\n // so neither can be reliably captured via native event registration.\n // Instead we expose callbacks for the consumer to attach as props.\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n layout.value = {\n width: e.nativeEvent.layout.width,\n height: e.nativeEvent.layout.height,\n };\n },\n [layout],\n );\n\n const onContentSizeChange = useCallback(\n (w: number, h: number) => {\n size.value = { width: w, height: h };\n },\n [size],\n );\n\n return { offset, layout, size, onLayout, onContentSizeChange };\n};\n\nexport default useScrollState;\n"],"mappings":"AAAA,SAASA,WAAW,EAAEC,SAAS,QAAQ,OAAO;AAC9C,SAASC,QAAQ,EAAEC,cAAc,QAAQ,yBAAyB;AAElE,SAASC,2BAA2B,QAAQ,gBAAgB;AAM5D,MAAMC,yBAAyB,GAAG,CAChC,UAAU,EACV,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,CACtB;AAiBD,MAAMC,cAAc,GAAIC,GAAuC,IAAK;EAClE,MAAMC,MAAM,GAAGL,cAAc,CAAC,CAAC,CAAC;EAChC,MAAMM,MAAM,GAAGN,cAAc,CAAC;IAAEO,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC,CAAC;EACtD,MAAMC,IAAI,GAAGT,cAAc,CAAC;IAAEO,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE,CAAC,CAAC;EAEpD,MAAME,QAAQ,GAAGT,2BAA2B,CAACG,GAAG,CAAC;EAEjD,MAAMO,YAAY,GAAGZ,QAAQ,CAAEa,KAAkB,IAAK;IACpD,SAAS;;IAET;IACAP,MAAM,CAACQ,KAAK,GAAGD,KAAK,CAACE,aAAa,CAACC,CAAC;IACpCT,MAAM,CAACO,KAAK,GAAGD,KAAK,CAACI,iBAAiB;IACtCP,IAAI,CAACI,KAAK,GAAGD,KAAK,CAACK,WAAW;EAChC,CAAC,EAAEf,yBAAyB,CAAC;EAE7BJ,SAAS,CAAC,MAAM;IACd,MAAMoB,OAAO,GAAGR,QAAQ,CAACC,YAAY,CAAC;IAEtC,OAAO,MAAM;MACXO,OAAO,CAAC,CAAC;IACX,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;;EAEN;EACA;EACA;EACA;EACA,MAAMC,QAAQ,GAAGtB,WAAW,CACzBuB,CAAoB,IAAK;IACxBd,MAAM,CAACO,KAAK,GAAG;MACbN,KAAK,EAAEa,CAAC,CAACC,WAAW,CAACf,MAAM,CAACC,KAAK;MACjCC,MAAM,EAAEY,CAAC,CAACC,WAAW,CAACf,MAAM,CAACE;IAC/B,CAAC;EACH,CAAC,EACD,CAACF,MAAM,CACT,CAAC;EAED,MAAMgB,mBAAmB,GAAGzB,WAAW,CACrC,CAAC0B,CAAS,EAAEC,CAAS,KAAK;IACxBf,IAAI,CAACI,KAAK,GAAG;MAAEN,KAAK,EAAEgB,CAAC;MAAEf,MAAM,EAAEgB;IAAE,CAAC;EACtC,CAAC,EACD,CAACf,IAAI,CACP,CAAC;EAED,OAAO;IAAEJ,MAAM;IAAEC,MAAM;IAAEG,IAAI;IAAEU,QAAQ;IAAEG;EAAoB,CAAC;AAChE,CAAC;AAED,eAAenB,cAAc","ignoreList":[]}
@@ -2,5 +2,5 @@ export { default as KeyboardAvoidingView } from "./KeyboardAvoidingView";
2
2
  export { default as KeyboardStickyView } from "./KeyboardStickyView";
3
3
  export { default as KeyboardAwareScrollView } from "./KeyboardAwareScrollView";
4
4
  export { default as KeyboardToolbar, DefaultKeyboardToolbarTheme } from "./KeyboardToolbar";
5
- export { default as ChatKit } from "./ChatKit";
5
+ export { default as KeyboardChatScrollView } from "./KeyboardChatScrollView";
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["default","KeyboardAvoidingView","KeyboardStickyView","KeyboardAwareScrollView","KeyboardToolbar","DefaultKeyboardToolbarTheme","ChatKit"],"sources":["index.ts"],"sourcesContent":["export { default as KeyboardAvoidingView } from \"./KeyboardAvoidingView\";\nexport { default as KeyboardStickyView } from \"./KeyboardStickyView\";\nexport { default as KeyboardAwareScrollView } from \"./KeyboardAwareScrollView\";\nexport {\n default as KeyboardToolbar,\n DefaultKeyboardToolbarTheme,\n} from \"./KeyboardToolbar\";\nexport { default as ChatKit } from \"./ChatKit\";\nexport type { KeyboardAvoidingViewProps } from \"./KeyboardAvoidingView\";\nexport type { KeyboardStickyViewProps } from \"./KeyboardStickyView\";\nexport type {\n KeyboardAwareScrollViewProps,\n KeyboardAwareScrollViewRef,\n} from \"./KeyboardAwareScrollView\";\nexport type { KeyboardToolbarProps } from \"./KeyboardToolbar\";\nexport type { ChatKitScrollViewProps } from \"./ChatKit/types\";\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,oBAAoB,QAAQ,wBAAwB;AACxE,SAASD,OAAO,IAAIE,kBAAkB,QAAQ,sBAAsB;AACpE,SAASF,OAAO,IAAIG,uBAAuB,QAAQ,2BAA2B;AAC9E,SACEH,OAAO,IAAII,eAAe,EAC1BC,2BAA2B,QACtB,mBAAmB;AAC1B,SAASL,OAAO,IAAIM,OAAO,QAAQ,WAAW","ignoreList":[]}
1
+ {"version":3,"names":["default","KeyboardAvoidingView","KeyboardStickyView","KeyboardAwareScrollView","KeyboardToolbar","DefaultKeyboardToolbarTheme","KeyboardChatScrollView"],"sources":["index.ts"],"sourcesContent":["export { default as KeyboardAvoidingView } from \"./KeyboardAvoidingView\";\nexport { default as KeyboardStickyView } from \"./KeyboardStickyView\";\nexport { default as KeyboardAwareScrollView } from \"./KeyboardAwareScrollView\";\nexport {\n default as KeyboardToolbar,\n DefaultKeyboardToolbarTheme,\n} from \"./KeyboardToolbar\";\nexport { default as KeyboardChatScrollView } from \"./KeyboardChatScrollView\";\nexport type { KeyboardAvoidingViewProps } from \"./KeyboardAvoidingView\";\nexport type { KeyboardStickyViewProps } from \"./KeyboardStickyView\";\nexport type {\n KeyboardAwareScrollViewProps,\n KeyboardAwareScrollViewRef,\n} from \"./KeyboardAwareScrollView\";\nexport type { KeyboardToolbarProps } from \"./KeyboardToolbar\";\nexport type { KeyboardChatScrollViewProps } from \"./KeyboardChatScrollView/types\";\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,oBAAoB,QAAQ,wBAAwB;AACxE,SAASD,OAAO,IAAIE,kBAAkB,QAAQ,sBAAsB;AACpE,SAASF,OAAO,IAAIG,uBAAuB,QAAQ,2BAA2B;AAC9E,SACEH,OAAO,IAAII,eAAe,EAC1BC,2BAA2B,QACtB,mBAAmB;AAC1B,SAASL,OAAO,IAAIM,sBAAsB,QAAQ,0BAA0B","ignoreList":[]}
@@ -6,7 +6,7 @@ export * from "./constants";
6
6
  export * from "./module";
7
7
  export * from "./types";
8
8
  export * from "./compat";
9
- export { ChatKit, KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView,
9
+ export { KeyboardChatScrollView, KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView,
10
10
  // keyboard toolbar
11
11
  KeyboardToolbar, DefaultKeyboardToolbarTheme } from "./components";
12
12
  export { OverKeyboardView, KeyboardExtender } from "./views";
@@ -1 +1 @@
1
- {"version":3,"names":["ChatKit","KeyboardAvoidingView","KeyboardStickyView","KeyboardAwareScrollView","KeyboardToolbar","DefaultKeyboardToolbarTheme","OverKeyboardView","KeyboardExtender"],"sources":["index.ts"],"sourcesContent":["export * from \"./bindings\";\nexport * from \"./animated\";\nexport * from \"./context\";\nexport * from \"./hooks\";\nexport * from \"./constants\";\nexport * from \"./module\";\nexport * from \"./types\";\nexport * from \"./compat\";\n\nexport {\n ChatKit,\n KeyboardAvoidingView,\n KeyboardStickyView,\n KeyboardAwareScrollView,\n // keyboard toolbar\n KeyboardToolbar,\n DefaultKeyboardToolbarTheme,\n} from \"./components\";\nexport type {\n ChatKitScrollViewProps,\n KeyboardAvoidingViewProps,\n KeyboardStickyViewProps,\n KeyboardAwareScrollViewProps,\n KeyboardAwareScrollViewRef,\n KeyboardToolbarProps,\n} from \"./components\";\nexport { OverKeyboardView, KeyboardExtender } from \"./views\";\n"],"mappings":"AAAA,cAAc,YAAY;AAC1B,cAAc,YAAY;AAC1B,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,aAAa;AAC3B,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,UAAU;AAExB,SACEA,OAAO,EACPC,oBAAoB,EACpBC,kBAAkB,EAClBC,uBAAuB;AACvB;AACAC,eAAe,EACfC,2BAA2B,QACtB,cAAc;AASrB,SAASC,gBAAgB,EAAEC,gBAAgB,QAAQ,SAAS","ignoreList":[]}
1
+ {"version":3,"names":["KeyboardChatScrollView","KeyboardAvoidingView","KeyboardStickyView","KeyboardAwareScrollView","KeyboardToolbar","DefaultKeyboardToolbarTheme","OverKeyboardView","KeyboardExtender"],"sources":["index.ts"],"sourcesContent":["export * from \"./bindings\";\nexport * from \"./animated\";\nexport * from \"./context\";\nexport * from \"./hooks\";\nexport * from \"./constants\";\nexport * from \"./module\";\nexport * from \"./types\";\nexport * from \"./compat\";\n\nexport {\n KeyboardChatScrollView,\n KeyboardAvoidingView,\n KeyboardStickyView,\n KeyboardAwareScrollView,\n // keyboard toolbar\n KeyboardToolbar,\n DefaultKeyboardToolbarTheme,\n} from \"./components\";\nexport type {\n KeyboardChatScrollViewProps,\n KeyboardAvoidingViewProps,\n KeyboardStickyViewProps,\n KeyboardAwareScrollViewProps,\n KeyboardAwareScrollViewRef,\n KeyboardToolbarProps,\n} from \"./components\";\nexport { OverKeyboardView, KeyboardExtender } from \"./views\";\n"],"mappings":"AAAA,cAAc,YAAY;AAC1B,cAAc,YAAY;AAC1B,cAAc,WAAW;AACzB,cAAc,SAAS;AACvB,cAAc,aAAa;AAC3B,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,UAAU;AAExB,SACEA,sBAAsB,EACtBC,oBAAoB,EACpBC,kBAAkB,EAClBC,uBAAuB;AACvB;AACAC,eAAe,EACfC,2BAA2B,QACtB,cAAc;AASrB,SAASC,gBAAgB,EAAEC,gBAAgB,QAAQ,SAAS","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["codegenNativeComponent","interfaceOnly","excludedPlatforms"],"sources":["ClippingScrollViewDecoratorViewNativeComponent.ts"],"sourcesContent":["import { codegenNativeComponent } from \"react-native\";\n\nimport type { HostComponent } from \"react-native\";\nimport type { ViewProps } from \"react-native\";\nimport type { Double } from \"react-native/Libraries/Types/CodegenTypes\";\n\nexport interface NativeProps extends ViewProps {\n contentInsetBottom: Double;\n}\n\nexport default codegenNativeComponent<NativeProps>(\n \"ClippingScrollViewDecoratorView\",\n {\n interfaceOnly: true,\n excludedPlatforms: [\"iOS\"],\n },\n) as HostComponent<NativeProps>;\n"],"mappings":"AAAA,SAASA,sBAAsB,QAAQ,cAAc;AAUrD,eAAeA,sBAAsB,CACnC,iCAAiC,EACjC;EACEC,aAAa,EAAE,IAAI;EACnBC,iBAAiB,EAAE,CAAC,KAAK;AAC3B,CACF,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["codegenNativeComponent","interfaceOnly","excludedPlatforms"],"sources":["ClippingScrollViewDecoratorViewNativeComponent.ts"],"sourcesContent":["import { codegenNativeComponent } from \"react-native\";\n\nimport type { HostComponent } from \"react-native\";\nimport type { ViewProps } from \"react-native\";\nimport type { Double } from \"react-native/Libraries/Types/CodegenTypes\";\n\nexport interface NativeProps extends ViewProps {\n contentInsetBottom: Double;\n contentInsetTop: Double;\n}\n\nexport default codegenNativeComponent<NativeProps>(\n \"ClippingScrollViewDecoratorView\",\n {\n interfaceOnly: true,\n excludedPlatforms: [\"iOS\"],\n },\n) as HostComponent<NativeProps>;\n"],"mappings":"AAAA,SAASA,sBAAsB,QAAQ,cAAc;AAWrD,eAAeA,sBAAsB,CACnC,iCAAiC,EACjC;EACEC,aAAa,EAAE,IAAI;EACnBC,iBAAiB,EAAE,CAAC,KAAK;AAC3B,CACF,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["views.ts"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport type { ViewProps } from \"react-native\";\n\nexport type KeyboardGestureAreaProps = {\n /**\n * Determines how the keyboard position will be controlled:\n * - `ios` - keyboard will be following finger only when finger touches keyboard\n * - `linear` - keyboard will be following finger position linearly.\n *\n * @platform android\n */\n interpolator?: \"ios\" | \"linear\";\n /**\n * Whether to allow to show a keyboard from dismissed state by swipe up.\n * Default to `false`.\n *\n * @platform android\n */\n showOnSwipeUp?: boolean;\n /**\n * Whether to allow to control a keyboard by gestures. The strategy how\n * it should be controlled is determined by `interpolator` property.\n * Defaults to `true`.\n *\n * @platform android\n */\n enableSwipeToDismiss?: boolean;\n /**\n * Extra distance to the keyboard.\n */\n offset?: number;\n /**\n * A corresponding `nativeID` value from the associated `TextInput` (a string that links the `KeyboardGestureArea` to one or more `TextInput` components).\n * This is **required on iOS** in order to apply the `offset` when the keyboard is shown. Only the currently focused `TextInput` with a matching `nativeID`\n * will receive offset behavior.\n *\n * @platform ios\n */\n textInputNativeID?: string;\n} & ViewProps;\nexport type OverKeyboardViewProps = PropsWithChildren<{\n /**\n * A boolean prop indicating whether the view is visible or not. If it's true then view is shown on the screen. If it's false then view is hidden.\n */\n visible: boolean;\n}>;\nexport type KeyboardBackgroundViewProps = PropsWithChildren<ViewProps>;\nexport type KeyboardExtenderProps = PropsWithChildren<{\n /** Controls whether this `KeyboardExtender` instance should take an effect. Default is `true`. */\n enabled?: boolean;\n}>;\nexport type ClippingScrollViewProps = PropsWithChildren<\n ViewProps & {\n /** An additional space that gets applied to the bottom of the `ScrollView` (inside a scrollable content). Default is `0`. */\n contentInsetBottom?: number;\n }\n>;\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["views.ts"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport type { ViewProps } from \"react-native\";\n\nexport type KeyboardGestureAreaProps = {\n /**\n * Determines how the keyboard position will be controlled:\n * - `ios` - keyboard will be following finger only when finger touches keyboard\n * - `linear` - keyboard will be following finger position linearly.\n *\n * @platform android\n */\n interpolator?: \"ios\" | \"linear\";\n /**\n * Whether to allow to show a keyboard from dismissed state by swipe up.\n * Default to `false`.\n *\n * @platform android\n */\n showOnSwipeUp?: boolean;\n /**\n * Whether to allow to control a keyboard by gestures. The strategy how\n * it should be controlled is determined by `interpolator` property.\n * Defaults to `true`.\n *\n * @platform android\n */\n enableSwipeToDismiss?: boolean;\n /**\n * Extra distance to the keyboard.\n */\n offset?: number;\n /**\n * A corresponding `nativeID` value from the associated `TextInput` (a string that links the `KeyboardGestureArea` to one or more `TextInput` components).\n * This is **required on iOS** in order to apply the `offset` when the keyboard is shown. Only the currently focused `TextInput` with a matching `nativeID`\n * will receive offset behavior.\n *\n * @platform ios\n */\n textInputNativeID?: string;\n} & ViewProps;\nexport type OverKeyboardViewProps = PropsWithChildren<{\n /**\n * A boolean prop indicating whether the view is visible or not. If it's true then view is shown on the screen. If it's false then view is hidden.\n */\n visible: boolean;\n}>;\nexport type KeyboardBackgroundViewProps = PropsWithChildren<ViewProps>;\nexport type KeyboardExtenderProps = PropsWithChildren<{\n /** Controls whether this `KeyboardExtender` instance should take an effect. Default is `true`. */\n enabled?: boolean;\n}>;\nexport type ClippingScrollViewProps = PropsWithChildren<\n ViewProps & {\n /** An additional space that gets applied to the bottom of the `ScrollView` (inside a scrollable content). Default is `0`. */\n contentInsetBottom?: number;\n /** An additional space that gets applied to the top of the `ScrollView` (inside a scrollable content). Default is `0`. */\n contentInsetTop?: number;\n }\n>;\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export { useChatKeyboard } from "./useChatKeyboard";
2
+ export type { KeyboardLiftBehavior } from "./useChatKeyboard/types";
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import Reanimated from "react-native-reanimated";
3
+ declare const KeyboardChatScrollView: React.ForwardRefExoticComponent<{
4
+ ScrollViewComponent?: import("../ScrollViewWithBottomPadding").AnimatedScrollViewComponent;
5
+ inverted?: boolean;
6
+ offset?: number;
7
+ keyboardLiftBehavior?: import("./hooks").KeyboardLiftBehavior;
8
+ freeze?: boolean;
9
+ } & import("react-native").ScrollViewProps & {
10
+ children?: React.ReactNode | undefined;
11
+ } & React.RefAttributes<Reanimated.ScrollView>>;
12
+ export default KeyboardChatScrollView;
@@ -1,14 +1,14 @@
1
1
  import type { AnimatedScrollViewComponent } from "../ScrollViewWithBottomPadding";
2
+ import type { KeyboardLiftBehavior } from "./useChatKeyboard/types";
2
3
  import type { ScrollViewProps } from "react-native";
3
- type KeyboardLiftBehavior = "always" | "whenAtEnd" | "persistent" | "never";
4
- export type ChatKitScrollViewProps = {
4
+ export type KeyboardChatScrollViewProps = {
5
5
  /** Custom component for `ScrollView`. Default is `ScrollView`. */
6
- ScrollViewComponent: AnimatedScrollViewComponent;
6
+ ScrollViewComponent?: AnimatedScrollViewComponent;
7
7
  /** Whether list are using `inverted` prop. Default is `false`. */
8
8
  inverted?: boolean;
9
9
  /**
10
- * The distance (in pixels) between the bottom of the screen and the `ScrollView`.
11
- * When the keyboard appears, the scroll view will only push content by the effective
10
+ * The distance between the bottom of the screen and the `ScrollView`.
11
+ * When the keyboard appears, the `ScrollView` will only push content by the effective
12
12
  * distance (`keyboardHeight - offset`) instead of the full keyboard height.
13
13
  *
14
14
  * Useful when the input is not at the very bottom of the screen (e.g., above safe area, above
@@ -46,4 +46,3 @@ export type ChatKitScrollViewProps = {
46
46
  */
47
47
  freeze?: boolean;
48
48
  } & ScrollViewProps;
49
- export {};
@@ -1,17 +1,38 @@
1
- type KeyboardLiftBehavior = "always" | "whenAtEnd" | "persistent" | "never";
1
+ import type { KeyboardLiftBehavior } from "./types";
2
+ /**
3
+ * Map the current keyboard height to an effective height that accounts for a
4
+ * fixed offset (e.g. bottom safe-area or tab-bar height).
5
+ *
6
+ * @param height - Current keyboard height.
7
+ * @param targetKeyboardHeight - Full target keyboard height (captured on keyboard open).
8
+ * @param offset - Fixed distance between the scroll-view bottom and the screen bottom.
9
+ * @returns Effective height after subtracting the offset proportionally.
10
+ * @example
11
+ * ```ts
12
+ * getEffectiveHeight(300, 300, 50); // 250
13
+ * getEffectiveHeight(150, 300, 50); // 125
14
+ * ```
15
+ */
16
+ export declare function getEffectiveHeight(height: number, targetKeyboardHeight: number, offset: number): number;
2
17
  /**
3
18
  * Check whether the scroll view is at the end of its content.
4
19
  *
20
+ * For non-inverted lists the "end" is the bottom of the content.
21
+ * For inverted lists the "end" is the top (scroll offset near 0),
22
+ * because that is where the latest messages are displayed.
23
+ *
5
24
  * @param scrollOffset - Current vertical scroll offset.
6
25
  * @param layoutHeight - Visible height of the scroll view.
7
26
  * @param contentHeight - Total height of the scrollable content.
27
+ * @param inverted - Whether the list is inverted.
8
28
  * @returns `true` if the scroll position is within the threshold of the content end.
9
29
  * @example
10
30
  * ```ts
11
31
  * const atEnd = isScrollAtEnd(100, 800, 920); // true (100 + 800 >= 920 - 20)
32
+ * const atEndInverted = isScrollAtEnd(5, 800, 2000, true); // true (5 <= 20)
12
33
  * ```
13
34
  */
14
- export declare function isScrollAtEnd(scrollOffset: number, layoutHeight: number, contentHeight: number): boolean;
35
+ export declare function isScrollAtEnd(scrollOffset: number, layoutHeight: number, contentHeight: number, inverted?: boolean): boolean;
15
36
  /**
16
37
  * Decide whether content should be shifted based on the keyboard lift behavior.
17
38
  *
@@ -54,4 +75,3 @@ export declare function clampedScrollTarget(offsetBeforeScroll: number, keyboard
54
75
  * ```
55
76
  */
56
77
  export declare function computeIOSContentOffset(relativeScroll: number, keyboardHeight: number, contentHeight: number, layoutHeight: number, inverted: boolean): number;
57
- export {};
@@ -0,0 +1,21 @@
1
+ import type { UseChatKeyboardOptions, UseChatKeyboardReturn } from "./types";
2
+ import type { AnimatedRef } from "react-native-reanimated";
3
+ import type Reanimated from "react-native-reanimated";
4
+ /**
5
+ * Hook that manages keyboard-driven scrolling for chat-style scroll views.
6
+ * Calculates padding (extra scrollable space) and content shift values,
7
+ * using per-frame scrollTo updates (Android and other platforms).
8
+ *
9
+ * @param scrollViewRef - Animated ref to the scroll view.
10
+ * @param options - Configuration for inverted and keyboardLiftBehavior.
11
+ * @returns Shared values for padding and contentOffsetY (always `undefined`).
12
+ * @example
13
+ * ```tsx
14
+ * const { padding, contentOffsetY } = useChatKeyboard(ref, {
15
+ * inverted: false,
16
+ * keyboardLiftBehavior: "always",
17
+ * });
18
+ * ```
19
+ */
20
+ declare function useChatKeyboard(scrollViewRef: AnimatedRef<Reanimated.ScrollView>, options: UseChatKeyboardOptions): UseChatKeyboardReturn;
21
+ export { useChatKeyboard };