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

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.
@@ -2,15 +2,11 @@ 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, runOnUI, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
5
+ import { useAnimatedRef, useSharedValue, useAnimatedScrollHandler, runOnJS, 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.native.ts
11
- var f = global.nativeFabricUIManager;
12
- var IsNewArchitecture = f !== void 0 && f != null;
13
-
14
10
  // src/utils/helpers.ts
15
11
  function isFunction(obj) {
16
12
  return typeof obj === "function";
@@ -38,17 +34,18 @@ var clampProgress = (progress) => {
38
34
  "worklet";
39
35
  return Math.min(1, Math.max(0, progress));
40
36
  };
41
- var calculateKeyboardInset = (height, safeAreaInsetBottom, isNewArchitecture) => {
42
- "worklet";
43
- return isNewArchitecture ? Math.max(0, height - safeAreaInsetBottom) : Math.max(isNewArchitecture ? 0 : -safeAreaInsetBottom, height - safeAreaInsetBottom * 2);
44
- };
45
- var calculateEndPaddingInset = (keyboardHeight, alignItemsAtEndPadding) => {
37
+ var calculateKeyboardInset = (height, safeAreaInsetBottom) => {
46
38
  "worklet";
47
- return Math.min(keyboardHeight, alignItemsAtEndPadding);
39
+ return Math.max(0, height - safeAreaInsetBottom);
48
40
  };
49
- var calculateTopInset = (safeAreaInsetTop, isNewArchitecture, extraTopInset) => {
41
+ var calculateEffectiveKeyboardHeight = (keyboardHeight, contentLength, scrollLength, alignItemsAtEnd) => {
50
42
  "worklet";
51
- return (isNewArchitecture ? 0 : safeAreaInsetTop * 2) + extraTopInset;
43
+ if (alignItemsAtEnd) {
44
+ return keyboardHeight;
45
+ } else {
46
+ const availableSpace = Math.max(0, scrollLength - contentLength);
47
+ return Math.max(0, keyboardHeight - availableSpace);
48
+ }
52
49
  };
53
50
  var calculateKeyboardTargetOffset = (startOffset, keyboardHeight, isOpening, progress) => {
54
51
  "worklet";
@@ -62,10 +59,11 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
62
59
  horizontal,
63
60
  onMetricsChange: onMetricsChangeProp,
64
61
  onScroll: onScrollProp,
65
- safeAreaInsets = { bottom: 0, top: 0 },
62
+ safeAreaInsetBottom = 0,
66
63
  style: styleProp,
67
64
  ...rest
68
65
  } = props;
66
+ const { alignItemsAtEnd } = props;
69
67
  const styleFlattened = StyleSheet.flatten(styleProp);
70
68
  const refLegendList = useRef(null);
71
69
  const combinedRef = useCombinedRef(forwardedRef, refLegendList);
@@ -76,16 +74,19 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
76
74
  const animatedOffsetY = useSharedValue(null);
77
75
  const scrollOffsetAtKeyboardStart = useSharedValue(0);
78
76
  const mode = useSharedValue("idle");
79
- const keyboardInset = useSharedValue({ bottom: 0, top: 0 });
77
+ const keyboardInset = useSharedValue(0);
80
78
  const keyboardHeight = useSharedValue(0);
79
+ const contentLength = useSharedValue(0);
80
+ const scrollLength = useSharedValue(0);
81
81
  const alignItemsAtEndPadding = useSharedValue(0);
82
82
  const isOpening = useSharedValue(false);
83
83
  const didInteractive = useSharedValue(false);
84
- const { top: safeAreaInsetTop, bottom: safeAreaInsetBottom } = safeAreaInsets;
85
84
  const isKeyboardOpen = useSharedValue(false);
86
85
  const scrollHandler = useAnimatedScrollHandler(
87
86
  (event) => {
88
- scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
87
+ if (mode.get() !== "running" || didInteractive.get()) {
88
+ scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
89
+ }
89
90
  if (onScrollProp) {
90
91
  runOnJS(onScrollProp)(event);
91
92
  }
@@ -99,36 +100,23 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
99
100
  },
100
101
  [refLegendList]
101
102
  );
103
+ const updateScrollMetrics = useCallback(() => {
104
+ var _a;
105
+ const state = (_a = refLegendList.current) == null ? void 0 : _a.getState();
106
+ if (!state) {
107
+ return;
108
+ }
109
+ contentLength.set(state.contentLength);
110
+ scrollLength.set(state.scrollLength);
111
+ }, [contentLength, scrollLength]);
102
112
  const handleMetricsChange = useCallback(
103
113
  (metrics) => {
114
+ updateScrollMetrics();
104
115
  const nextPadding = metrics.alignItemsAtEndPadding || 0;
105
116
  alignItemsAtEndPadding.set(nextPadding);
106
- if (!horizontal) {
107
- runOnUI((padding, safeInsetTop, isNewArchitecture) => {
108
- "worklet";
109
- if (!isKeyboardOpen.get()) {
110
- return;
111
- }
112
- const vKeyboardHeight = keyboardHeight.get();
113
- const vTopInset = calculateEndPaddingInset(vKeyboardHeight, padding);
114
- const topInset = calculateTopInset(safeInsetTop, isNewArchitecture, vTopInset);
115
- keyboardInset.set({
116
- bottom: keyboardInset.get().bottom,
117
- top: topInset
118
- });
119
- })(nextPadding, safeAreaInsetTop, IsNewArchitecture);
120
- }
121
117
  onMetricsChangeProp == null ? void 0 : onMetricsChangeProp(metrics);
122
118
  },
123
- [
124
- alignItemsAtEndPadding,
125
- horizontal,
126
- isKeyboardOpen,
127
- keyboardHeight,
128
- keyboardInset,
129
- onMetricsChangeProp,
130
- safeAreaInsetTop
131
- ]
119
+ [alignItemsAtEndPadding, onMetricsChangeProp, updateScrollMetrics]
132
120
  );
133
121
  useKeyboardHandler(
134
122
  // biome-ignore assist/source/useSortedKeys: prefer start/move/end
@@ -157,18 +145,11 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
157
145
  }
158
146
  mode.set("running");
159
147
  if (!didInteractive.get()) {
160
- if (!isAndroid && !IsNewArchitecture) {
161
- keyboardInset.set({
162
- bottom: keyboardInset.get().bottom,
163
- // Legacy iOS uses a doubled top inset to keep content below the status bar.
164
- top: calculateTopInset(safeAreaInsetTop, IsNewArchitecture, 0)
165
- });
166
- }
167
148
  didInteractive.set(true);
168
149
  }
169
150
  if (isAndroid && !horizontal) {
170
- const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom, IsNewArchitecture);
171
- keyboardInset.set({ bottom: newInset, top: safeAreaInsetTop * 2 });
151
+ const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
152
+ keyboardInset.set(newInset);
172
153
  }
173
154
  },
174
155
  onMove: (event) => {
@@ -177,28 +158,23 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
177
158
  const progress = clampProgress(event.progress);
178
159
  const vIsOpening = isOpening.get();
179
160
  const vKeyboardHeight = keyboardHeight.get();
180
- const vAlignItemsPadding = alignItemsAtEndPadding.get();
181
- const vTopInset = calculateEndPaddingInset(vKeyboardHeight, vAlignItemsPadding);
161
+ const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
162
+ vKeyboardHeight,
163
+ contentLength.get(),
164
+ scrollLength.get(),
165
+ alignItemsAtEnd
166
+ );
182
167
  const targetOffset = calculateKeyboardTargetOffset(
183
168
  scrollOffsetAtKeyboardStart.get(),
184
- vKeyboardHeight,
169
+ vEffectiveKeyboardHeight,
185
170
  vIsOpening,
186
171
  progress
187
172
  );
188
173
  scrollOffsetY.set(targetOffset);
189
174
  animatedOffsetY.set(targetOffset);
190
175
  if (!horizontal) {
191
- const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom, IsNewArchitecture);
192
- const topInset = calculateTopInset(
193
- safeAreaInsetTop,
194
- IsNewArchitecture,
195
- vIsOpening ? vTopInset : 0
196
- );
197
- keyboardInset.set({
198
- bottom: newInset,
199
- // Add top padding only while opening to keep end-aligned items visible.
200
- top: topInset
201
- });
176
+ const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
177
+ keyboardInset.set(newInset);
202
178
  }
203
179
  }
204
180
  },
@@ -210,13 +186,17 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
210
186
  if (vMode === "running") {
211
187
  const progress = clampProgress(event.progress);
212
188
  const vKeyboardHeight = keyboardHeight.get();
213
- const vAlignItemsPadding = alignItemsAtEndPadding.get();
214
- const vTopInset = calculateEndPaddingInset(vKeyboardHeight, vAlignItemsPadding);
189
+ const vEffectiveKeyboardHeight = calculateEffectiveKeyboardHeight(
190
+ vKeyboardHeight,
191
+ contentLength.get(),
192
+ scrollLength.get(),
193
+ alignItemsAtEnd
194
+ );
215
195
  const vIsOpening = isOpening.get();
216
196
  if (!wasInteractive) {
217
197
  const targetOffset = calculateKeyboardTargetOffset(
218
198
  scrollOffsetAtKeyboardStart.get(),
219
- vKeyboardHeight,
199
+ vEffectiveKeyboardHeight,
220
200
  vIsOpening,
221
201
  progress
222
202
  );
@@ -227,17 +207,8 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
227
207
  didInteractive.set(false);
228
208
  isKeyboardOpen.set(event.height > 0);
229
209
  if (!horizontal) {
230
- const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom, IsNewArchitecture);
231
- const topInset = calculateTopInset(
232
- safeAreaInsetTop,
233
- IsNewArchitecture,
234
- event.height > 0 ? vTopInset : 0
235
- );
236
- keyboardInset.set({
237
- bottom: newInset,
238
- // Preserve end-aligned padding only while the keyboard is visible.
239
- top: topInset
240
- });
210
+ const newInset = calculateKeyboardInset(event.height, safeAreaInsetBottom);
211
+ keyboardInset.set(newInset);
241
212
  if (newInset <= 0) {
242
213
  animatedOffsetY.set(scrollOffsetY.get());
243
214
  }
@@ -245,7 +216,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
245
216
  }
246
217
  }
247
218
  },
248
- [scrollViewRef, safeAreaInsetBottom]
219
+ [alignItemsAtEnd, safeAreaInsetBottom, scrollViewRef]
249
220
  );
250
221
  const animatedProps = useAnimatedProps(() => {
251
222
  "worklet";
@@ -257,24 +228,21 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
257
228
  y: vAnimatedOffsetY
258
229
  }
259
230
  };
260
- const { top: keyboardInsetTop, bottom: keyboardInsetBottom } = keyboardInset.get();
231
+ const keyboardInsetBottom = keyboardInset.get();
261
232
  return isIos ? Object.assign(baseProps, {
262
233
  contentInset: {
263
234
  bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInsetBottom),
264
235
  left: (_b = contentInsetProp == null ? void 0 : contentInsetProp.left) != null ? _b : 0,
265
236
  right: (_c = contentInsetProp == null ? void 0 : contentInsetProp.right) != null ? _c : 0,
266
- top: ((_d = contentInsetProp == null ? void 0 : contentInsetProp.top) != null ? _d : 0) - keyboardInsetTop
237
+ top: (_d = contentInsetProp == null ? void 0 : contentInsetProp.top) != null ? _d : 0
267
238
  }
268
239
  }) : baseProps;
269
240
  });
270
241
  const style = isAndroid ? useAnimatedStyle(
271
- () => {
272
- var _a;
273
- return {
274
- ...styleFlattened || {},
275
- marginBottom: (_a = keyboardInset.get().bottom) != null ? _a : 0
276
- };
277
- },
242
+ () => ({
243
+ ...styleFlattened || {},
244
+ marginBottom: keyboardInset.get()
245
+ }),
278
246
  [styleProp, keyboardInset]
279
247
  ) : void 0;
280
248
  return /* @__PURE__ */ React.createElement(
@@ -282,6 +250,7 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
282
250
  {
283
251
  ...rest,
284
252
  animatedProps,
253
+ automaticallyAdjustContentInsets: false,
285
254
  keyboardDismissMode: "interactive",
286
255
  onMetricsChange: handleMetricsChange,
287
256
  onScroll: scrollHandler,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "3.0.0-beta.21",
3
+ "version": "3.0.0-beta.23",
4
4
  "description": "Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,