@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 +7 -0
- package/index.js +15 -8
- package/index.mjs +15 -8
- package/keyboard.d.mts +2 -2
- package/keyboard.d.ts +2 -2
- package/keyboard.js +87 -30
- package/keyboard.mjs +88 -31
- package/package.json +1 -1
- package/reanimated.js +10 -1
- package/reanimated.mjs +10 -1
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
|
-
|
|
2359
|
-
|
|
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
|
-
|
|
2338
|
-
|
|
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>, "
|
|
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>, "
|
|
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.
|
|
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
|
-
|
|
93
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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:
|
|
181
|
+
contentOffset: vAnimatedOffsetY === null ? void 0 : {
|
|
132
182
|
x: 0,
|
|
133
|
-
y:
|
|
183
|
+
y: vAnimatedOffsetY
|
|
134
184
|
}
|
|
135
185
|
};
|
|
136
|
-
return
|
|
186
|
+
return isIos ? Object.assign(baseProps, {
|
|
137
187
|
contentInset: {
|
|
138
|
-
bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInset.
|
|
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 =
|
|
146
|
-
|
|
147
|
-
|
|
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.
|
|
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
|
-
|
|
72
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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:
|
|
160
|
+
contentOffset: vAnimatedOffsetY === null ? void 0 : {
|
|
111
161
|
x: 0,
|
|
112
|
-
y:
|
|
162
|
+
y: vAnimatedOffsetY
|
|
113
163
|
}
|
|
114
164
|
};
|
|
115
|
-
return
|
|
165
|
+
return isIos ? Object.assign(baseProps, {
|
|
116
166
|
contentInset: {
|
|
117
|
-
bottom: ((_a = contentInsetProp == null ? void 0 : contentInsetProp.bottom) != null ? _a : 0) + (horizontal ? 0 : keyboardInset.
|
|
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 =
|
|
125
|
-
|
|
126
|
-
|
|
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
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(
|
|
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(
|
|
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
|
|