@legendapp/list 2.0.17 → 2.0.19

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 2.0.19
2
+ - Fix: Add safety checks for getItemType, getEstimatedItemSize, getFixedItemSize, and keyExtractor to prevent calling when index is out of range
3
+ - Fix: Error with animatedProps in reanimated integration
4
+
5
+ ## 2.0.18
6
+ - Improvement: KeyboardAvoidingLegendList now supports KeyboardGestureArea with improved interactive behavior
7
+
1
8
  ## 2.0.17
2
9
  - Feat: Add stickyHeaderOffset property to control sticky header positioning
3
10
  - Feat: Add sticky header backdrop component support
package/index.js CHANGED
@@ -2091,7 +2091,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2091
2091
  if (needNewContainers.length > 0) {
2092
2092
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
2093
2093
  const itemType = getItemType(data[i], i);
2094
- return itemType ? String(itemType) : "";
2094
+ return itemType !== void 0 ? String(itemType) : "";
2095
2095
  }) : void 0;
2096
2096
  const availableContainers = findAvailableContainers(
2097
2097
  ctx,
@@ -2355,8 +2355,10 @@ function doInitialAllocateContainers(ctx, state) {
2355
2355
  const num = Math.min(20, data.length);
2356
2356
  for (let i = 0; i < num; i++) {
2357
2357
  const item = data[i];
2358
- const itemType = getItemType ? (_a = getItemType(item, i)) != null ? _a : "" : "";
2359
- totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2358
+ if (item !== void 0) {
2359
+ const itemType = (_a = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a : "";
2360
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2361
+ }
2360
2362
  }
2361
2363
  averageItemSize = totalSize / num;
2362
2364
  } else {
@@ -2441,7 +2443,6 @@ function onScroll(ctx, state, event) {
2441
2443
  }
2442
2444
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2443
2445
  state.scrollPending = newScroll;
2444
- console.log("newScroll", newScroll);
2445
2446
  const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
2446
2447
  if (state.initialScroll && newScroll > maxOffset) {
2447
2448
  newScroll = maxOffset;
@@ -2645,6 +2646,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2645
2646
  }
2646
2647
  return 0;
2647
2648
  }
2649
+ function useWrapIfItem(fn) {
2650
+ return React2.useMemo(
2651
+ () => fn ? (arg1, arg2, arg3) => arg1 !== void 0 && arg2 !== void 0 ? fn(arg1, arg2, arg3) : void 0 : void 0,
2652
+ [fn]
2653
+ );
2654
+ }
2648
2655
  var useCombinedRef = (...refs) => {
2649
2656
  const callback = React2.useCallback((element) => {
2650
2657
  for (const ref of refs) {
@@ -2914,14 +2921,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2914
2921
  dataVersion,
2915
2922
  enableAverages,
2916
2923
  estimatedItemSize,
2917
- getEstimatedItemSize,
2918
- getFixedItemSize,
2919
- getItemType,
2924
+ getEstimatedItemSize: useWrapIfItem(getEstimatedItemSize),
2925
+ getFixedItemSize: useWrapIfItem(getFixedItemSize),
2926
+ getItemType: useWrapIfItem(getItemType),
2920
2927
  horizontal: !!horizontal,
2921
2928
  initialContainerPoolRatio,
2922
2929
  initialScroll,
2923
2930
  itemsAreEqual,
2924
- keyExtractor,
2931
+ keyExtractor: useWrapIfItem(keyExtractor),
2925
2932
  maintainScrollAtEnd,
2926
2933
  maintainScrollAtEndThreshold,
2927
2934
  maintainVisibleContentPosition,
package/index.mjs CHANGED
@@ -2070,7 +2070,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2070
2070
  if (needNewContainers.length > 0) {
2071
2071
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
2072
2072
  const itemType = getItemType(data[i], i);
2073
- return itemType ? String(itemType) : "";
2073
+ return itemType !== void 0 ? String(itemType) : "";
2074
2074
  }) : void 0;
2075
2075
  const availableContainers = findAvailableContainers(
2076
2076
  ctx,
@@ -2334,8 +2334,10 @@ function doInitialAllocateContainers(ctx, state) {
2334
2334
  const num = Math.min(20, data.length);
2335
2335
  for (let i = 0; i < num; i++) {
2336
2336
  const item = data[i];
2337
- const itemType = getItemType ? (_a = getItemType(item, i)) != null ? _a : "" : "";
2338
- totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2337
+ if (item !== void 0) {
2338
+ const itemType = (_a = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a : "";
2339
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2340
+ }
2339
2341
  }
2340
2342
  averageItemSize = totalSize / num;
2341
2343
  } else {
@@ -2420,7 +2422,6 @@ function onScroll(ctx, state, event) {
2420
2422
  }
2421
2423
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2422
2424
  state.scrollPending = newScroll;
2423
- console.log("newScroll", newScroll);
2424
2425
  const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
2425
2426
  if (state.initialScroll && newScroll > maxOffset) {
2426
2427
  newScroll = maxOffset;
@@ -2624,6 +2625,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2624
2625
  }
2625
2626
  return 0;
2626
2627
  }
2628
+ function useWrapIfItem(fn) {
2629
+ return useMemo(
2630
+ () => fn ? (arg1, arg2, arg3) => arg1 !== void 0 && arg2 !== void 0 ? fn(arg1, arg2, arg3) : void 0 : void 0,
2631
+ [fn]
2632
+ );
2633
+ }
2627
2634
  var useCombinedRef = (...refs) => {
2628
2635
  const callback = useCallback((element) => {
2629
2636
  for (const ref of refs) {
@@ -2893,14 +2900,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2893
2900
  dataVersion,
2894
2901
  enableAverages,
2895
2902
  estimatedItemSize,
2896
- getEstimatedItemSize,
2897
- getFixedItemSize,
2898
- getItemType,
2903
+ getEstimatedItemSize: useWrapIfItem(getEstimatedItemSize),
2904
+ getFixedItemSize: useWrapIfItem(getFixedItemSize),
2905
+ getItemType: useWrapIfItem(getItemType),
2899
2906
  horizontal: !!horizontal,
2900
2907
  initialContainerPoolRatio,
2901
2908
  initialScroll,
2902
2909
  itemsAreEqual,
2903
- keyExtractor,
2910
+ keyExtractor: useWrapIfItem(keyExtractor),
2904
2911
  maintainScrollAtEnd,
2905
2912
  maintainScrollAtEndThreshold,
2906
2913
  maintainVisibleContentPosition,
package/keyboard.d.mts CHANGED
@@ -4,9 +4,9 @@ import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/ho
4
4
  import { LegendListRef } from '@legendapp/list';
5
5
  import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
6
6
 
7
- declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "contentInset" | "onScroll"> & {
7
+ declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "onScroll" | "contentInset"> & {
8
8
  onScroll?: (event: ReanimatedScrollEvent) => void;
9
- contentInset?: Insets;
9
+ contentInset?: Insets | undefined;
10
10
  safeAreaInsetBottom?: number;
11
11
  } & React.RefAttributes<LegendListRef>) => React.ReactNode;
12
12
 
package/keyboard.d.ts CHANGED
@@ -4,9 +4,9 @@ import { ReanimatedScrollEvent } from 'react-native-reanimated/lib/typescript/ho
4
4
  import { LegendListRef } from '@legendapp/list';
5
5
  import { AnimatedLegendListProps } from '@legendapp/list/reanimated';
6
6
 
7
- declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "contentInset" | "onScroll"> & {
7
+ declare const KeyboardAvoidingLegendList: <ItemT>(props: Omit<AnimatedLegendListProps<ItemT>, "onScroll" | "contentInset"> & {
8
8
  onScroll?: (event: ReanimatedScrollEvent) => void;
9
- contentInset?: Insets;
9
+ contentInset?: Insets | undefined;
10
10
  safeAreaInsetBottom?: number;
11
11
  } & React.RefAttributes<LegendListRef>) => React.ReactNode;
12
12
 
package/keyboard.js CHANGED
@@ -57,20 +57,27 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
57
57
  horizontal,
58
58
  onScroll: onScrollProp,
59
59
  safeAreaInsetBottom = 0,
60
+ style: styleProp,
60
61
  ...rest
61
62
  } = props;
63
+ const styleFlattened = reactNative.StyleSheet.flatten(styleProp);
62
64
  const refLegendList = React.useRef(null);
63
65
  const combinedRef = useCombinedRef(forwardedRef, refLegendList);
66
+ const isIos = reactNative.Platform.OS === "ios";
67
+ const isAndroid = reactNative.Platform.OS === "android";
64
68
  const scrollViewRef = reactNativeReanimated.useAnimatedRef();
65
69
  const scrollOffsetY = reactNativeReanimated.useSharedValue(0);
66
70
  const animatedOffsetY = reactNativeReanimated.useSharedValue(null);
67
71
  const scrollOffsetAtKeyboardStart = reactNativeReanimated.useSharedValue(0);
72
+ const mode = reactNativeReanimated.useSharedValue("idle");
68
73
  const keyboardInset = reactNativeReanimated.useSharedValue(0);
69
74
  const keyboardHeight = reactNativeReanimated.useSharedValue(0);
70
75
  const isOpening = reactNativeReanimated.useSharedValue(false);
76
+ const didInteractive = reactNativeReanimated.useSharedValue(false);
77
+ const isKeyboardOpen = reactNativeReanimated.useSharedValue(false);
71
78
  const scrollHandler = reactNativeReanimated.useAnimatedScrollHandler(
72
79
  (event) => {
73
- scrollOffsetY.value = event.contentOffset[horizontal ? "x" : "y"];
80
+ scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
74
81
  if (onScrollProp) {
75
82
  reactNativeReanimated.runOnJS(onScrollProp)(event);
76
83
  }
@@ -89,37 +96,79 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
89
96
  {
90
97
  onStart: (event) => {
91
98
  "worklet";
92
- if (event.height > 0) {
93
- keyboardHeight.set(event.height - safeAreaInsetBottom);
99
+ mode.set("running");
100
+ if (isKeyboardOpen.get() && event.progress === 1 && event.height > 0) {
101
+ return;
102
+ }
103
+ if (!didInteractive.get()) {
104
+ if (event.height > 0) {
105
+ keyboardHeight.set(event.height - safeAreaInsetBottom);
106
+ }
107
+ isOpening.set(event.progress > 0);
108
+ scrollOffsetAtKeyboardStart.set(scrollOffsetY.get());
109
+ animatedOffsetY.set(scrollOffsetY.get());
110
+ reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(false);
111
+ }
112
+ },
113
+ onInteractive: (event) => {
114
+ "worklet";
115
+ if (mode.get() !== "running") {
116
+ reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(false);
117
+ }
118
+ mode.set("running");
119
+ if (!didInteractive.get()) {
120
+ didInteractive.set(true);
121
+ }
122
+ if (isAndroid && !horizontal) {
123
+ keyboardInset.set(Math.max(0, event.height - safeAreaInsetBottom));
94
124
  }
95
- isOpening.set(event.progress > 0);
96
- scrollOffsetAtKeyboardStart.value = scrollOffsetY.value;
97
- animatedOffsetY.set(scrollOffsetY.value);
98
- reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(false);
99
125
  },
100
126
  onMove: (event) => {
101
127
  "worklet";
102
- const vIsOpening = isOpening.get();
103
- const vKeyboardHeight = keyboardHeight.get();
104
- const vProgress = vIsOpening ? event.progress : 1 - event.progress;
105
- const targetOffset = scrollOffsetAtKeyboardStart.value + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * vProgress;
106
- scrollOffsetY.value = targetOffset;
107
- animatedOffsetY.set(targetOffset);
108
- if (!horizontal) {
109
- keyboardInset.value = Math.max(0, event.height - safeAreaInsetBottom);
128
+ if (!didInteractive.get()) {
129
+ const vIsOpening = isOpening.get();
130
+ const vKeyboardHeight = keyboardHeight.get();
131
+ const vProgress = vIsOpening ? event.progress : 1 - event.progress;
132
+ const targetOffset = Math.max(
133
+ 0,
134
+ scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * vProgress
135
+ );
136
+ scrollOffsetY.set(targetOffset);
137
+ animatedOffsetY.set(targetOffset);
138
+ if (!horizontal) {
139
+ keyboardInset.set(Math.max(0, event.height - safeAreaInsetBottom));
140
+ }
110
141
  }
111
142
  },
112
143
  onEnd: (event) => {
113
144
  "worklet";
114
- const vIsOpening = isOpening.get();
115
- const vKeyboardHeight = keyboardHeight.get();
116
- const targetOffset = scrollOffsetAtKeyboardStart.value + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * (vIsOpening ? event.progress : 1 - event.progress);
117
- scrollOffsetY.value = targetOffset;
118
- animatedOffsetY.set(targetOffset);
119
- if (!horizontal) {
120
- keyboardInset.value = Math.max(0, event.height - safeAreaInsetBottom);
145
+ const wasInteractive = didInteractive.get();
146
+ const vMode = mode.get();
147
+ mode.set("idle");
148
+ if (vMode === "running") {
149
+ if (!wasInteractive) {
150
+ const vIsOpening = isOpening.get();
151
+ const vKeyboardHeight = keyboardHeight.get();
152
+ const targetOffset = Math.max(
153
+ 0,
154
+ scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * (vIsOpening ? event.progress : 1 - event.progress)
155
+ );
156
+ scrollOffsetY.set(targetOffset);
157
+ animatedOffsetY.set(targetOffset);
158
+ }
159
+ reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(true);
160
+ didInteractive.set(false);
161
+ isKeyboardOpen.set(event.height > 0);
162
+ if (!horizontal) {
163
+ const newInset = Math.max(0, event.height - safeAreaInsetBottom);
164
+ if (newInset > 0) {
165
+ keyboardInset.set(newInset);
166
+ } else {
167
+ keyboardInset.set(newInset);
168
+ animatedOffsetY.set(scrollOffsetY.get());
169
+ }
170
+ }
121
171
  }
122
- reactNativeReanimated.runOnJS(setScrollProcessingEnabled)(true);
123
172
  }
124
173
  },
125
174
  [scrollViewRef, safeAreaInsetBottom]
@@ -127,24 +176,32 @@ var KeyboardAvoidingLegendList = React.forwardRef(function KeyboardAvoidingLegen
127
176
  const animatedProps = reactNativeReanimated.useAnimatedProps(() => {
128
177
  "worklet";
129
178
  var _a, _b, _c, _d;
179
+ const vAnimatedOffsetY = animatedOffsetY.get();
130
180
  const baseProps = {
131
- contentOffset: animatedOffsetY.value === null ? void 0 : {
181
+ contentOffset: vAnimatedOffsetY === null ? void 0 : {
132
182
  x: 0,
133
- y: animatedOffsetY.value
183
+ y: vAnimatedOffsetY
134
184
  }
135
185
  };
136
- return reactNative.Platform.OS === "ios" ? Object.assign(baseProps, {
186
+ return isIos ? Object.assign(baseProps, {
137
187
  contentInset: {
138
- bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInset.value),
188
+ bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInset.get()),
139
189
  left: (_b = contentInsetProp == null ? void 0 : contentInsetProp.left) != null ? _b : 0,
140
190
  right: (_c = contentInsetProp == null ? void 0 : contentInsetProp.right) != null ? _c : 0,
141
191
  top: (_d = contentInsetProp == null ? void 0 : contentInsetProp.top) != null ? _d : 0
142
192
  }
143
193
  }) : baseProps;
144
194
  });
145
- const style = reactNative.Platform.OS !== "ios" ? reactNativeReanimated.useAnimatedStyle(() => ({
146
- marginBottom: keyboardInset.value
147
- })) : void 0;
195
+ const style = isAndroid ? reactNativeReanimated.useAnimatedStyle(
196
+ () => {
197
+ var _a;
198
+ return {
199
+ ...styleFlattened || {},
200
+ marginBottom: (_a = keyboardInset.get()) != null ? _a : 0
201
+ };
202
+ },
203
+ [styleProp, keyboardInset]
204
+ ) : void 0;
148
205
  return /* @__PURE__ */ React__namespace.createElement(
149
206
  reanimated.AnimatedLegendList,
150
207
  {
package/keyboard.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { forwardRef, useRef, useCallback } from 'react';
3
- import { Platform } from 'react-native';
3
+ import { StyleSheet, Platform } from 'react-native';
4
4
  import { useKeyboardHandler } from 'react-native-keyboard-controller';
5
5
  import { useAnimatedRef, useSharedValue, useAnimatedScrollHandler, runOnJS, useAnimatedProps, useAnimatedStyle } from 'react-native-reanimated';
6
6
  import { AnimatedLegendList } from '@legendapp/list/reanimated';
@@ -36,20 +36,27 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
36
36
  horizontal,
37
37
  onScroll: onScrollProp,
38
38
  safeAreaInsetBottom = 0,
39
+ style: styleProp,
39
40
  ...rest
40
41
  } = props;
42
+ const styleFlattened = StyleSheet.flatten(styleProp);
41
43
  const refLegendList = useRef(null);
42
44
  const combinedRef = useCombinedRef(forwardedRef, refLegendList);
45
+ const isIos = Platform.OS === "ios";
46
+ const isAndroid = Platform.OS === "android";
43
47
  const scrollViewRef = useAnimatedRef();
44
48
  const scrollOffsetY = useSharedValue(0);
45
49
  const animatedOffsetY = useSharedValue(null);
46
50
  const scrollOffsetAtKeyboardStart = useSharedValue(0);
51
+ const mode = useSharedValue("idle");
47
52
  const keyboardInset = useSharedValue(0);
48
53
  const keyboardHeight = useSharedValue(0);
49
54
  const isOpening = useSharedValue(false);
55
+ const didInteractive = useSharedValue(false);
56
+ const isKeyboardOpen = useSharedValue(false);
50
57
  const scrollHandler = useAnimatedScrollHandler(
51
58
  (event) => {
52
- scrollOffsetY.value = event.contentOffset[horizontal ? "x" : "y"];
59
+ scrollOffsetY.set(event.contentOffset[horizontal ? "x" : "y"]);
53
60
  if (onScrollProp) {
54
61
  runOnJS(onScrollProp)(event);
55
62
  }
@@ -68,37 +75,79 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
68
75
  {
69
76
  onStart: (event) => {
70
77
  "worklet";
71
- if (event.height > 0) {
72
- keyboardHeight.set(event.height - safeAreaInsetBottom);
78
+ mode.set("running");
79
+ if (isKeyboardOpen.get() && event.progress === 1 && event.height > 0) {
80
+ return;
81
+ }
82
+ if (!didInteractive.get()) {
83
+ if (event.height > 0) {
84
+ keyboardHeight.set(event.height - safeAreaInsetBottom);
85
+ }
86
+ isOpening.set(event.progress > 0);
87
+ scrollOffsetAtKeyboardStart.set(scrollOffsetY.get());
88
+ animatedOffsetY.set(scrollOffsetY.get());
89
+ runOnJS(setScrollProcessingEnabled)(false);
90
+ }
91
+ },
92
+ onInteractive: (event) => {
93
+ "worklet";
94
+ if (mode.get() !== "running") {
95
+ runOnJS(setScrollProcessingEnabled)(false);
96
+ }
97
+ mode.set("running");
98
+ if (!didInteractive.get()) {
99
+ didInteractive.set(true);
100
+ }
101
+ if (isAndroid && !horizontal) {
102
+ keyboardInset.set(Math.max(0, event.height - safeAreaInsetBottom));
73
103
  }
74
- isOpening.set(event.progress > 0);
75
- scrollOffsetAtKeyboardStart.value = scrollOffsetY.value;
76
- animatedOffsetY.set(scrollOffsetY.value);
77
- runOnJS(setScrollProcessingEnabled)(false);
78
104
  },
79
105
  onMove: (event) => {
80
106
  "worklet";
81
- const vIsOpening = isOpening.get();
82
- const vKeyboardHeight = keyboardHeight.get();
83
- const vProgress = vIsOpening ? event.progress : 1 - event.progress;
84
- const targetOffset = scrollOffsetAtKeyboardStart.value + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * vProgress;
85
- scrollOffsetY.value = targetOffset;
86
- animatedOffsetY.set(targetOffset);
87
- if (!horizontal) {
88
- keyboardInset.value = Math.max(0, event.height - safeAreaInsetBottom);
107
+ if (!didInteractive.get()) {
108
+ const vIsOpening = isOpening.get();
109
+ const vKeyboardHeight = keyboardHeight.get();
110
+ const vProgress = vIsOpening ? event.progress : 1 - event.progress;
111
+ const targetOffset = Math.max(
112
+ 0,
113
+ scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * vProgress
114
+ );
115
+ scrollOffsetY.set(targetOffset);
116
+ animatedOffsetY.set(targetOffset);
117
+ if (!horizontal) {
118
+ keyboardInset.set(Math.max(0, event.height - safeAreaInsetBottom));
119
+ }
89
120
  }
90
121
  },
91
122
  onEnd: (event) => {
92
123
  "worklet";
93
- const vIsOpening = isOpening.get();
94
- const vKeyboardHeight = keyboardHeight.get();
95
- const targetOffset = scrollOffsetAtKeyboardStart.value + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * (vIsOpening ? event.progress : 1 - event.progress);
96
- scrollOffsetY.value = targetOffset;
97
- animatedOffsetY.set(targetOffset);
98
- if (!horizontal) {
99
- keyboardInset.value = Math.max(0, event.height - safeAreaInsetBottom);
124
+ const wasInteractive = didInteractive.get();
125
+ const vMode = mode.get();
126
+ mode.set("idle");
127
+ if (vMode === "running") {
128
+ if (!wasInteractive) {
129
+ const vIsOpening = isOpening.get();
130
+ const vKeyboardHeight = keyboardHeight.get();
131
+ const targetOffset = Math.max(
132
+ 0,
133
+ scrollOffsetAtKeyboardStart.get() + (vIsOpening ? vKeyboardHeight : -vKeyboardHeight) * (vIsOpening ? event.progress : 1 - event.progress)
134
+ );
135
+ scrollOffsetY.set(targetOffset);
136
+ animatedOffsetY.set(targetOffset);
137
+ }
138
+ runOnJS(setScrollProcessingEnabled)(true);
139
+ didInteractive.set(false);
140
+ isKeyboardOpen.set(event.height > 0);
141
+ if (!horizontal) {
142
+ const newInset = Math.max(0, event.height - safeAreaInsetBottom);
143
+ if (newInset > 0) {
144
+ keyboardInset.set(newInset);
145
+ } else {
146
+ keyboardInset.set(newInset);
147
+ animatedOffsetY.set(scrollOffsetY.get());
148
+ }
149
+ }
100
150
  }
101
- runOnJS(setScrollProcessingEnabled)(true);
102
151
  }
103
152
  },
104
153
  [scrollViewRef, safeAreaInsetBottom]
@@ -106,24 +155,32 @@ var KeyboardAvoidingLegendList = forwardRef(function KeyboardAvoidingLegendList2
106
155
  const animatedProps = useAnimatedProps(() => {
107
156
  "worklet";
108
157
  var _a, _b, _c, _d;
158
+ const vAnimatedOffsetY = animatedOffsetY.get();
109
159
  const baseProps = {
110
- contentOffset: animatedOffsetY.value === null ? void 0 : {
160
+ contentOffset: vAnimatedOffsetY === null ? void 0 : {
111
161
  x: 0,
112
- y: animatedOffsetY.value
162
+ y: vAnimatedOffsetY
113
163
  }
114
164
  };
115
- return Platform.OS === "ios" ? Object.assign(baseProps, {
165
+ return isIos ? Object.assign(baseProps, {
116
166
  contentInset: {
117
- bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInset.value),
167
+ bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInset.get()),
118
168
  left: (_b = contentInsetProp == null ? void 0 : contentInsetProp.left) != null ? _b : 0,
119
169
  right: (_c = contentInsetProp == null ? void 0 : contentInsetProp.right) != null ? _c : 0,
120
170
  top: (_d = contentInsetProp == null ? void 0 : contentInsetProp.top) != null ? _d : 0
121
171
  }
122
172
  }) : baseProps;
123
173
  });
124
- const style = Platform.OS !== "ios" ? useAnimatedStyle(() => ({
125
- marginBottom: keyboardInset.value
126
- })) : void 0;
174
+ const style = isAndroid ? useAnimatedStyle(
175
+ () => {
176
+ var _a;
177
+ return {
178
+ ...styleFlattened || {},
179
+ marginBottom: (_a = keyboardInset.get()) != null ? _a : 0
180
+ };
181
+ },
182
+ [styleProp, keyboardInset]
183
+ ) : void 0;
127
184
  return /* @__PURE__ */ React.createElement(
128
185
  AnimatedLegendList,
129
186
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "2.0.17",
3
+ "version": "2.0.19",
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,
package/reanimated.js CHANGED
@@ -69,9 +69,18 @@ var AnimatedLegendListComponent = Reanimated__default.default.createAnimatedComp
69
69
  var AnimatedLegendList = typedMemo(
70
70
  React__namespace.forwardRef(function AnimatedLegendList2(props, ref) {
71
71
  const { refScrollView, ...rest } = props;
72
+ const { animatedProps } = props;
72
73
  const refLegendList = React__namespace.useRef(null);
73
74
  const combinedRef = useCombinedRef(refLegendList, ref);
74
- return /* @__PURE__ */ React__namespace.createElement(AnimatedLegendListComponent, { ref: refScrollView, refLegendList: combinedRef, ...rest });
75
+ return /* @__PURE__ */ React__namespace.createElement(
76
+ AnimatedLegendListComponent,
77
+ {
78
+ animatedPropsInternal: animatedProps,
79
+ ref: refScrollView,
80
+ refLegendList: combinedRef,
81
+ ...rest
82
+ }
83
+ );
75
84
  })
76
85
  );
77
86
 
package/reanimated.mjs CHANGED
@@ -45,9 +45,18 @@ var AnimatedLegendListComponent = Reanimated.createAnimatedComponent(LegendListF
45
45
  var AnimatedLegendList = typedMemo(
46
46
  React.forwardRef(function AnimatedLegendList2(props, ref) {
47
47
  const { refScrollView, ...rest } = props;
48
+ const { animatedProps } = props;
48
49
  const refLegendList = React.useRef(null);
49
50
  const combinedRef = useCombinedRef(refLegendList, ref);
50
- return /* @__PURE__ */ React.createElement(AnimatedLegendListComponent, { ref: refScrollView, refLegendList: combinedRef, ...rest });
51
+ return /* @__PURE__ */ React.createElement(
52
+ AnimatedLegendListComponent,
53
+ {
54
+ animatedPropsInternal: animatedProps,
55
+ ref: refScrollView,
56
+ refLegendList: combinedRef,
57
+ ...rest
58
+ }
59
+ );
51
60
  })
52
61
  );
53
62