@legendapp/list 3.0.0-beta.20 → 3.0.0-beta.21

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.
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ import { LegendList as LegendList$1, LegendListProps, LegendListRef } from '@legendapp/list';
3
+ import { AnimatedLegendList } from '@legendapp/list/animated';
4
+ import { AnimatedLegendList as AnimatedLegendList$1 } from '@legendapp/list/reanimated';
5
+
6
+ declare const LegendList: <ItemT, ListT extends typeof LegendList$1 | typeof AnimatedLegendList | typeof AnimatedLegendList$1 = (<T>(props: LegendListProps<T> & React.RefAttributes<LegendListRef>) => React.ReactNode) & {
7
+ displayName?: string;
8
+ }>(props: (LegendListProps<ItemT> & {
9
+ LegendList?: ListT;
10
+ }) & React.RefAttributes<LegendListRef>) => React.ReactNode;
11
+
12
+ export { LegendList };
@@ -0,0 +1,69 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactNative = require('react-native');
5
+ var reactNativeKeyboardController = require('react-native-keyboard-controller');
6
+ var reactNativeReanimated = require('react-native-reanimated');
7
+ var list = require('@legendapp/list');
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
+
29
+ // src/integrations/keyboard-controller.tsx
30
+ var typedForwardRef = React.forwardRef;
31
+ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
32
+ const {
33
+ LegendList: LegendListProp,
34
+ contentContainerStyle: contentContainerStyleProp,
35
+ scrollIndicatorInsets: scrollIndicatorInsetsProp,
36
+ ...rest
37
+ } = props;
38
+ const [padding, setPadding] = React.useState(0);
39
+ const updatePadding = (height) => {
40
+ setPadding(height);
41
+ };
42
+ reactNativeKeyboardController.useKeyboardHandler({
43
+ onEnd: (e) => {
44
+ "worklet";
45
+ reactNativeReanimated.runOnJS(updatePadding)(e.height);
46
+ }
47
+ });
48
+ const LegendListComponent = LegendListProp != null ? LegendListProp : list.LegendList;
49
+ const contentContainerStyleFlattened = reactNative.StyleSheet.flatten(contentContainerStyleProp) || {};
50
+ const contentContainerStyle = { ...contentContainerStyleFlattened, paddingTop: padding };
51
+ const scrollIndicatorInsets = scrollIndicatorInsetsProp ? { ...scrollIndicatorInsetsProp } : {};
52
+ if (!props.horizontal) {
53
+ scrollIndicatorInsets.top = ((scrollIndicatorInsets == null ? void 0 : scrollIndicatorInsets.top) || 0) + padding;
54
+ }
55
+ return (
56
+ // @ts-expect-error TODO: Fix this type
57
+ /* @__PURE__ */ React__namespace.createElement(
58
+ LegendListComponent,
59
+ {
60
+ ...rest,
61
+ contentContainerStyle,
62
+ ref: forwardedRef,
63
+ scrollIndicatorInsets
64
+ }
65
+ )
66
+ );
67
+ });
68
+
69
+ exports.LegendList = LegendList;
@@ -0,0 +1,48 @@
1
+ import * as React from 'react';
2
+ import { useState, forwardRef } from 'react';
3
+ import { StyleSheet } from 'react-native';
4
+ import { useKeyboardHandler } from 'react-native-keyboard-controller';
5
+ import { runOnJS } from 'react-native-reanimated';
6
+ import { LegendList as LegendList$1 } from '@legendapp/list';
7
+
8
+ // src/integrations/keyboard-controller.tsx
9
+ var typedForwardRef = forwardRef;
10
+ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
11
+ const {
12
+ LegendList: LegendListProp,
13
+ contentContainerStyle: contentContainerStyleProp,
14
+ scrollIndicatorInsets: scrollIndicatorInsetsProp,
15
+ ...rest
16
+ } = props;
17
+ const [padding, setPadding] = useState(0);
18
+ const updatePadding = (height) => {
19
+ setPadding(height);
20
+ };
21
+ useKeyboardHandler({
22
+ onEnd: (e) => {
23
+ "worklet";
24
+ runOnJS(updatePadding)(e.height);
25
+ }
26
+ });
27
+ const LegendListComponent = LegendListProp != null ? LegendListProp : LegendList$1;
28
+ const contentContainerStyleFlattened = StyleSheet.flatten(contentContainerStyleProp) || {};
29
+ const contentContainerStyle = { ...contentContainerStyleFlattened, paddingTop: padding };
30
+ const scrollIndicatorInsets = scrollIndicatorInsetsProp ? { ...scrollIndicatorInsetsProp } : {};
31
+ if (!props.horizontal) {
32
+ scrollIndicatorInsets.top = ((scrollIndicatorInsets == null ? void 0 : scrollIndicatorInsets.top) || 0) + padding;
33
+ }
34
+ return (
35
+ // @ts-expect-error TODO: Fix this type
36
+ /* @__PURE__ */ React.createElement(
37
+ LegendListComponent,
38
+ {
39
+ ...rest,
40
+ contentContainerStyle,
41
+ ref: forwardedRef,
42
+ scrollIndicatorInsets
43
+ }
44
+ )
45
+ );
46
+ });
47
+
48
+ export { LegendList };
package/keyboard.js CHANGED
@@ -28,6 +28,9 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
28
 
29
29
  // src/integrations/keyboard.tsx
30
30
 
31
+ // src/constants-platform.ts
32
+ var IsNewArchitecture = true;
33
+
31
34
  // src/utils/helpers.ts
32
35
  function isFunction(obj) {
33
36
  return typeof obj === "function";
@@ -51,14 +54,33 @@ var useCombinedRef = (...refs) => {
51
54
  };
52
55
 
53
56
  // src/integrations/keyboard.tsx
57
+ var clampProgress = (progress) => {
58
+ "worklet";
59
+ return Math.min(1, Math.max(0, progress));
60
+ };
54
61
  var calculateKeyboardInset = (height, safeAreaInsetBottom, isNewArchitecture) => {
55
62
  "worklet";
56
63
  return Math.max(0, height - safeAreaInsetBottom) ;
57
64
  };
65
+ var calculateEndPaddingInset = (keyboardHeight, alignItemsAtEndPadding) => {
66
+ "worklet";
67
+ return Math.min(keyboardHeight, alignItemsAtEndPadding);
68
+ };
69
+ var calculateTopInset = (safeAreaInsetTop, isNewArchitecture, extraTopInset) => {
70
+ "worklet";
71
+ return (isNewArchitecture ? 0 : safeAreaInsetTop * 2) + extraTopInset;
72
+ };
73
+ var calculateKeyboardTargetOffset = (startOffset, keyboardHeight, isOpening, progress) => {
74
+ "worklet";
75
+ const normalizedProgress = isOpening ? progress : 1 - progress;
76
+ const delta = (isOpening ? keyboardHeight : -keyboardHeight) * normalizedProgress;
77
+ return Math.max(0, startOffset + delta);
78
+ };
58
79
  var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegendList2(props, forwardedRef) {
59
80
  const {
60
81
  contentInset: contentInsetProp,
61
82
  horizontal,
83
+ onMetricsChange: onMetricsChangeProp,
62
84
  onScroll: onScrollProp,
63
85
  safeAreaInsets = { bottom: 0, top: 0 },
64
86
  style: styleProp,
@@ -76,6 +98,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
76
98
  const mode = reactNativeReanimated.useSharedValue("idle");
77
99
  const keyboardInset = reactNativeReanimated.useSharedValue({ bottom: 0, top: 0 });
78
100
  const keyboardHeight = reactNativeReanimated.useSharedValue(0);
101
+ const alignItemsAtEndPadding = reactNativeReanimated.useSharedValue(0);
79
102
  const isOpening = reactNativeReanimated.useSharedValue(false);
80
103
  const didInteractive = reactNativeReanimated.useSharedValue(false);
81
104
  const { top: safeAreaInsetTop, bottom: safeAreaInsetBottom } = safeAreaInsets;
@@ -96,20 +119,52 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
96
119
  },
97
120
  [refLegendList]
98
121
  );
122
+ const handleMetricsChange = React.useCallback(
123
+ (metrics) => {
124
+ const nextPadding = metrics.alignItemsAtEndPadding || 0;
125
+ alignItemsAtEndPadding.set(nextPadding);
126
+ if (!horizontal) {
127
+ reactNativeReanimated.runOnUI((padding, safeInsetTop, isNewArchitecture) => {
128
+ "worklet";
129
+ if (!isKeyboardOpen.get()) {
130
+ return;
131
+ }
132
+ const vKeyboardHeight = keyboardHeight.get();
133
+ const vTopInset = calculateEndPaddingInset(vKeyboardHeight, padding);
134
+ const topInset = calculateTopInset(safeInsetTop, isNewArchitecture, vTopInset);
135
+ keyboardInset.set({
136
+ bottom: keyboardInset.get().bottom,
137
+ top: topInset
138
+ });
139
+ })(nextPadding, safeAreaInsetTop, IsNewArchitecture);
140
+ }
141
+ onMetricsChangeProp == null ? void 0 : onMetricsChangeProp(metrics);
142
+ },
143
+ [
144
+ alignItemsAtEndPadding,
145
+ horizontal,
146
+ isKeyboardOpen,
147
+ keyboardHeight,
148
+ keyboardInset,
149
+ onMetricsChangeProp,
150
+ safeAreaInsetTop
151
+ ]
152
+ );
99
153
  reactNativeKeyboardController.useKeyboardHandler(
100
154
  // biome-ignore assist/source/useSortedKeys: prefer start/move/end
101
155
  {
102
156
  onStart: (event) => {
103
157
  "worklet";
104
158
  mode.set("running");
105
- if (isKeyboardOpen.get() && event.progress === 1 && event.height > 0) {
159
+ const progress = clampProgress(event.progress);
160
+ if (isKeyboardOpen.get() && progress >= 1 && event.height > 0) {
106
161
  return;
107
162
  }
108
163
  if (!didInteractive.get()) {
109
164
  if (event.height > 0) {
110
165
  keyboardHeight.set(event.height - safeAreaInsetBottom);
111
166
  }
112
- isOpening.set(event.progress > 0);
167
+ isOpening.set(progress > 0);
113
168
  scrollOffsetAtKeyboardStart.set(scrollOffsetY.get());
114
169
  animatedOffsetY.set(scrollOffsetY.get());
115
170
  reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(false);
@@ -122,6 +177,13 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
122
177
  }
123
178
  mode.set("running");
124
179
  if (!didInteractive.get()) {
180
+ if (!isAndroid && !IsNewArchitecture) {
181
+ keyboardInset.set({
182
+ bottom: keyboardInset.get().bottom,
183
+ // Legacy iOS uses a doubled top inset to keep content below the status bar.
184
+ top: calculateTopInset(safeAreaInsetTop, IsNewArchitecture, 0)
185
+ });
186
+ }
125
187
  didInteractive.set(true);
126
188
  }
127
189
  if (isAndroid && !horizontal) {
@@ -132,18 +194,31 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
132
194
  onMove: (event) => {
133
195
  "worklet";
134
196
  if (!didInteractive.get()) {
197
+ const progress = clampProgress(event.progress);
135
198
  const vIsOpening = isOpening.get();
136
199
  const vKeyboardHeight = keyboardHeight.get();
137
- const vProgress = vIsOpening ? event.progress : 1 - event.progress;
138
- const targetOffset = Math.max(
139
- 0,
140
- scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * vProgress
200
+ const vAlignItemsPadding = alignItemsAtEndPadding.get();
201
+ const vTopInset = calculateEndPaddingInset(vKeyboardHeight, vAlignItemsPadding);
202
+ const targetOffset = calculateKeyboardTargetOffset(
203
+ scrollOffsetAtKeyboardStart.get(),
204
+ vKeyboardHeight,
205
+ vIsOpening,
206
+ progress
141
207
  );
142
208
  scrollOffsetY.set(targetOffset);
143
209
  animatedOffsetY.set(targetOffset);
144
210
  if (!horizontal) {
145
211
  const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
146
- keyboardInset.set({ bottom: newInset, top: 0 });
212
+ const topInset = calculateTopInset(
213
+ safeAreaInsetTop,
214
+ IsNewArchitecture,
215
+ vIsOpening ? vTopInset : 0
216
+ );
217
+ keyboardInset.set({
218
+ bottom: newInset,
219
+ // Add top padding only while opening to keep end-aligned items visible.
220
+ top: topInset
221
+ });
147
222
  }
148
223
  }
149
224
  },
@@ -153,12 +228,17 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
153
228
  const vMode = mode.get();
154
229
  mode.set("idle");
155
230
  if (vMode === "running") {
231
+ const progress = clampProgress(event.progress);
232
+ const vKeyboardHeight = keyboardHeight.get();
233
+ const vAlignItemsPadding = alignItemsAtEndPadding.get();
234
+ const vTopInset = calculateEndPaddingInset(vKeyboardHeight, vAlignItemsPadding);
235
+ const vIsOpening = isOpening.get();
156
236
  if (!wasInteractive) {
157
- const vIsOpening = isOpening.get();
158
- const vKeyboardHeight = keyboardHeight.get();
159
- const targetOffset = Math.max(
160
- 0,
161
- scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * (vIsOpening ? event.progress : 1 - event.progress)
237
+ const targetOffset = calculateKeyboardTargetOffset(
238
+ scrollOffsetAtKeyboardStart.get(),
239
+ vKeyboardHeight,
240
+ vIsOpening,
241
+ progress
162
242
  );
163
243
  scrollOffsetY.set(targetOffset);
164
244
  animatedOffsetY.set(targetOffset);
@@ -168,7 +248,16 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
168
248
  isKeyboardOpen.set(event.height > 0);
169
249
  if (!horizontal) {
170
250
  const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
171
- keyboardInset.set({ bottom: newInset, top: 0 });
251
+ const topInset = calculateTopInset(
252
+ safeAreaInsetTop,
253
+ IsNewArchitecture,
254
+ event.height > 0 ? vTopInset : 0
255
+ );
256
+ keyboardInset.set({
257
+ bottom: newInset,
258
+ // Preserve end-aligned padding only while the keyboard is visible.
259
+ top: topInset
260
+ });
172
261
  if (newInset <= 0) {
173
262
  animatedOffsetY.set(scrollOffsetY.get());
174
263
  }
@@ -214,6 +303,7 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
214
303
  ...rest,
215
304
  animatedProps,
216
305
  keyboardDismissMode: "interactive",
306
+ onMetricsChange: handleMetricsChange,
217
307
  onScroll: scrollHandler,
218
308
  ref: combinedRef,
219
309
  refScrollView: scrollViewRef,
package/keyboard.mjs CHANGED
@@ -2,11 +2,14 @@ import * as React from 'react';
2
2
  import { forwardRef, useRef, useCallback } from 'react';
3
3
  import { StyleSheet, Platform } from 'react-native';
4
4
  import { useKeyboardHandler } from 'react-native-keyboard-controller';
5
- import { useAnimatedRef, useSharedValue, useAnimatedScrollHandler, runOnJS, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
5
+ import { useAnimatedRef, useSharedValue, useAnimatedScrollHandler, runOnJS, runOnUI, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
6
6
  import { AnimatedLegendList } from '@legendapp/list/reanimated';
7
7
 
8
8
  // src/integrations/keyboard.tsx
9
9
 
10
+ // src/constants-platform.ts
11
+ var IsNewArchitecture = true;
12
+
10
13
  // src/utils/helpers.ts
11
14
  function isFunction(obj) {
12
15
  return typeof obj === "function";
@@ -30,14 +33,33 @@ var useCombinedRef = (...refs) => {
30
33
  };
31
34
 
32
35
  // src/integrations/keyboard.tsx
36
+ var clampProgress = (progress) => {
37
+ "worklet";
38
+ return Math.min(1, Math.max(0, progress));
39
+ };
33
40
  var calculateKeyboardInset = (height, safeAreaInsetBottom, isNewArchitecture) => {
34
41
  "worklet";
35
42
  return Math.max(0, height - safeAreaInsetBottom) ;
36
43
  };
44
+ var calculateEndPaddingInset = (keyboardHeight, alignItemsAtEndPadding) => {
45
+ "worklet";
46
+ return Math.min(keyboardHeight, alignItemsAtEndPadding);
47
+ };
48
+ var calculateTopInset = (safeAreaInsetTop, isNewArchitecture, extraTopInset) => {
49
+ "worklet";
50
+ return (isNewArchitecture ? 0 : safeAreaInsetTop * 2) + extraTopInset;
51
+ };
52
+ var calculateKeyboardTargetOffset = (startOffset, keyboardHeight, isOpening, progress) => {
53
+ "worklet";
54
+ const normalizedProgress = isOpening ? progress : 1 - progress;
55
+ const delta = (isOpening ? keyboardHeight : -keyboardHeight) * normalizedProgress;
56
+ return Math.max(0, startOffset + delta);
57
+ };
37
58
  var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2(props, forwardedRef) {
38
59
  const {
39
60
  contentInset: contentInsetProp,
40
61
  horizontal,
62
+ onMetricsChange: onMetricsChangeProp,
41
63
  onScroll: onScrollProp,
42
64
  safeAreaInsets = { bottom: 0, top: 0 },
43
65
  style: styleProp,
@@ -55,6 +77,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
55
77
  const mode = useSharedValue("idle");
56
78
  const keyboardInset = useSharedValue({ bottom: 0, top: 0 });
57
79
  const keyboardHeight = useSharedValue(0);
80
+ const alignItemsAtEndPadding = useSharedValue(0);
58
81
  const isOpening = useSharedValue(false);
59
82
  const didInteractive = useSharedValue(false);
60
83
  const { top: safeAreaInsetTop, bottom: safeAreaInsetBottom } = safeAreaInsets;
@@ -75,20 +98,52 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
75
98
  },
76
99
  [refLegendList]
77
100
  );
101
+ const handleMetricsChange = useCallback(
102
+ (metrics) => {
103
+ const nextPadding = metrics.alignItemsAtEndPadding || 0;
104
+ alignItemsAtEndPadding.set(nextPadding);
105
+ if (!horizontal) {
106
+ runOnUI((padding, safeInsetTop, isNewArchitecture) => {
107
+ "worklet";
108
+ if (!isKeyboardOpen.get()) {
109
+ return;
110
+ }
111
+ const vKeyboardHeight = keyboardHeight.get();
112
+ const vTopInset = calculateEndPaddingInset(vKeyboardHeight, padding);
113
+ const topInset = calculateTopInset(safeInsetTop, isNewArchitecture, vTopInset);
114
+ keyboardInset.set({
115
+ bottom: keyboardInset.get().bottom,
116
+ top: topInset
117
+ });
118
+ })(nextPadding, safeAreaInsetTop, IsNewArchitecture);
119
+ }
120
+ onMetricsChangeProp == null ? void 0 : onMetricsChangeProp(metrics);
121
+ },
122
+ [
123
+ alignItemsAtEndPadding,
124
+ horizontal,
125
+ isKeyboardOpen,
126
+ keyboardHeight,
127
+ keyboardInset,
128
+ onMetricsChangeProp,
129
+ safeAreaInsetTop
130
+ ]
131
+ );
78
132
  useKeyboardHandler(
79
133
  // biome-ignore assist/source/useSortedKeys: prefer start/move/end
80
134
  {
81
135
  onStart: (event) => {
82
136
  "worklet";
83
137
  mode.set("running");
84
- if (isKeyboardOpen.get() && event.progress === 1 && event.height > 0) {
138
+ const progress = clampProgress(event.progress);
139
+ if (isKeyboardOpen.get() && progress >= 1 && event.height > 0) {
85
140
  return;
86
141
  }
87
142
  if (!didInteractive.get()) {
88
143
  if (event.height > 0) {
89
144
  keyboardHeight.set(event.height - safeAreaInsetBottom);
90
145
  }
91
- isOpening.set(event.progress > 0);
146
+ isOpening.set(progress > 0);
92
147
  scrollOffsetAtKeyboardStart.set(scrollOffsetY.get());
93
148
  animatedOffsetY.set(scrollOffsetY.get());
94
149
  runOnJS(setScrollProcessingEnabled)(false);
@@ -101,6 +156,13 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
101
156
  }
102
157
  mode.set("running");
103
158
  if (!didInteractive.get()) {
159
+ if (!isAndroid && !IsNewArchitecture) {
160
+ keyboardInset.set({
161
+ bottom: keyboardInset.get().bottom,
162
+ // Legacy iOS uses a doubled top inset to keep content below the status bar.
163
+ top: calculateTopInset(safeAreaInsetTop, IsNewArchitecture, 0)
164
+ });
165
+ }
104
166
  didInteractive.set(true);
105
167
  }
106
168
  if (isAndroid && !horizontal) {
@@ -111,18 +173,31 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
111
173
  onMove: (event) => {
112
174
  "worklet";
113
175
  if (!didInteractive.get()) {
176
+ const progress = clampProgress(event.progress);
114
177
  const vIsOpening = isOpening.get();
115
178
  const vKeyboardHeight = keyboardHeight.get();
116
- const vProgress = vIsOpening ? event.progress : 1 - event.progress;
117
- const targetOffset = Math.max(
118
- 0,
119
- scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * vProgress
179
+ const vAlignItemsPadding = alignItemsAtEndPadding.get();
180
+ const vTopInset = calculateEndPaddingInset(vKeyboardHeight, vAlignItemsPadding);
181
+ const targetOffset = calculateKeyboardTargetOffset(
182
+ scrollOffsetAtKeyboardStart.get(),
183
+ vKeyboardHeight,
184
+ vIsOpening,
185
+ progress
120
186
  );
121
187
  scrollOffsetY.set(targetOffset);
122
188
  animatedOffsetY.set(targetOffset);
123
189
  if (!horizontal) {
124
190
  const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
125
- keyboardInset.set({ bottom: newInset, top: 0 });
191
+ const topInset = calculateTopInset(
192
+ safeAreaInsetTop,
193
+ IsNewArchitecture,
194
+ vIsOpening ? vTopInset : 0
195
+ );
196
+ keyboardInset.set({
197
+ bottom: newInset,
198
+ // Add top padding only while opening to keep end-aligned items visible.
199
+ top: topInset
200
+ });
126
201
  }
127
202
  }
128
203
  },
@@ -132,12 +207,17 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
132
207
  const vMode = mode.get();
133
208
  mode.set("idle");
134
209
  if (vMode === "running") {
210
+ const progress = clampProgress(event.progress);
211
+ const vKeyboardHeight = keyboardHeight.get();
212
+ const vAlignItemsPadding = alignItemsAtEndPadding.get();
213
+ const vTopInset = calculateEndPaddingInset(vKeyboardHeight, vAlignItemsPadding);
214
+ const vIsOpening = isOpening.get();
135
215
  if (!wasInteractive) {
136
- const vIsOpening = isOpening.get();
137
- const vKeyboardHeight = keyboardHeight.get();
138
- const targetOffset = Math.max(
139
- 0,
140
- scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * (vIsOpening ? event.progress : 1 - event.progress)
216
+ const targetOffset = calculateKeyboardTargetOffset(
217
+ scrollOffsetAtKeyboardStart.get(),
218
+ vKeyboardHeight,
219
+ vIsOpening,
220
+ progress
141
221
  );
142
222
  scrollOffsetY.set(targetOffset);
143
223
  animatedOffsetY.set(targetOffset);
@@ -147,7 +227,16 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
147
227
  isKeyboardOpen.set(event.height > 0);
148
228
  if (!horizontal) {
149
229
  const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
150
- keyboardInset.set({ bottom: newInset, top: 0 });
230
+ const topInset = calculateTopInset(
231
+ safeAreaInsetTop,
232
+ IsNewArchitecture,
233
+ event.height > 0 ? vTopInset : 0
234
+ );
235
+ keyboardInset.set({
236
+ bottom: newInset,
237
+ // Preserve end-aligned padding only while the keyboard is visible.
238
+ top: topInset
239
+ });
151
240
  if (newInset <= 0) {
152
241
  animatedOffsetY.set(scrollOffsetY.get());
153
242
  }
@@ -193,6 +282,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
193
282
  ...rest,
194
283
  animatedProps,
195
284
  keyboardDismissMode: "interactive",
285
+ onMetricsChange: handleMetricsChange,
196
286
  onScroll: scrollHandler,
197
287
  ref: combinedRef,
198
288
  refScrollView: scrollViewRef,
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import { Insets } from 'react-native';
3
+ import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/hook/commonTypes';
4
+ import { LegendListRef } from '@legendapp/list';
5
+ import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
6
+
7
+ declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "onScroll" | "contentInset"> & {
8
+ onScroll?: (event: ReanimatedScrollEvent) => void;
9
+ contentInset?: Insets | undefined;
10
+ safeAreaInsets?: {
11
+ top: number;
12
+ bottom: number;
13
+ };
14
+ } & React.RefAttributes<LegendListRef>) => React.ReactNode;
15
+
16
+ export { KeyboardAvoidingLegendList, KeyboardAvoidingLegendList as LegendList };
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import { Insets } from 'react-native';
3
+ import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/hook/commonTypes';
4
+ import { LegendListRef } from '@legendapp/list';
5
+ import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
6
+
7
+ declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "onScroll" | "contentInset"> & {
8
+ onScroll?: (event: ReanimatedScrollEvent) => void;
9
+ contentInset?: Insets | undefined;
10
+ safeAreaInsets?: {
11
+ top: number;
12
+ bottom: number;
13
+ };
14
+ } & React.RefAttributes<LegendListRef>) => React.ReactNode;
15
+
16
+ export { KeyboardAvoidingLegendList, KeyboardAvoidingLegendList as LegendList };