react-native-keyboard-controller 1.21.6 → 1.21.8

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 (32) hide show
  1. package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +58 -25
  2. package/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +11 -1
  3. package/ios/observers/movement/KeyboardViewLocator.swift +1 -1
  4. package/ios/views/ClippingScrollViewDecoratorViewManager.mm +6 -0
  5. package/lib/commonjs/components/KeyboardChatScrollView/index.js +9 -0
  6. package/lib/commonjs/components/KeyboardChatScrollView/index.js.map +1 -1
  7. package/lib/commonjs/components/KeyboardChatScrollView/types.js.map +1 -1
  8. package/lib/commonjs/components/KeyboardChatScrollView/useEndVisible.js +40 -0
  9. package/lib/commonjs/components/KeyboardChatScrollView/useEndVisible.js.map +1 -0
  10. package/lib/commonjs/components/KeyboardStickyView/index.js +10 -14
  11. package/lib/commonjs/components/KeyboardStickyView/index.js.map +1 -1
  12. package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js +34 -13
  13. package/lib/commonjs/components/ScrollViewWithBottomPadding/index.js.map +1 -1
  14. package/lib/module/components/KeyboardChatScrollView/index.js +9 -0
  15. package/lib/module/components/KeyboardChatScrollView/index.js.map +1 -1
  16. package/lib/module/components/KeyboardChatScrollView/types.js.map +1 -1
  17. package/lib/module/components/KeyboardChatScrollView/useEndVisible.js +33 -0
  18. package/lib/module/components/KeyboardChatScrollView/useEndVisible.js.map +1 -0
  19. package/lib/module/components/KeyboardStickyView/index.js +11 -15
  20. package/lib/module/components/KeyboardStickyView/index.js.map +1 -1
  21. package/lib/module/components/ScrollViewWithBottomPadding/index.js +35 -14
  22. package/lib/module/components/ScrollViewWithBottomPadding/index.js.map +1 -1
  23. package/lib/typescript/components/KeyboardChatScrollView/index.d.ts +2 -0
  24. package/lib/typescript/components/KeyboardChatScrollView/types.d.ts +25 -1
  25. package/lib/typescript/components/KeyboardChatScrollView/useEndVisible.d.ts +17 -0
  26. package/lib/typescript/components/ScrollViewWithBottomPadding/index.d.ts +12 -0
  27. package/package.json +1 -1
  28. package/src/components/KeyboardChatScrollView/index.tsx +10 -0
  29. package/src/components/KeyboardChatScrollView/types.ts +28 -1
  30. package/src/components/KeyboardChatScrollView/useEndVisible.ts +66 -0
  31. package/src/components/KeyboardStickyView/index.tsx +18 -19
  32. package/src/components/ScrollViewWithBottomPadding/index.tsx +65 -16
@@ -1,7 +1,10 @@
1
1
  import React, { forwardRef } from "react";
2
2
  import { Platform } from "react-native";
3
3
  import Reanimated, {
4
+ runOnJS,
4
5
  useAnimatedProps,
6
+ useAnimatedReaction,
7
+ useDerivedValue,
5
8
  useSharedValue,
6
9
  } from "react-native-reanimated";
7
10
 
@@ -26,6 +29,13 @@ export type AnimatedScrollViewComponent = React.ForwardRefExoticComponent<
26
29
  AnimatedScrollViewProps & React.RefAttributes<Reanimated.ScrollView>
27
30
  >;
28
31
 
32
+ export type ScrollViewContentInsets = {
33
+ top: number;
34
+ bottom: number;
35
+ left: number;
36
+ right: number;
37
+ };
38
+
29
39
  type ScrollViewWithBottomPaddingProps = {
30
40
  ScrollViewComponent: AnimatedScrollViewComponent;
31
41
  children?: React.ReactNode;
@@ -36,6 +46,12 @@ type ScrollViewWithBottomPaddingProps = {
36
46
  /** Absolute Y content offset (iOS only, for KeyboardChatScrollView). */
37
47
  contentOffsetY?: SharedValue<number>;
38
48
  applyWorkaroundForContentInsetHitTestBug?: boolean;
49
+ /**
50
+ * Fires whenever the effective content inset changes (combines the static `contentInset`
51
+ * prop with the dynamic keyboard-driven padding). Useful on Android where the synthetic
52
+ * inset is not reflected in `onScroll` events.
53
+ */
54
+ onContentInsetChange?: (insets: ScrollViewContentInsets) => void;
39
55
  } & ScrollViewProps;
40
56
 
41
57
  const ScrollViewWithBottomPadding = forwardRef<
@@ -52,6 +68,7 @@ const ScrollViewWithBottomPadding = forwardRef<
52
68
  inverted,
53
69
  contentOffsetY,
54
70
  applyWorkaroundForContentInsetHitTestBug,
71
+ onContentInsetChange,
55
72
  children,
56
73
  ...rest
57
74
  },
@@ -59,11 +76,52 @@ const ScrollViewWithBottomPadding = forwardRef<
59
76
  ) => {
60
77
  const prevContentOffsetY = useSharedValue<number | null>(null);
61
78
 
79
+ const insets = useDerivedValue(() => {
80
+ const dynamicTop = inverted ? bottomPadding.value : 0;
81
+ const dynamicBottom = !inverted ? bottomPadding.value : 0;
82
+
83
+ return {
84
+ dynamic: {
85
+ top: dynamicTop,
86
+ bottom: dynamicBottom,
87
+ },
88
+ effective: {
89
+ top: dynamicTop + (contentInset?.top || 0),
90
+ bottom: dynamicBottom + (contentInset?.bottom || 0),
91
+ left: contentInset?.left || 0,
92
+ right: contentInset?.right || 0,
93
+ } as ScrollViewContentInsets,
94
+ };
95
+ }, [
96
+ inverted,
97
+ contentInset?.top,
98
+ contentInset?.bottom,
99
+ contentInset?.left,
100
+ contentInset?.right,
101
+ ]);
102
+
103
+ useAnimatedReaction(
104
+ () => insets.value.effective,
105
+ (current, previous) => {
106
+ if (!onContentInsetChange) {
107
+ return;
108
+ }
109
+ if (
110
+ previous &&
111
+ current.top === previous.top &&
112
+ current.bottom === previous.bottom &&
113
+ current.left === previous.left &&
114
+ current.right === previous.right
115
+ ) {
116
+ return;
117
+ }
118
+ runOnJS(onContentInsetChange)(current);
119
+ },
120
+ [onContentInsetChange],
121
+ );
122
+
62
123
  const animatedProps = useAnimatedProps(() => {
63
- const insetTop = inverted ? bottomPadding.value : 0;
64
- const insetBottom = !inverted ? bottomPadding.value : 0;
65
- const bottom = insetBottom + (contentInset?.bottom || 0);
66
- const top = insetTop + (contentInset?.top || 0);
124
+ const { dynamic, effective } = insets.value;
67
125
 
68
126
  const indicatorPadding = scrollIndicatorPadding ?? bottomPadding;
69
127
  const indicatorTop =
@@ -75,12 +133,7 @@ const ScrollViewWithBottomPadding = forwardRef<
75
133
 
76
134
  const result: Record<string, unknown> = {
77
135
  // iOS prop
78
- contentInset: {
79
- bottom: bottom,
80
- top: top,
81
- right: contentInset?.right,
82
- left: contentInset?.left,
83
- },
136
+ contentInset: effective,
84
137
  scrollIndicatorInsets: {
85
138
  bottom: indicatorBottom,
86
139
  top: indicatorTop,
@@ -88,8 +141,8 @@ const ScrollViewWithBottomPadding = forwardRef<
88
141
  left: scrollIndicatorInsets?.left,
89
142
  },
90
143
  // Android prop
91
- contentInsetBottom: insetBottom,
92
- contentInsetTop: insetTop,
144
+ contentInsetBottom: dynamic.bottom,
145
+ contentInsetTop: dynamic.top,
93
146
  };
94
147
 
95
148
  if (contentOffsetY) {
@@ -104,10 +157,6 @@ const ScrollViewWithBottomPadding = forwardRef<
104
157
 
105
158
  return result;
106
159
  }, [
107
- contentInset?.bottom,
108
- contentInset?.top,
109
- contentInset?.right,
110
- contentInset?.left,
111
160
  scrollIndicatorInsets?.bottom,
112
161
  scrollIndicatorInsets?.top,
113
162
  scrollIndicatorInsets?.right,