@rific/scroll-view 0.2.0 → 0.3.0
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/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +627 -306
- package/dist/index.mjs +580 -259
- package/package.json +3 -3
- package/src/CustomList.tsx +32 -8
- package/src/FlatList.tsx +102 -20
- package/src/PullSearch.tsx +4 -3
- package/src/ScrollView.tsx +28 -8
- package/src/ScrollViewContext.ts +17 -4
- package/src/ScrollViewHeader.tsx +34 -31
- package/src/ScrollViewProvider.tsx +22 -6
- package/src/SectionList.tsx +31 -10
- package/src/__mocks__/react-native-reanimated.ts +32 -1
- package/src/__tests__/FlatList.test.tsx +83 -0
- package/src/__tests__/useScrollHandlerJS.test.ts +119 -0
- package/src/__tests__/useScrollInit.test.ts +251 -0
- package/src/internal/useScrollHandler.ts +19 -21
- package/src/internal/useScrollHandlerJS.ts +141 -0
- package/src/internal/useScrollList.ts +16 -11
- package/src/useScrollInit.ts +200 -19
- package/src/out.txt +0 -61
package/dist/index.mjs
CHANGED
|
@@ -3,9 +3,10 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
|
|
5
5
|
// src/CustomList.tsx
|
|
6
|
-
import { memo, useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
6
|
+
import { memo, useCallback as useCallback2, useContext as useContext4, useLayoutEffect as useLayoutEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
7
7
|
import { Dimensions, View } from "react-native";
|
|
8
8
|
import { Gesture, GestureDetector } from "react-native-gesture-handler";
|
|
9
|
+
import { runOnUI, useSharedValue as useSharedValue4 } from "react-native-reanimated";
|
|
9
10
|
|
|
10
11
|
// src/internal/RefreshControl.tsx
|
|
11
12
|
import { RefreshControl as RNRefreshControl } from "react-native";
|
|
@@ -31,8 +32,8 @@ var styles = StyleSheet.create({
|
|
|
31
32
|
});
|
|
32
33
|
|
|
33
34
|
// src/internal/useScrollHandler.ts
|
|
34
|
-
import { useContext } from "react";
|
|
35
|
-
import { runOnJS, useAnimatedScrollHandler, useSharedValue, withTiming } from "react-native-reanimated";
|
|
35
|
+
import { useContext as useContext2 } from "react";
|
|
36
|
+
import { runOnJS, useAnimatedScrollHandler, useSharedValue as useSharedValue2, withTiming } from "react-native-reanimated";
|
|
36
37
|
|
|
37
38
|
// src/ScrollViewContext.ts
|
|
38
39
|
import { createContext } from "react";
|
|
@@ -42,10 +43,16 @@ var ScrollViewContext = createContext({
|
|
|
42
43
|
footerHeightShared: null,
|
|
43
44
|
footerFixed: false,
|
|
44
45
|
footerOffset: null,
|
|
45
|
-
headerHeight:
|
|
46
|
+
headerHeight: null,
|
|
46
47
|
headerHeightShared: null,
|
|
47
48
|
headerFixed: false,
|
|
48
49
|
headerOffset: null,
|
|
50
|
+
jsListGeneration: { current: 0 },
|
|
51
|
+
listGeneration: null,
|
|
52
|
+
onJsListUnmount: () => {
|
|
53
|
+
},
|
|
54
|
+
onListUnmount: () => {
|
|
55
|
+
},
|
|
49
56
|
progress: null,
|
|
50
57
|
progressing: false,
|
|
51
58
|
pullSearchHeightShared: null,
|
|
@@ -64,17 +71,207 @@ var ScrollViewContext = createContext({
|
|
|
64
71
|
tabBarHeight: 60
|
|
65
72
|
});
|
|
66
73
|
|
|
74
|
+
// src/useScrollInit.ts
|
|
75
|
+
import { createElement, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
76
|
+
import { useSharedValue } from "react-native-reanimated";
|
|
77
|
+
var REMOUNT_SYNC_MAX_ATTEMPTS = 8;
|
|
78
|
+
var REMOUNT_SYNC_TOLERANCE = 1;
|
|
79
|
+
var REMOUNT_SYNC_FALLBACK_MS = 500;
|
|
80
|
+
var REMOUNT_PRIME_FRAMES = 40;
|
|
81
|
+
var SNAP_VERIFY_TOLERANCE = 1;
|
|
82
|
+
var SNAP_VERIFY_MAX_ATTEMPTS = 5;
|
|
83
|
+
var SNAP_VERIFY_INITIAL_DELAY_MS = 400;
|
|
84
|
+
var SNAP_VERIFY_RETRY_DELAY_MS = 150;
|
|
85
|
+
function useScrollInit({ listHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollTo }) {
|
|
86
|
+
const { headerHeight, scrollPosition, setProgressing } = useContext(ScrollViewContext);
|
|
87
|
+
const hasPullSearch = pullSearchHeight !== void 0;
|
|
88
|
+
const [phase, setPhase] = useState(hasPullSearch && !headerHeight ? "measuring" : "ready");
|
|
89
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
90
|
+
const refreshingRef = useRef(refreshing);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
refreshingRef.current = refreshing;
|
|
93
|
+
}, [refreshing]);
|
|
94
|
+
const dragStartY = useRef(null);
|
|
95
|
+
const pendingSnapTarget = useRef(null);
|
|
96
|
+
const snapVerifyTimeout = useRef(null);
|
|
97
|
+
const snapVerifyAttempts = useRef(0);
|
|
98
|
+
const scheduleSnapVerification = useCallback(
|
|
99
|
+
(target, delay) => {
|
|
100
|
+
if (snapVerifyTimeout.current !== null) clearTimeout(snapVerifyTimeout.current);
|
|
101
|
+
pendingSnapTarget.current = target;
|
|
102
|
+
snapVerifyAttempts.current = 0;
|
|
103
|
+
const check = () => {
|
|
104
|
+
snapVerifyTimeout.current = null;
|
|
105
|
+
if (pendingSnapTarget.current !== target) return;
|
|
106
|
+
if (Math.abs(scrollPosition.value - target) <= SNAP_VERIFY_TOLERANCE) {
|
|
107
|
+
pendingSnapTarget.current = null;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
snapVerifyAttempts.current += 1;
|
|
111
|
+
if (snapVerifyAttempts.current > SNAP_VERIFY_MAX_ATTEMPTS || refreshingRef.current) {
|
|
112
|
+
pendingSnapTarget.current = null;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
scrollTo(target, false);
|
|
116
|
+
snapVerifyTimeout.current = setTimeout(check, SNAP_VERIFY_RETRY_DELAY_MS);
|
|
117
|
+
};
|
|
118
|
+
snapVerifyTimeout.current = setTimeout(check, delay);
|
|
119
|
+
},
|
|
120
|
+
[scrollPosition, scrollTo]
|
|
121
|
+
);
|
|
122
|
+
useEffect(
|
|
123
|
+
() => () => {
|
|
124
|
+
if (snapVerifyTimeout.current !== null) clearTimeout(snapVerifyTimeout.current);
|
|
125
|
+
},
|
|
126
|
+
[]
|
|
127
|
+
);
|
|
128
|
+
const [remountTarget] = useState(() => headerHeight !== null ? -headerHeight + (pullSearchHeight ?? 0) : null);
|
|
129
|
+
const remountSyncTarget = useSharedValue(remountTarget);
|
|
130
|
+
const [scrollReady, setScrollReady] = useState(remountTarget === null);
|
|
131
|
+
const remountAttempts = useRef(0);
|
|
132
|
+
const onRemountSynced = useCallback(
|
|
133
|
+
(y) => {
|
|
134
|
+
scrollPosition.value = y;
|
|
135
|
+
setScrollReady(true);
|
|
136
|
+
},
|
|
137
|
+
[scrollPosition]
|
|
138
|
+
);
|
|
139
|
+
const onRemountSyncRetry = useCallback(
|
|
140
|
+
(currentY) => {
|
|
141
|
+
if (remountTarget === null) return;
|
|
142
|
+
remountAttempts.current += 1;
|
|
143
|
+
if (remountAttempts.current > REMOUNT_SYNC_MAX_ATTEMPTS) {
|
|
144
|
+
remountSyncTarget.value = null;
|
|
145
|
+
onRemountSynced(currentY);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
scrollTo(remountTarget, false);
|
|
149
|
+
},
|
|
150
|
+
[onRemountSynced, remountSyncTarget, remountTarget, scrollTo]
|
|
151
|
+
);
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (remountTarget === null) return;
|
|
154
|
+
scrollTo(remountTarget, false);
|
|
155
|
+
const fallback = setTimeout(() => {
|
|
156
|
+
if (remountSyncTarget.value === null) return;
|
|
157
|
+
remountSyncTarget.value = null;
|
|
158
|
+
onRemountSynced(remountTarget);
|
|
159
|
+
}, REMOUNT_SYNC_FALLBACK_MS);
|
|
160
|
+
return () => clearTimeout(fallback);
|
|
161
|
+
}, []);
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (phase === "ready" || !headerHeight || !pullSearchHeight) return;
|
|
164
|
+
scrollPosition.value = -headerHeight + pullSearchHeight;
|
|
165
|
+
setPhase("ready");
|
|
166
|
+
}, [phase, headerHeight, pullSearchHeight, scrollPosition]);
|
|
167
|
+
const headerInitialized = useRef(false);
|
|
168
|
+
useLayoutEffect(() => {
|
|
169
|
+
if (!headerHeight || headerInitialized.current) return;
|
|
170
|
+
headerInitialized.current = true;
|
|
171
|
+
const target = remountTarget ?? -headerHeight;
|
|
172
|
+
scrollPosition.value = target;
|
|
173
|
+
scrollTo(target, false);
|
|
174
|
+
if (remountTarget === null) return;
|
|
175
|
+
let framesLeft = REMOUNT_PRIME_FRAMES;
|
|
176
|
+
let handle = null;
|
|
177
|
+
const tick = () => {
|
|
178
|
+
const offset = framesLeft === 1 ? target : framesLeft % 2 === 0 ? target + 30 : target - 30;
|
|
179
|
+
scrollTo(offset, false);
|
|
180
|
+
framesLeft -= 1;
|
|
181
|
+
if (framesLeft > 0) handle = requestAnimationFrame(tick);
|
|
182
|
+
};
|
|
183
|
+
handle = requestAnimationFrame(tick);
|
|
184
|
+
return () => {
|
|
185
|
+
if (handle !== null) cancelAnimationFrame(handle);
|
|
186
|
+
};
|
|
187
|
+
}, [remountTarget, headerHeight, scrollPosition, scrollTo]);
|
|
188
|
+
const pullSearchInitialized = useRef(false);
|
|
189
|
+
useLayoutEffect(() => {
|
|
190
|
+
if (remountTarget !== null || !hasPullSearch || phase !== "ready" || pullSearchInitialized.current || !headerHeight || !pullSearchHeight || !scrollReady) return;
|
|
191
|
+
pullSearchInitialized.current = true;
|
|
192
|
+
scrollPosition.value = -headerHeight + pullSearchHeight;
|
|
193
|
+
scrollTo(-headerHeight + pullSearchHeight, false);
|
|
194
|
+
}, [remountTarget, hasPullSearch, phase, headerHeight, pullSearchHeight, scrollPosition, scrollReady, scrollTo]);
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
if (pullSearchHeight) setProgressing(refreshing);
|
|
197
|
+
}, [pullSearchHeight, refreshing, setProgressing]);
|
|
198
|
+
const handleScrollBeginDrag = useCallback(
|
|
199
|
+
(e) => {
|
|
200
|
+
if (snapVerifyTimeout.current !== null) {
|
|
201
|
+
clearTimeout(snapVerifyTimeout.current);
|
|
202
|
+
snapVerifyTimeout.current = null;
|
|
203
|
+
}
|
|
204
|
+
pendingSnapTarget.current = null;
|
|
205
|
+
if (pullSearchHeight) dragStartY.current = e.nativeEvent.contentOffset.y;
|
|
206
|
+
externalScrollBeginDrag?.(e);
|
|
207
|
+
},
|
|
208
|
+
[externalScrollBeginDrag, pullSearchHeight]
|
|
209
|
+
);
|
|
210
|
+
const handleScrollEndDrag = useCallback(
|
|
211
|
+
(e) => {
|
|
212
|
+
if (pullSearchHeight && headerHeight) {
|
|
213
|
+
const y = e.nativeEvent.contentOffset.y;
|
|
214
|
+
const showY = -headerHeight;
|
|
215
|
+
const hideY = -headerHeight + pullSearchHeight;
|
|
216
|
+
const startY = dragStartY.current;
|
|
217
|
+
dragStartY.current = null;
|
|
218
|
+
const pulledDown = (startY ?? hideY) <= hideY;
|
|
219
|
+
const dragDistance = startY !== null ? startY - y : 0;
|
|
220
|
+
if (pulledDown && dragDistance >= pullSearchHeight * 0.5) {
|
|
221
|
+
if (y <= showY && !refreshing && onRefresh) {
|
|
222
|
+
setRefreshing(true);
|
|
223
|
+
Promise.resolve(onRefresh()).finally(() => setRefreshing(false));
|
|
224
|
+
}
|
|
225
|
+
scrollTo(showY, true);
|
|
226
|
+
scheduleSnapVerification(showY, SNAP_VERIFY_INITIAL_DELAY_MS);
|
|
227
|
+
} else if (y < hideY) {
|
|
228
|
+
scrollTo(hideY, true);
|
|
229
|
+
scheduleSnapVerification(hideY, SNAP_VERIFY_INITIAL_DELAY_MS);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
externalScrollEndDrag?.(e);
|
|
233
|
+
},
|
|
234
|
+
[externalScrollEndDrag, headerHeight, onRefresh, pullSearchHeight, refreshing, scheduleSnapVerification, scrollTo]
|
|
235
|
+
);
|
|
236
|
+
const handleMomentumScrollEnd = useCallback(
|
|
237
|
+
(e) => {
|
|
238
|
+
if (pullSearchHeight && headerHeight && !refreshing && pendingSnapTarget.current === null) {
|
|
239
|
+
const y = e.nativeEvent.contentOffset.y;
|
|
240
|
+
const hideY = -headerHeight + pullSearchHeight;
|
|
241
|
+
if (y < hideY - 1) {
|
|
242
|
+
scrollTo(hideY, true);
|
|
243
|
+
scheduleSnapVerification(hideY, SNAP_VERIFY_INITIAL_DELAY_MS);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
externalMomentumScrollEnd?.(e);
|
|
247
|
+
},
|
|
248
|
+
[externalMomentumScrollEnd, headerHeight, pullSearchHeight, refreshing, scheduleSnapVerification, scrollTo]
|
|
249
|
+
);
|
|
250
|
+
const activeListHeader = hasPullSearch && phase === "measuring" ? null : listHeaderComponent;
|
|
251
|
+
const hiddenHeader = phase === "measuring" && listHeaderComponent != null ? typeof listHeaderComponent === "function" ? createElement(listHeaderComponent) : listHeaderComponent : null;
|
|
252
|
+
return { activeListHeader, handleMomentumScrollEnd, handleScrollBeginDrag, handleScrollEndDrag, hiddenHeader, onRemountSyncRetry, onRemountSynced, pullSearchMinHeight: pullSearchHeight ?? 0, remountSyncTarget, remountTarget, scrollReady };
|
|
253
|
+
}
|
|
254
|
+
|
|
67
255
|
// src/internal/useScrollHandler.ts
|
|
68
|
-
function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal,
|
|
69
|
-
const { footerHeightShared, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared } =
|
|
70
|
-
const snapUpAccum =
|
|
71
|
-
const fromBottomBounce =
|
|
72
|
-
const isMomentum = useSharedValue(false);
|
|
73
|
-
const momentumPullSearchFired = useSharedValue(false);
|
|
256
|
+
function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, listGeneration, onRemountSyncRetry, onRemountSynced, remountSyncTarget }) {
|
|
257
|
+
const { footerHeightShared, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared } = useContext2(ScrollViewContext);
|
|
258
|
+
const snapUpAccum = useSharedValue2(0);
|
|
259
|
+
const fromBottomBounce = useSharedValue2(false);
|
|
74
260
|
return useAnimatedScrollHandler(
|
|
75
261
|
{
|
|
76
262
|
onScroll: ({ contentOffset: { x, y }, contentSize: { height: contentHeight }, layoutMeasurement: { height: layoutHeight } }) => {
|
|
77
263
|
"worklet";
|
|
264
|
+
if (remountSyncTarget && remountSyncTarget.value !== null) {
|
|
265
|
+
const target = remountSyncTarget.value;
|
|
266
|
+
if (Math.abs(y - target) < REMOUNT_SYNC_TOLERANCE) {
|
|
267
|
+
remountSyncTarget.value = null;
|
|
268
|
+
if (onRemountSynced) runOnJS(onRemountSynced)(y);
|
|
269
|
+
} else if (onRemountSyncRetry) {
|
|
270
|
+
runOnJS(onRemountSyncRetry)(y);
|
|
271
|
+
}
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
if (listGeneration.value !== capturedGeneration.value) return;
|
|
78
275
|
if (isHorizontal) {
|
|
79
276
|
scrollPosition.value = x;
|
|
80
277
|
chipHidden.value = x < chipThreshold ? 1 : 0;
|
|
@@ -90,13 +287,6 @@ function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, header
|
|
|
90
287
|
} else if (fromBottomBounce.value) {
|
|
91
288
|
fromBottomBounce.value = false;
|
|
92
289
|
}
|
|
93
|
-
if (isMomentum.value && pullSearchHeightShared.value > 0 && !momentumPullSearchFired.value) {
|
|
94
|
-
const hideY = -headerHeightShared.value + pullSearchHeightShared.value;
|
|
95
|
-
if (y < hideY) {
|
|
96
|
-
momentumPullSearchFired.value = true;
|
|
97
|
-
if (onPullSearchZoneEnter) runOnJS(onPullSearchZoneEnter)();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
290
|
const snapHeader = snapBackHeaderShared.value && !headerFixed;
|
|
101
291
|
const snapFooter = snapBackFooterShared.value && !footerFixed;
|
|
102
292
|
if (snapHeader || snapFooter) {
|
|
@@ -122,16 +312,9 @@ function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, header
|
|
|
122
312
|
},
|
|
123
313
|
onBeginDrag: () => {
|
|
124
314
|
"worklet";
|
|
125
|
-
isMomentum.value = false;
|
|
126
|
-
momentumPullSearchFired.value = false;
|
|
127
315
|
fromBottomBounce.value = false;
|
|
128
316
|
snapUpAccum.value = 0;
|
|
129
317
|
},
|
|
130
|
-
onMomentumBegin: () => {
|
|
131
|
-
"worklet";
|
|
132
|
-
isMomentum.value = true;
|
|
133
|
-
momentumPullSearchFired.value = false;
|
|
134
|
-
},
|
|
135
318
|
onEndDrag: ({ contentOffset: { y }, contentSize: { height: contentHeight }, layoutMeasurement: { height: layoutHeight } }) => {
|
|
136
319
|
"worklet";
|
|
137
320
|
if (isHorizontal) return;
|
|
@@ -142,28 +325,26 @@ function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, header
|
|
|
142
325
|
},
|
|
143
326
|
onMomentumEnd: () => {
|
|
144
327
|
"worklet";
|
|
145
|
-
isMomentum.value = false;
|
|
146
|
-
momentumPullSearchFired.value = false;
|
|
147
328
|
fromBottomBounce.value = false;
|
|
148
329
|
snapUpAccum.value = 0;
|
|
149
330
|
}
|
|
150
331
|
},
|
|
151
|
-
[headerFixed, footerFixed, isHorizontal, chipThreshold,
|
|
332
|
+
[capturedGeneration, headerFixed, footerFixed, isHorizontal, chipThreshold, listGeneration, onRemountSyncRetry, onRemountSynced, remountSyncTarget]
|
|
152
333
|
);
|
|
153
334
|
}
|
|
154
335
|
|
|
155
336
|
// src/internal/useScrollList.ts
|
|
156
|
-
import { useContext as
|
|
337
|
+
import { useContext as useContext3, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
|
|
157
338
|
import { StyleSheet as StyleSheet2 } from "react-native";
|
|
158
|
-
import { useAnimatedStyle, useSharedValue as
|
|
339
|
+
import { useAnimatedStyle, useSharedValue as useSharedValue3, withTiming as withTiming2 } from "react-native-reanimated";
|
|
159
340
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
160
341
|
|
|
161
342
|
// src/useKeyboardInset.ts
|
|
162
|
-
import { useState } from "react";
|
|
343
|
+
import { useState as useState2 } from "react";
|
|
163
344
|
import { useKeyboardHandler } from "react-native-keyboard-controller";
|
|
164
345
|
import { runOnJS as runOnJS2 } from "react-native-reanimated";
|
|
165
346
|
var useKeyboardInset = () => {
|
|
166
|
-
const [keyboardHeight, setKeyboardHeight] =
|
|
347
|
+
const [keyboardHeight, setKeyboardHeight] = useState2(0);
|
|
167
348
|
useKeyboardHandler(
|
|
168
349
|
{
|
|
169
350
|
onMove: (e) => {
|
|
@@ -185,28 +366,30 @@ var CHIP_SLIDE = 48;
|
|
|
185
366
|
function useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, isHorizontal, keyboardAware, pullSearchHeight, style } = {}) {
|
|
186
367
|
const insets = useSafeAreaInsets();
|
|
187
368
|
const keyboardHeight = useKeyboardInset();
|
|
188
|
-
const { footerHeight, footerFixed: contextFooterFixed, headerHeight, headerFixed: contextHeaderFixed, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } =
|
|
369
|
+
const { footerHeight, footerFixed: contextFooterFixed, headerHeight, headerFixed: contextHeaderFixed, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } = useContext3(ScrollViewContext);
|
|
189
370
|
const headerFixed = isHorizontal ? true : headerFixedProp ?? contextHeaderFixed;
|
|
190
371
|
const footerFixed = isHorizontal ? true : footerFixedProp ?? contextFooterFixed;
|
|
191
|
-
|
|
372
|
+
useEffect2(() => {
|
|
192
373
|
pullSearchHeightShared.value = pullSearchHeight ?? 0;
|
|
193
374
|
}, [pullSearchHeight, pullSearchHeightShared]);
|
|
194
|
-
const containerStyle = useMemo(() => headerHeight ===
|
|
195
|
-
const contentInset = useMemo(() => ({ bottom: (footerFixed ? footerHeight || insets.bottom : insets.bottom) + (keyboardAware ? keyboardHeight : 0), top: headerHeight }), [footerFixed, footerHeight, insets.bottom, headerHeight, keyboardAware, keyboardHeight]);
|
|
196
|
-
const
|
|
197
|
-
const
|
|
375
|
+
const containerStyle = useMemo(() => headerHeight === null ? [{ flex: 1, opacity: 0 }, style] : [StyleSheet2.absoluteFill, style], [headerHeight, style]);
|
|
376
|
+
const contentInset = useMemo(() => ({ bottom: (footerFixed ? footerHeight || insets.bottom : insets.bottom) + (keyboardAware ? keyboardHeight : 0), top: headerHeight ?? 0 }), [footerFixed, footerHeight, insets.bottom, headerHeight, keyboardAware, keyboardHeight]);
|
|
377
|
+
const [startedWithHeader] = useState3(headerHeight !== null);
|
|
378
|
+
const contentOffset = useMemo(() => ({ x: 0, y: headerHeight !== null ? -headerHeight + (startedWithHeader && !isHorizontal && pullSearchHeight ? pullSearchHeight : 0) : 0 }), [headerHeight, isHorizontal, pullSearchHeight, startedWithHeader]);
|
|
379
|
+
const chipHidden = useSharedValue3(1);
|
|
198
380
|
const chipStyle = useAnimatedStyle(() => {
|
|
199
381
|
const pointerEvents = chipHidden.value ? "none" : "box-none";
|
|
200
382
|
if (isHorizontal) {
|
|
201
383
|
return {
|
|
202
384
|
opacity: chipHidden.value ? withTiming2(0) : withTiming2(1),
|
|
203
385
|
pointerEvents,
|
|
204
|
-
top: Math.max(headerHeight, insets.top) + 4,
|
|
386
|
+
top: Math.max(headerHeight ?? 0, insets.top) + 4,
|
|
205
387
|
transform: [{ translateX: chipHidden.value ? withTiming2(-CHIP_SLIDE) : withTiming2(0) }]
|
|
206
388
|
};
|
|
207
389
|
}
|
|
208
|
-
const
|
|
209
|
-
const
|
|
390
|
+
const h = headerHeight ?? 0;
|
|
391
|
+
const slide = headerFixed ? 0 : snapBackHeaderShared.value ? -headerOffset.value : Math.max(0, scrollPosition.value + h - pullSearchHeightShared.value);
|
|
392
|
+
const top = Math.max(h - slide, insets.top) + 4;
|
|
210
393
|
return {
|
|
211
394
|
opacity: chipHidden.value ? withTiming2(0) : withTiming2(1),
|
|
212
395
|
pointerEvents,
|
|
@@ -217,90 +400,21 @@ function useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedP
|
|
|
217
400
|
return { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed, headerHeight, insets, isHorizontal: isHorizontal ?? false };
|
|
218
401
|
}
|
|
219
402
|
|
|
220
|
-
// src/useScrollInit.ts
|
|
221
|
-
import { createElement, useCallback, useContext as useContext3, useEffect as useEffect2, useLayoutEffect, useRef, useState as useState2 } from "react";
|
|
222
|
-
function useScrollInit({ listHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollTo }) {
|
|
223
|
-
const { headerHeight, scrollPosition, setProgressing } = useContext3(ScrollViewContext);
|
|
224
|
-
const hasPullSearch = pullSearchHeight !== void 0;
|
|
225
|
-
const [phase, setPhase] = useState2(hasPullSearch ? "measuring" : "ready");
|
|
226
|
-
const [refreshing, setRefreshing] = useState2(false);
|
|
227
|
-
const dragStartY = useRef(null);
|
|
228
|
-
const deliberatelyOpened = useRef(false);
|
|
229
|
-
useEffect2(() => {
|
|
230
|
-
if (phase === "ready" || !headerHeight || !pullSearchHeight) return;
|
|
231
|
-
scrollPosition.value = -headerHeight + pullSearchHeight;
|
|
232
|
-
setPhase("ready");
|
|
233
|
-
}, [phase, headerHeight, pullSearchHeight, scrollPosition]);
|
|
234
|
-
const headerInitialized = useRef(false);
|
|
235
|
-
useLayoutEffect(() => {
|
|
236
|
-
if (!headerHeight || headerInitialized.current) return;
|
|
237
|
-
headerInitialized.current = true;
|
|
238
|
-
scrollPosition.value = -headerHeight;
|
|
239
|
-
scrollTo(-headerHeight, false);
|
|
240
|
-
}, [headerHeight, scrollPosition, scrollTo]);
|
|
241
|
-
const pullSearchInitialized = useRef(false);
|
|
242
|
-
useLayoutEffect(() => {
|
|
243
|
-
if (!hasPullSearch || phase !== "ready" || pullSearchInitialized.current || !headerHeight || !pullSearchHeight) return;
|
|
244
|
-
pullSearchInitialized.current = true;
|
|
245
|
-
scrollPosition.value = -headerHeight + pullSearchHeight;
|
|
246
|
-
scrollTo(-headerHeight + pullSearchHeight, false);
|
|
247
|
-
}, [hasPullSearch, phase, headerHeight, pullSearchHeight, scrollPosition, scrollTo]);
|
|
248
|
-
useEffect2(() => {
|
|
249
|
-
if (pullSearchHeight) setProgressing(refreshing);
|
|
250
|
-
}, [pullSearchHeight, refreshing, setProgressing]);
|
|
251
|
-
const handleScrollBeginDrag = useCallback(
|
|
252
|
-
(e) => {
|
|
253
|
-
deliberatelyOpened.current = false;
|
|
254
|
-
if (pullSearchHeight) dragStartY.current = e.nativeEvent.contentOffset.y;
|
|
255
|
-
externalScrollBeginDrag?.(e);
|
|
256
|
-
},
|
|
257
|
-
[externalScrollBeginDrag, pullSearchHeight]
|
|
258
|
-
);
|
|
259
|
-
const handleScrollEndDrag = useCallback(
|
|
260
|
-
(e) => {
|
|
261
|
-
if (pullSearchHeight && headerHeight) {
|
|
262
|
-
const y = e.nativeEvent.contentOffset.y;
|
|
263
|
-
const showY = -headerHeight;
|
|
264
|
-
const hideY = -headerHeight + pullSearchHeight;
|
|
265
|
-
const pulledDown = (dragStartY.current ?? hideY) <= hideY;
|
|
266
|
-
dragStartY.current = null;
|
|
267
|
-
if (pulledDown && y <= showY + pullSearchHeight * 0.5) {
|
|
268
|
-
deliberatelyOpened.current = true;
|
|
269
|
-
if (y <= showY && !refreshing && onRefresh) {
|
|
270
|
-
setRefreshing(true);
|
|
271
|
-
Promise.resolve(onRefresh()).finally(() => setRefreshing(false));
|
|
272
|
-
}
|
|
273
|
-
scrollTo(showY, true);
|
|
274
|
-
} else if (y < hideY) {
|
|
275
|
-
scrollTo(hideY, true);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
externalScrollEndDrag?.(e);
|
|
279
|
-
},
|
|
280
|
-
[externalScrollEndDrag, headerHeight, onRefresh, pullSearchHeight, refreshing, scrollTo]
|
|
281
|
-
);
|
|
282
|
-
const handleMomentumScrollEnd = useCallback(
|
|
283
|
-
(e) => {
|
|
284
|
-
if (pullSearchHeight && headerHeight && !deliberatelyOpened.current && !refreshing) {
|
|
285
|
-
const y = e.nativeEvent.contentOffset.y;
|
|
286
|
-
const hideY = -headerHeight + pullSearchHeight;
|
|
287
|
-
if (y < hideY - 1) scrollTo(hideY, true);
|
|
288
|
-
}
|
|
289
|
-
deliberatelyOpened.current = false;
|
|
290
|
-
externalMomentumScrollEnd?.(e);
|
|
291
|
-
},
|
|
292
|
-
[externalMomentumScrollEnd, headerHeight, pullSearchHeight, refreshing, scrollTo]
|
|
293
|
-
);
|
|
294
|
-
const activeListHeader = hasPullSearch && phase === "measuring" ? null : listHeaderComponent;
|
|
295
|
-
const hiddenHeader = phase === "measuring" && listHeaderComponent != null ? typeof listHeaderComponent === "function" ? createElement(listHeaderComponent) : listHeaderComponent : null;
|
|
296
|
-
return { activeListHeader, handleMomentumScrollEnd, handleScrollBeginDrag, handleScrollEndDrag, hiddenHeader, pullSearchMinHeight: pullSearchHeight ?? 0 };
|
|
297
|
-
}
|
|
298
|
-
|
|
299
403
|
// src/CustomList.tsx
|
|
300
404
|
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
301
405
|
var CustomListInner = ({ chipProps, chipThreshold, component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }) => {
|
|
302
406
|
const { ListHeaderComponent: listHeaderComponent, contentContainerStyle: externalContentContainerStyle, ...restProps } = props;
|
|
303
407
|
const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
|
|
408
|
+
const { listGeneration, onListUnmount } = useContext4(ScrollViewContext);
|
|
409
|
+
const capturedGeneration = useSharedValue4(-1);
|
|
410
|
+
useLayoutEffect2(() => {
|
|
411
|
+
const generation = listGeneration.value;
|
|
412
|
+
runOnUI((gen) => {
|
|
413
|
+
"worklet";
|
|
414
|
+
capturedGeneration.value = gen;
|
|
415
|
+
})(generation);
|
|
416
|
+
}, [capturedGeneration, listGeneration]);
|
|
417
|
+
useLayoutEffect2(() => () => onListUnmount(), [onListUnmount]);
|
|
304
418
|
const scrollViewInternal = useRef2(null);
|
|
305
419
|
const handleRef = useCallback2(
|
|
306
420
|
(el) => {
|
|
@@ -318,7 +432,10 @@ var CustomListInner = ({ chipProps, chipThreshold, component: List, renderFilter
|
|
|
318
432
|
handleScrollBeginDrag,
|
|
319
433
|
handleScrollEndDrag,
|
|
320
434
|
hiddenHeader,
|
|
321
|
-
|
|
435
|
+
onRemountSyncRetry,
|
|
436
|
+
onRemountSynced,
|
|
437
|
+
pullSearchMinHeight,
|
|
438
|
+
remountSyncTarget
|
|
322
439
|
} = useScrollInit({
|
|
323
440
|
listHeaderComponent,
|
|
324
441
|
onMomentumScrollEnd: externalMomentumScrollEnd,
|
|
@@ -337,11 +454,7 @@ var CustomListInner = ({ chipProps, chipThreshold, component: List, renderFilter
|
|
|
337
454
|
] });
|
|
338
455
|
}, [pullSearchHeader, renderFilters]);
|
|
339
456
|
const contentContainerStyle = useMemo2(() => [{ minHeight: Dimensions.get("window").height - contentInset.top - contentInset.bottom + pullSearchMinHeight }, externalContentContainerStyle], [contentInset.bottom, contentInset.top, externalContentContainerStyle, pullSearchMinHeight]);
|
|
340
|
-
const
|
|
341
|
-
if (!pullSearchHeight) return;
|
|
342
|
-
scrollViewInternal.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true });
|
|
343
|
-
}, [contentInset.top, pullSearchHeight]);
|
|
344
|
-
const onScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
|
|
457
|
+
const onScroll = useScrollHandler({ capturedGeneration, chipHidden, chipThreshold, footerFixed, headerFixed, listGeneration, onRemountSyncRetry, onRemountSynced, remountSyncTarget });
|
|
345
458
|
const handleScrollToTop = useCallback2(() => {
|
|
346
459
|
const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
|
|
347
460
|
scrollViewInternal.current?.scrollToOffset({ offset, animated: true });
|
|
@@ -362,14 +475,13 @@ var styles2 = { measureContainer: { left: 0, opacity: 0, position: "absolute", r
|
|
|
362
475
|
var CustomList = memo(CustomListInner);
|
|
363
476
|
|
|
364
477
|
// src/FlatList.tsx
|
|
365
|
-
import { memo as memo2, useCallback as
|
|
366
|
-
import { Dimensions as Dimensions2, View as View3 } from "react-native";
|
|
478
|
+
import { Fragment as Fragment2, memo as memo2, useCallback as useCallback4, useContext as useContext7, useLayoutEffect as useLayoutEffect3, useMemo as useMemo3, useRef as useRef4 } from "react";
|
|
479
|
+
import { Dimensions as Dimensions2, FlatList as RNFlatList, View as View3 } from "react-native";
|
|
367
480
|
import { Gesture as Gesture2, GestureDetector as GestureDetector2 } from "react-native-gesture-handler";
|
|
368
|
-
import Animated3 from "react-native-reanimated";
|
|
369
481
|
|
|
370
482
|
// src/internal/HorizontalDots.tsx
|
|
371
483
|
import { BlurView } from "@rific/auto-paper";
|
|
372
|
-
import { useContext as
|
|
484
|
+
import { useContext as useContext5 } from "react";
|
|
373
485
|
import { StyleSheet as StyleSheet3, useWindowDimensions, View as View2 } from "react-native";
|
|
374
486
|
import { useTheme } from "react-native-paper";
|
|
375
487
|
import Animated2, { interpolateColor, useAnimatedStyle as useAnimatedStyle2 } from "react-native-reanimated";
|
|
@@ -398,7 +510,7 @@ var Dot = ({ activeColor, index, inactiveColor, pageWidth, scrollPosition }) =>
|
|
|
398
510
|
return /* @__PURE__ */ jsx4(View2, { style: styles3.dotContainer, children: /* @__PURE__ */ jsx4(Animated2.View, { style: circleStyle }) });
|
|
399
511
|
};
|
|
400
512
|
var HorizontalDots = ({ total }) => {
|
|
401
|
-
const { blur, footerHeightShared, scrollPosition } =
|
|
513
|
+
const { blur, footerHeightShared, scrollPosition } = useContext5(ScrollViewContext);
|
|
402
514
|
const { width } = useWindowDimensions();
|
|
403
515
|
const insets = useSafeAreaInsets2();
|
|
404
516
|
const theme = useTheme();
|
|
@@ -434,14 +546,144 @@ var styles3 = StyleSheet3.create({
|
|
|
434
546
|
pillContainer: { alignItems: "center", left: 0, position: "absolute", right: 0, zIndex: 3 }
|
|
435
547
|
});
|
|
436
548
|
|
|
549
|
+
// src/internal/useScrollHandlerJS.ts
|
|
550
|
+
import { useCallback as useCallback3, useContext as useContext6, useRef as useRef3 } from "react";
|
|
551
|
+
import { withTiming as withTiming3 } from "react-native-reanimated";
|
|
552
|
+
var REMOUNT_RETRY_TOLERANCE = 1;
|
|
553
|
+
var REMOUNT_RETRY_MAX_ATTEMPTS = 8;
|
|
554
|
+
function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, jsListGeneration, remountTarget = null, scrollTo }) {
|
|
555
|
+
const { footerHeightShared, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared } = useContext6(ScrollViewContext);
|
|
556
|
+
const snapUpAccum = useRef3(0);
|
|
557
|
+
const fromBottomBounce = useRef3(false);
|
|
558
|
+
const pendingRemountTarget = useRef3(remountTarget);
|
|
559
|
+
const remountAttempts = useRef3(0);
|
|
560
|
+
const onScroll = useCallback3(
|
|
561
|
+
(event) => {
|
|
562
|
+
if (jsListGeneration.current !== capturedGeneration.current) return;
|
|
563
|
+
const {
|
|
564
|
+
contentOffset: { x, y },
|
|
565
|
+
contentSize: { height: contentHeight },
|
|
566
|
+
layoutMeasurement: { height: layoutHeight }
|
|
567
|
+
} = event.nativeEvent;
|
|
568
|
+
if (pendingRemountTarget.current !== null) {
|
|
569
|
+
const target = pendingRemountTarget.current;
|
|
570
|
+
if (Math.abs(y - target) < REMOUNT_RETRY_TOLERANCE) {
|
|
571
|
+
pendingRemountTarget.current = null;
|
|
572
|
+
} else {
|
|
573
|
+
remountAttempts.current += 1;
|
|
574
|
+
if (remountAttempts.current > REMOUNT_RETRY_MAX_ATTEMPTS) {
|
|
575
|
+
pendingRemountTarget.current = null;
|
|
576
|
+
} else {
|
|
577
|
+
scrollTo?.(target, false);
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (isHorizontal) {
|
|
583
|
+
scrollPosition.value = x;
|
|
584
|
+
chipHidden.value = x < chipThreshold ? 1 : 0;
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const delta = y - scrollPosition.value;
|
|
588
|
+
scrollPosition.value = y;
|
|
589
|
+
chipHidden.value = y < chipThreshold ? 1 : 0;
|
|
590
|
+
const maxScroll = contentHeight - layoutHeight;
|
|
591
|
+
if (maxScroll > 0 && y >= maxScroll) {
|
|
592
|
+
fromBottomBounce.current = true;
|
|
593
|
+
snapUpAccum.current = 0;
|
|
594
|
+
} else if (fromBottomBounce.current) {
|
|
595
|
+
fromBottomBounce.current = false;
|
|
596
|
+
}
|
|
597
|
+
const snapHeader = snapBackHeaderShared.value && !headerFixed;
|
|
598
|
+
const snapFooter = snapBackFooterShared.value && !footerFixed;
|
|
599
|
+
if (snapHeader || snapFooter) {
|
|
600
|
+
if (y <= -headerHeightShared.value) {
|
|
601
|
+
snapUpAccum.current = 0;
|
|
602
|
+
if (snapHeader) headerOffset.value = 0;
|
|
603
|
+
if (snapFooter) footerOffset.value = 0;
|
|
604
|
+
} else if (delta > 0) {
|
|
605
|
+
snapUpAccum.current = 0;
|
|
606
|
+
if (y >= -headerHeightShared.value + pullSearchHeightShared.value) {
|
|
607
|
+
if (snapHeader) headerOffset.value = Math.max(-headerHeightShared.value, Math.min(0, headerOffset.value - delta));
|
|
608
|
+
if (snapFooter) footerOffset.value = Math.max(0, Math.min(footerHeightShared.value, footerOffset.value + delta));
|
|
609
|
+
}
|
|
610
|
+
} else if (delta < 0 && !fromBottomBounce.current) {
|
|
611
|
+
if (y >= -headerHeightShared.value + pullSearchHeightShared.value) snapUpAccum.current -= delta;
|
|
612
|
+
if (snapUpAccum.current >= 10) {
|
|
613
|
+
snapUpAccum.current = 999;
|
|
614
|
+
if (snapHeader) headerOffset.value = withTiming3(0, { duration: 200 });
|
|
615
|
+
if (snapFooter) footerOffset.value = withTiming3(0, { duration: 200 });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
[capturedGeneration, chipHidden, chipThreshold, footerFixed, footerHeightShared, footerOffset, headerFixed, headerHeightShared, headerOffset, isHorizontal, jsListGeneration, pullSearchHeightShared, scrollPosition, scrollTo, snapBackFooterShared, snapBackHeaderShared]
|
|
621
|
+
);
|
|
622
|
+
const onScrollBeginDrag = useCallback3(() => {
|
|
623
|
+
fromBottomBounce.current = false;
|
|
624
|
+
snapUpAccum.current = 0;
|
|
625
|
+
}, []);
|
|
626
|
+
const onMomentumScrollBegin = useCallback3(() => {
|
|
627
|
+
}, []);
|
|
628
|
+
const onScrollEndDrag = useCallback3(
|
|
629
|
+
(event) => {
|
|
630
|
+
if (isHorizontal) return;
|
|
631
|
+
const {
|
|
632
|
+
contentOffset: { y },
|
|
633
|
+
contentSize: { height: contentHeight },
|
|
634
|
+
layoutMeasurement: { height: layoutHeight }
|
|
635
|
+
} = event.nativeEvent;
|
|
636
|
+
if (y >= contentHeight - layoutHeight - 10) {
|
|
637
|
+
fromBottomBounce.current = true;
|
|
638
|
+
snapUpAccum.current = 0;
|
|
639
|
+
}
|
|
640
|
+
},
|
|
641
|
+
[isHorizontal]
|
|
642
|
+
);
|
|
643
|
+
const onMomentumScrollEnd = useCallback3(() => {
|
|
644
|
+
fromBottomBounce.current = false;
|
|
645
|
+
snapUpAccum.current = 0;
|
|
646
|
+
}, []);
|
|
647
|
+
return { onMomentumScrollBegin, onMomentumScrollEnd, onScroll, onScrollBeginDrag, onScrollEndDrag };
|
|
648
|
+
}
|
|
649
|
+
|
|
437
650
|
// src/FlatList.tsx
|
|
438
|
-
import { Fragment as
|
|
439
|
-
var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }) => {
|
|
440
|
-
const scrollView =
|
|
651
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
652
|
+
var FlatListInner = ({ chipProps, chipThreshold, columnWrapperStyle, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, keyExtractor, maxToRenderPerBatch = 50, numColumns, renderFilters, renderItem, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }) => {
|
|
653
|
+
const scrollView = useRef4(null);
|
|
441
654
|
const isHorizontal = horizontal === true;
|
|
442
655
|
const showDots = isHorizontal && pagingEnabled === true && (data?.length ?? 0) > 1;
|
|
656
|
+
const cols = numColumns && numColumns > 1 ? numColumns : 1;
|
|
657
|
+
const rowData = useMemo3(() => {
|
|
658
|
+
if (cols <= 1 || !data) return data;
|
|
659
|
+
const items = Array.from(data);
|
|
660
|
+
const rows = [];
|
|
661
|
+
for (let i = 0; i < items.length; i += cols) rows.push(items.slice(i, i + cols));
|
|
662
|
+
return rows;
|
|
663
|
+
}, [cols, data]);
|
|
664
|
+
const rowKeyExtractor = useCallback4(
|
|
665
|
+
(row, rowIndex) => {
|
|
666
|
+
if (cols <= 1) return keyExtractor ? keyExtractor(row, rowIndex) : defaultKeyExtractor(row, rowIndex);
|
|
667
|
+
return row.map((item, kk) => keyExtractor ? keyExtractor(item, rowIndex * cols + kk) : defaultKeyExtractor(item, rowIndex * cols + kk)).join(":");
|
|
668
|
+
},
|
|
669
|
+
[cols, keyExtractor]
|
|
670
|
+
);
|
|
671
|
+
const rowRenderItem = useCallback4(
|
|
672
|
+
(info) => {
|
|
673
|
+
if (cols <= 1) return renderItem ? renderItem(info) : null;
|
|
674
|
+
const row = info.item;
|
|
675
|
+
return /* @__PURE__ */ jsx5(View3, { style: [styles4.row, columnWrapperStyle], children: row.map((item, kk) => /* @__PURE__ */ jsx5(Fragment2, { children: renderItem ? renderItem({ index: info.index * cols + kk, item, separators: info.separators }) : null }, kk)) });
|
|
676
|
+
},
|
|
677
|
+
[cols, columnWrapperStyle, renderItem]
|
|
678
|
+
);
|
|
443
679
|
const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, isHorizontal, keyboardAware, pullSearchHeight, style });
|
|
444
|
-
const
|
|
680
|
+
const { jsListGeneration, onJsListUnmount } = useContext7(ScrollViewContext);
|
|
681
|
+
const capturedGeneration = useRef4(jsListGeneration.current);
|
|
682
|
+
useLayoutEffect3(() => {
|
|
683
|
+
capturedGeneration.current = jsListGeneration.current;
|
|
684
|
+
}, [jsListGeneration]);
|
|
685
|
+
useLayoutEffect3(() => () => onJsListUnmount(), [onJsListUnmount]);
|
|
686
|
+
const scrollTo = useCallback4((offset, animated) => {
|
|
445
687
|
scrollView.current?.scrollToOffset({ offset, animated });
|
|
446
688
|
}, []);
|
|
447
689
|
const {
|
|
@@ -450,7 +692,8 @@ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: external
|
|
|
450
692
|
handleScrollBeginDrag,
|
|
451
693
|
handleScrollEndDrag,
|
|
452
694
|
hiddenHeader,
|
|
453
|
-
pullSearchMinHeight
|
|
695
|
+
pullSearchMinHeight,
|
|
696
|
+
remountTarget
|
|
454
697
|
} = useScrollInit({
|
|
455
698
|
listHeaderComponent: externalListHeaderComponent,
|
|
456
699
|
onMomentumScrollEnd: externalMomentumScrollEnd,
|
|
@@ -463,18 +706,35 @@ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: external
|
|
|
463
706
|
const activeListHeader = useMemo3(() => {
|
|
464
707
|
if (!renderFilters) return pullSearchHeader;
|
|
465
708
|
const Inner = pullSearchHeader;
|
|
466
|
-
return () => /* @__PURE__ */ jsxs3(
|
|
709
|
+
return () => /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
467
710
|
Inner ? typeof Inner === "function" ? /* @__PURE__ */ jsx5(Inner, {}) : Inner : null,
|
|
468
711
|
renderFilters
|
|
469
712
|
] });
|
|
470
713
|
}, [pullSearchHeader, renderFilters]);
|
|
471
714
|
const contentContainerStyle = useMemo3(() => isHorizontal ? externalContentContainerStyle : [{ minHeight: Dimensions2.get("window").height - contentInset.top - contentInset.bottom + pullSearchMinHeight }, externalContentContainerStyle], [isHorizontal, contentInset.bottom, contentInset.top, externalContentContainerStyle, pullSearchMinHeight]);
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
715
|
+
const scrollHandler = useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, jsListGeneration, remountTarget, scrollTo });
|
|
716
|
+
const onScrollBeginDrag = useCallback4(
|
|
717
|
+
(e) => {
|
|
718
|
+
scrollHandler.onScrollBeginDrag(e);
|
|
719
|
+
handleScrollBeginDrag(e);
|
|
720
|
+
},
|
|
721
|
+
[scrollHandler, handleScrollBeginDrag]
|
|
722
|
+
);
|
|
723
|
+
const onScrollEndDrag = useCallback4(
|
|
724
|
+
(e) => {
|
|
725
|
+
scrollHandler.onScrollEndDrag(e);
|
|
726
|
+
handleScrollEndDrag(e);
|
|
727
|
+
},
|
|
728
|
+
[scrollHandler, handleScrollEndDrag]
|
|
729
|
+
);
|
|
730
|
+
const onMomentumScrollEnd = useCallback4(
|
|
731
|
+
(e) => {
|
|
732
|
+
scrollHandler.onMomentumScrollEnd(e);
|
|
733
|
+
handleMomentumScrollEnd(e);
|
|
734
|
+
},
|
|
735
|
+
[scrollHandler, handleMomentumScrollEnd]
|
|
736
|
+
);
|
|
737
|
+
const handleScrollToTop = useCallback4(() => {
|
|
478
738
|
if (isHorizontal) {
|
|
479
739
|
scrollView.current?.scrollToOffset({ offset: 0, animated: true });
|
|
480
740
|
return;
|
|
@@ -482,7 +742,7 @@ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: external
|
|
|
482
742
|
const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
|
|
483
743
|
scrollView.current?.scrollToOffset({ offset, animated: true });
|
|
484
744
|
}, [isHorizontal, contentInset.top, pullSearchHeight]);
|
|
485
|
-
const handleContentSizeChange =
|
|
745
|
+
const handleContentSizeChange = useCallback4(
|
|
486
746
|
(w, h) => {
|
|
487
747
|
if (onContentSizeChange) onContentSizeChange(w, h);
|
|
488
748
|
},
|
|
@@ -494,23 +754,27 @@ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: external
|
|
|
494
754
|
const detectorGesture = gesture !== void 0 ? combinedGesture : void 0;
|
|
495
755
|
const content = /* @__PURE__ */ jsxs3(View3, { style: containerStyle, children: [
|
|
496
756
|
/* @__PURE__ */ jsx5(
|
|
497
|
-
|
|
757
|
+
RNFlatList,
|
|
498
758
|
{
|
|
499
759
|
...props,
|
|
500
760
|
contentContainerStyle,
|
|
501
761
|
contentInset,
|
|
762
|
+
contentInsetAdjustmentBehavior: "never",
|
|
502
763
|
contentOffset,
|
|
503
|
-
data,
|
|
764
|
+
data: cols > 1 ? rowData : data,
|
|
504
765
|
horizontal: isHorizontal,
|
|
505
766
|
initialNumToRender,
|
|
767
|
+
keyExtractor: cols > 1 ? rowKeyExtractor : keyExtractor,
|
|
506
768
|
ListHeaderComponent: activeListHeader,
|
|
507
769
|
maxToRenderPerBatch,
|
|
508
770
|
onContentSizeChange: handleContentSizeChange,
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
771
|
+
onMomentumScrollBegin: scrollHandler.onMomentumScrollBegin,
|
|
772
|
+
onMomentumScrollEnd,
|
|
773
|
+
onScroll: scrollHandler.onScroll,
|
|
774
|
+
onScrollBeginDrag,
|
|
775
|
+
onScrollEndDrag,
|
|
513
776
|
pagingEnabled,
|
|
777
|
+
renderItem: cols > 1 ? rowRenderItem : renderItem,
|
|
514
778
|
ref: (el) => {
|
|
515
779
|
if (externalRef) externalRef.current = el;
|
|
516
780
|
scrollView.current = el;
|
|
@@ -529,22 +793,26 @@ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: external
|
|
|
529
793
|
] });
|
|
530
794
|
return detectorGesture ? /* @__PURE__ */ jsx5(GestureDetector2, { gesture: detectorGesture, children: content }) : content;
|
|
531
795
|
};
|
|
532
|
-
var
|
|
796
|
+
var defaultKeyExtractor = (item, index) => {
|
|
797
|
+
const key = item?.key ?? item?.id;
|
|
798
|
+
return key != null ? String(key) : String(index);
|
|
799
|
+
};
|
|
800
|
+
var styles4 = { measureContainer: { left: 0, opacity: 0, position: "absolute", right: 0, top: -9999 }, row: { flexDirection: "row" } };
|
|
533
801
|
var FlatList = memo2(FlatListInner);
|
|
534
802
|
|
|
535
803
|
// src/PullSearch.tsx
|
|
536
|
-
import { forwardRef, useCallback as
|
|
804
|
+
import { forwardRef, useCallback as useCallback5, useContext as useContext8, useEffect as useEffect3, useImperativeHandle, useRef as useRef5, useState as useState4 } from "react";
|
|
537
805
|
import { StyleSheet as StyleSheet4 } from "react-native";
|
|
538
806
|
import { Searchbar, useTheme as useTheme2 } from "react-native-paper";
|
|
539
|
-
import
|
|
807
|
+
import Animated3, { Extrapolation, interpolate, runOnJS as runOnJS3, useAnimatedReaction, useAnimatedStyle as useAnimatedStyle3 } from "react-native-reanimated";
|
|
540
808
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
541
809
|
var PullSearch = forwardRef(function PullSearch2({ debounce, onChangeText, onHeightChange, placeholder, value: propValue }, ref) {
|
|
542
|
-
const { headerHeight, scrollPosition } =
|
|
810
|
+
const { headerHeight, scrollPosition } = useContext8(ScrollViewContext);
|
|
543
811
|
const theme = useTheme2();
|
|
544
|
-
const inputRef =
|
|
545
|
-
const [barHeight, setBarHeight] =
|
|
546
|
-
const [value, setValue] =
|
|
547
|
-
const prevPropValueRef =
|
|
812
|
+
const inputRef = useRef5(null);
|
|
813
|
+
const [barHeight, setBarHeight] = useState4(0);
|
|
814
|
+
const [value, setValue] = useState4(propValue ?? "");
|
|
815
|
+
const prevPropValueRef = useRef5(propValue);
|
|
548
816
|
useEffect3(() => {
|
|
549
817
|
if (prevPropValueRef.current === propValue) return;
|
|
550
818
|
prevPropValueRef.current = propValue;
|
|
@@ -554,22 +822,22 @@ var PullSearch = forwardRef(function PullSearch2({ debounce, onChangeText, onHei
|
|
|
554
822
|
blur: () => inputRef.current?.blur(),
|
|
555
823
|
focus: () => inputRef.current?.focus()
|
|
556
824
|
}));
|
|
557
|
-
const blurInput =
|
|
825
|
+
const blurInput = useCallback5(() => inputRef.current?.blur(), []);
|
|
558
826
|
useAnimatedReaction(
|
|
559
827
|
() => {
|
|
560
828
|
if (barHeight === 0) return false;
|
|
561
|
-
return scrollPosition.value >= -headerHeight + barHeight;
|
|
829
|
+
return scrollPosition.value >= -(headerHeight ?? 0) + barHeight;
|
|
562
830
|
},
|
|
563
831
|
(isHidden, wasHidden) => {
|
|
564
832
|
if (isHidden && !wasHidden) runOnJS3(blurInput)();
|
|
565
833
|
},
|
|
566
834
|
[barHeight, headerHeight, blurInput]
|
|
567
835
|
);
|
|
568
|
-
const handleClear =
|
|
836
|
+
const handleClear = useCallback5(() => {
|
|
569
837
|
setValue("");
|
|
570
838
|
onChangeText("");
|
|
571
839
|
}, [onChangeText]);
|
|
572
|
-
const handleLayout =
|
|
840
|
+
const handleLayout = useCallback5(
|
|
573
841
|
({
|
|
574
842
|
nativeEvent: {
|
|
575
843
|
layout: { height }
|
|
@@ -590,11 +858,12 @@ var PullSearch = forwardRef(function PullSearch2({ debounce, onChangeText, onHei
|
|
|
590
858
|
}, [debounce, onChangeText, value]);
|
|
591
859
|
const animatedStyle = useAnimatedStyle3(() => {
|
|
592
860
|
if (barHeight === 0) return { opacity: 0 };
|
|
593
|
-
const
|
|
594
|
-
const
|
|
861
|
+
const h = headerHeight ?? 0;
|
|
862
|
+
const showY = -h;
|
|
863
|
+
const hideY = -h + barHeight;
|
|
595
864
|
return { opacity: interpolate(scrollPosition.value, [showY, hideY], [1, 0], Extrapolation.CLAMP) };
|
|
596
865
|
}, [barHeight, headerHeight]);
|
|
597
|
-
return /* @__PURE__ */ jsx6(
|
|
866
|
+
return /* @__PURE__ */ jsx6(Animated3.View, { onLayout: handleLayout, style: [styles5.container, animatedStyle], children: /* @__PURE__ */ jsx6(Searchbar, { autoCorrect: false, onChangeText: (text) => setValue((text || "").trimStart()), onClearIconPress: handleClear, placeholder, placeholderTextColor: theme.colors.onSurfaceVariant, ref: inputRef, spellCheck: false, style: styles5.input, value }) });
|
|
598
867
|
});
|
|
599
868
|
var styles5 = StyleSheet4.create({
|
|
600
869
|
container: { paddingVertical: 8 },
|
|
@@ -1095,6 +1364,24 @@ var objectTraps = {
|
|
|
1095
1364
|
get(state, prop) {
|
|
1096
1365
|
if (prop === DRAFT_STATE)
|
|
1097
1366
|
return state;
|
|
1367
|
+
if (prop === "constructor" || prop === "__proto__") {
|
|
1368
|
+
const source2 = latest(state);
|
|
1369
|
+
const value2 = source2[prop];
|
|
1370
|
+
return new Proxy(value2 || {}, {
|
|
1371
|
+
get: (target, key) => {
|
|
1372
|
+
if (key === "__proto__" || key === "prototype") {
|
|
1373
|
+
return Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
1374
|
+
}
|
|
1375
|
+
return Reflect.get(target, key);
|
|
1376
|
+
},
|
|
1377
|
+
set: () => {
|
|
1378
|
+
return true;
|
|
1379
|
+
},
|
|
1380
|
+
apply: (target, thisArg, args) => {
|
|
1381
|
+
return Reflect.apply(target, thisArg, args);
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1098
1385
|
let arrayPlugin = state.scope_.arrayMethodsPlugin_;
|
|
1099
1386
|
const isArrayWithStringProp = state.type_ === 1 && typeof prop === "string";
|
|
1100
1387
|
if (isArrayWithStringProp) {
|
|
@@ -1124,12 +1411,18 @@ var objectTraps = {
|
|
|
1124
1411
|
return value;
|
|
1125
1412
|
},
|
|
1126
1413
|
has(state, prop) {
|
|
1414
|
+
if (prop === "constructor" || prop === "__proto__" || prop === "prototype") {
|
|
1415
|
+
return false;
|
|
1416
|
+
}
|
|
1127
1417
|
return prop in latest(state);
|
|
1128
1418
|
},
|
|
1129
1419
|
ownKeys(state) {
|
|
1130
1420
|
return Reflect.ownKeys(latest(state));
|
|
1131
1421
|
},
|
|
1132
1422
|
set(state, prop, value) {
|
|
1423
|
+
if (prop === "constructor" || prop === "__proto__" || prop === "prototype") {
|
|
1424
|
+
return true;
|
|
1425
|
+
}
|
|
1133
1426
|
const desc = getDescriptorFromProto(latest(state), prop);
|
|
1134
1427
|
if (desc?.set) {
|
|
1135
1428
|
desc.set.call(state.draft_, value);
|
|
@@ -1149,7 +1442,7 @@ var objectTraps = {
|
|
|
1149
1442
|
markChanged(state);
|
|
1150
1443
|
}
|
|
1151
1444
|
if (state.copy_[prop] === value && // special case: handle new props with value 'undefined'
|
|
1152
|
-
(value !== void 0 || prop
|
|
1445
|
+
(value !== void 0 || has(state.copy_, prop, state.type_)) || // special case: NaN
|
|
1153
1446
|
Number.isNaN(value) && Number.isNaN(state.copy_[prop]))
|
|
1154
1447
|
return true;
|
|
1155
1448
|
state.copy_[prop] = value;
|
|
@@ -2165,16 +2458,26 @@ var scrollViewActions = slice.actions;
|
|
|
2165
2458
|
var scrollViewReducer = slice.reducer;
|
|
2166
2459
|
|
|
2167
2460
|
// src/ScrollView.tsx
|
|
2168
|
-
import { memo as memo3, useCallback as
|
|
2461
|
+
import { memo as memo3, useCallback as useCallback6, useContext as useContext9, useLayoutEffect as useLayoutEffect4, useMemo as useMemo4, useRef as useRef6 } from "react";
|
|
2169
2462
|
import { View as View4 } from "react-native";
|
|
2170
2463
|
import { Gesture as Gesture3, GestureDetector as GestureDetector3 } from "react-native-gesture-handler";
|
|
2171
|
-
import
|
|
2464
|
+
import Animated4, { runOnUI as runOnUI2, useSharedValue as useSharedValue5 } from "react-native-reanimated";
|
|
2172
2465
|
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2173
2466
|
var ScrollViewInner = ({ chipProps, chipThreshold, children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }) => {
|
|
2174
|
-
const scrollView =
|
|
2467
|
+
const scrollView = useRef6(null);
|
|
2175
2468
|
const isHorizontal = horizontal === true;
|
|
2176
2469
|
const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, isHorizontal, keyboardAware, pullSearchHeight, style });
|
|
2177
|
-
const
|
|
2470
|
+
const { listGeneration, onListUnmount } = useContext9(ScrollViewContext);
|
|
2471
|
+
const capturedGeneration = useSharedValue5(-1);
|
|
2472
|
+
useLayoutEffect4(() => {
|
|
2473
|
+
const generation = listGeneration.value;
|
|
2474
|
+
runOnUI2((gen) => {
|
|
2475
|
+
"worklet";
|
|
2476
|
+
capturedGeneration.value = gen;
|
|
2477
|
+
})(generation);
|
|
2478
|
+
}, [capturedGeneration, listGeneration]);
|
|
2479
|
+
useLayoutEffect4(() => () => onListUnmount(), [onListUnmount]);
|
|
2480
|
+
const scrollTo = useCallback6((offset, animated) => {
|
|
2178
2481
|
scrollView.current?.scrollTo({ y: offset, animated });
|
|
2179
2482
|
}, []);
|
|
2180
2483
|
const { handleMomentumScrollEnd, handleScrollBeginDrag, handleScrollEndDrag } = useScrollInit({
|
|
@@ -2184,12 +2487,8 @@ var ScrollViewInner = ({ chipProps, chipThreshold, children, footerFixed: footer
|
|
|
2184
2487
|
pullSearchHeight,
|
|
2185
2488
|
scrollTo
|
|
2186
2489
|
});
|
|
2187
|
-
const
|
|
2188
|
-
|
|
2189
|
-
scrollTo(-contentInset.top + pullSearchHeight, true);
|
|
2190
|
-
}, [contentInset.top, pullSearchHeight, scrollTo]);
|
|
2191
|
-
const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
|
|
2192
|
-
const handleScrollToTop = useCallback5(() => {
|
|
2490
|
+
const handleScroll = useScrollHandler({ capturedGeneration, chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, listGeneration });
|
|
2491
|
+
const handleScrollToTop = useCallback6(() => {
|
|
2193
2492
|
if (isHorizontal) {
|
|
2194
2493
|
scrollView.current?.scrollTo({ x: 0, animated: true });
|
|
2195
2494
|
return;
|
|
@@ -2203,7 +2502,7 @@ var ScrollViewInner = ({ chipProps, chipThreshold, children, footerFixed: footer
|
|
|
2203
2502
|
const detectorGesture = gesture !== void 0 ? combinedGesture : void 0;
|
|
2204
2503
|
const content = /* @__PURE__ */ jsxs4(View4, { style: containerStyle, children: [
|
|
2205
2504
|
/* @__PURE__ */ jsx7(
|
|
2206
|
-
|
|
2505
|
+
Animated4.ScrollView,
|
|
2207
2506
|
{
|
|
2208
2507
|
...props,
|
|
2209
2508
|
contentInset,
|
|
@@ -2229,13 +2528,13 @@ var ScrollView = memo3(ScrollViewInner);
|
|
|
2229
2528
|
|
|
2230
2529
|
// src/ScrollViewFooter.tsx
|
|
2231
2530
|
import { BlurView as BlurView2 } from "@rific/auto-paper";
|
|
2232
|
-
import { useContext as
|
|
2531
|
+
import { useContext as useContext10, useEffect as useEffect4 } from "react";
|
|
2233
2532
|
import { StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
2234
|
-
import
|
|
2533
|
+
import Animated5, { useAnimatedStyle as useAnimatedStyle4 } from "react-native-reanimated";
|
|
2235
2534
|
import { useSafeAreaInsets as useSafeAreaInsets3 } from "react-native-safe-area-context";
|
|
2236
2535
|
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2237
2536
|
var ScrollViewFooter = ({ children, style }) => {
|
|
2238
|
-
const { blur, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared } =
|
|
2537
|
+
const { blur, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared } = useContext10(ScrollViewContext);
|
|
2239
2538
|
const insets = useSafeAreaInsets3();
|
|
2240
2539
|
useEffect4(
|
|
2241
2540
|
() => () => {
|
|
@@ -2257,7 +2556,7 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
2257
2556
|
if (effective <= 0) return { transform: [{ translateY: 0 }] };
|
|
2258
2557
|
return { transform: [{ translateY: Math.min(effective, footerHeight) }] };
|
|
2259
2558
|
}, [footerHeight, footerFixed]);
|
|
2260
|
-
return /* @__PURE__ */ jsxs5(
|
|
2559
|
+
return /* @__PURE__ */ jsxs5(Animated5.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, footerStyle], children: [
|
|
2261
2560
|
footerHeight > 0 && /* @__PURE__ */ jsx8(BlurView2, { blur, style: StyleSheet5.absoluteFill }),
|
|
2262
2561
|
/* @__PURE__ */ jsx8(View5, { style: [styles6.row, { paddingBottom: insets.bottom }, style], children })
|
|
2263
2562
|
] });
|
|
@@ -2269,16 +2568,16 @@ var styles6 = StyleSheet5.create({
|
|
|
2269
2568
|
|
|
2270
2569
|
// src/ScrollViewHeader.tsx
|
|
2271
2570
|
import { BlurView as BlurView3 } from "@rific/auto-paper";
|
|
2272
|
-
import { useContext as
|
|
2571
|
+
import { useContext as useContext11 } from "react";
|
|
2273
2572
|
import { StyleSheet as StyleSheet6, Text, View as View6 } from "react-native";
|
|
2274
2573
|
import { Appbar, ProgressBar, Surface, useTheme as useTheme3 } from "react-native-paper";
|
|
2275
|
-
import
|
|
2574
|
+
import Animated6, { useAnimatedStyle as useAnimatedStyle5 } from "react-native-reanimated";
|
|
2276
2575
|
import { useSafeAreaInsets as useSafeAreaInsets4 } from "react-native-safe-area-context";
|
|
2277
|
-
import { Fragment as
|
|
2576
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2278
2577
|
var ActionBg = ({ blur, style }) => blur ? /* @__PURE__ */ jsx9(View6, { style: [StyleSheet6.absoluteFill, styles7.actionBg, style], children: /* @__PURE__ */ jsx9(BlurView3, { blur: true, style: StyleSheet6.absoluteFill }) }) : /* @__PURE__ */ jsx9(View6, { style: [StyleSheet6.absoluteFill, styles7.actionBg, style], pointerEvents: "none", children: /* @__PURE__ */ jsx9(Surface, { style: StyleSheet6.absoluteFill, elevation: 1, children: null }) });
|
|
2279
2578
|
var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionFixed, caption, centerContent, children, iconSize, style, title, topInset = true, trailingAction, trailingActionFixed = true }) => {
|
|
2280
|
-
const { blur, headerHeight, headerFixed, headerOffset, progress, progressing, pullSearchHeightShared, scrollPosition, setHeaderHeight, snapBackHeaderShared } =
|
|
2281
|
-
const { settings } =
|
|
2579
|
+
const { blur, headerHeight, headerFixed, headerOffset, progress, progressing, pullSearchHeightShared, scrollPosition, setHeaderHeight, snapBackHeaderShared } = useContext11(ScrollViewContext);
|
|
2580
|
+
const { settings } = useContext11(ScrollViewSettingsContext);
|
|
2282
2581
|
const effectiveBackActionFixed = backActionFixed ?? settings.backActionFixed;
|
|
2283
2582
|
const insets = useSafeAreaInsets4();
|
|
2284
2583
|
const theme = useTheme3();
|
|
@@ -2293,20 +2592,22 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionFi
|
|
|
2293
2592
|
const translateStyle = useAnimatedStyle5(() => {
|
|
2294
2593
|
if (headerFixed) return { transform: [{ translateY: 0 }] };
|
|
2295
2594
|
if (snapBackHeaderShared.value) return { transform: [{ translateY: headerOffset.value }] };
|
|
2296
|
-
const effective = scrollPosition.value + headerHeight - pullSearchHeightShared.value;
|
|
2595
|
+
const effective = scrollPosition.value + (headerHeight ?? 0) - pullSearchHeightShared.value;
|
|
2297
2596
|
if (effective <= 0) return { transform: [{ translateY: 0 }] };
|
|
2298
2597
|
return { transform: [{ translateY: -effective }] };
|
|
2299
2598
|
}, [headerFixed, headerHeight]);
|
|
2300
2599
|
const blurStyle = useAnimatedStyle5(() => {
|
|
2301
2600
|
if (!headerHeight) return { height: 0 };
|
|
2302
2601
|
if (headerFixed) return { height: headerHeight };
|
|
2303
|
-
const
|
|
2304
|
-
|
|
2602
|
+
const h = headerHeight ?? 0;
|
|
2603
|
+
const translateY = snapBackHeaderShared.value ? headerOffset.value : -Math.max(0, scrollPosition.value + h - pullSearchHeightShared.value);
|
|
2604
|
+
return { height: Math.max(h + translateY, top) };
|
|
2305
2605
|
}, [headerFixed, headerHeight, top]);
|
|
2306
2606
|
const progressStyle = useAnimatedStyle5(() => {
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2607
|
+
const h = headerHeight ?? 0;
|
|
2608
|
+
if (headerFixed) return { top: h };
|
|
2609
|
+
const slide = snapBackHeaderShared.value ? -headerOffset.value : Math.max(0, scrollPosition.value + h - pullSearchHeightShared.value);
|
|
2610
|
+
return { top: Math.max(h - slide, top) };
|
|
2310
2611
|
}, [headerFixed, headerHeight, top]);
|
|
2311
2612
|
const actionMargin = 4;
|
|
2312
2613
|
const contentMinHeight = actionSize + 2 * actionMargin;
|
|
@@ -2315,32 +2616,31 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionFi
|
|
|
2315
2616
|
const actionShadow = { borderRadius: actionSize / 2, elevation: 2, shadowColor: "#000", shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.15, shadowRadius: 2 };
|
|
2316
2617
|
const leadingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", left: actionMargin, position: "absolute", top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
|
|
2317
2618
|
const trailingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", position: "absolute", right: actionMargin, top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
|
|
2318
|
-
return /* @__PURE__ */ jsxs6(
|
|
2319
|
-
/* @__PURE__ */ jsx9(
|
|
2320
|
-
/* @__PURE__ */ jsxs6(
|
|
2321
|
-
/* @__PURE__ */ jsx9(View6, { style: [{ paddingTop: top }, style], children: /* @__PURE__ */ jsxs6(View6, { style: [styles7.content, { minHeight: contentMinHeight }], children: [
|
|
2619
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2620
|
+
/* @__PURE__ */ jsx9(Animated6.View, { pointerEvents: "none", style: [styles7.blur, blurStyle], children: headerHeight !== null && headerHeight > 0 && /* @__PURE__ */ jsx9(BlurView3, { blur, style: [styles7.blurInner, { height: headerHeight }] }) }),
|
|
2621
|
+
/* @__PURE__ */ jsxs6(Animated6.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [headerHeight === null ? styles7.headerInit : styles7.header, translateStyle], children: [
|
|
2622
|
+
/* @__PURE__ */ jsx9(View6, { style: [{ paddingTop: top }, style], children: children ?? /* @__PURE__ */ jsxs6(View6, { style: [styles7.content, { minHeight: contentMinHeight }], children: [
|
|
2322
2623
|
/* @__PURE__ */ jsx9(View6, { style: styles7.side }),
|
|
2323
2624
|
/* @__PURE__ */ jsx9(View6, { style: styles7.spacer }),
|
|
2324
|
-
/* @__PURE__ */ jsx9(View6, { style: styles7.
|
|
2325
|
-
(centerContent || title || caption) && /* @__PURE__ */ jsx9(View6, { style: [StyleSheet6.absoluteFill, styles7.titleContainer], pointerEvents: centerContent ? "box-none" : "none", children: centerContent ?? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
2625
|
+
(centerContent || title || caption) && /* @__PURE__ */ jsx9(View6, { style: [StyleSheet6.absoluteFill, styles7.titleContainer], pointerEvents: centerContent ? "box-none" : "none", children: centerContent ?? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2326
2626
|
title && /* @__PURE__ */ jsx9(Text, { numberOfLines: 1, style: [styles7.title, { color: theme.colors.onSurface }], children: title }),
|
|
2327
2627
|
caption && /* @__PURE__ */ jsx9(Text, { numberOfLines: 1, style: [styles7.caption, { color: theme.colors.onSurfaceVariant }], children: caption })
|
|
2328
2628
|
] }) })
|
|
2329
2629
|
] }) }),
|
|
2330
2630
|
!blur && /* @__PURE__ */ jsx9(View6, { style: [styles7.divider, { backgroundColor: theme.colors.outlineVariant }] })
|
|
2331
2631
|
] }),
|
|
2332
|
-
/* @__PURE__ */ jsx9(
|
|
2333
|
-
backAction && (effectiveBackActionFixed ? /* @__PURE__ */ jsxs6(
|
|
2632
|
+
/* @__PURE__ */ jsx9(Animated6.View, { pointerEvents: "none", style: [styles7.progress, progressStyle], children: /* @__PURE__ */ jsx9(ProgressBar, { indeterminate: progress === null, visible: progressing, progress: progress ?? void 0 }) }),
|
|
2633
|
+
backAction && (effectiveBackActionFixed ? /* @__PURE__ */ jsxs6(Animated6.View, { style: leadingStyle, children: [
|
|
2334
2634
|
/* @__PURE__ */ jsx9(ActionBg, { blur, style: actionStyle }),
|
|
2335
2635
|
/* @__PURE__ */ jsx9(Appbar.BackAction, { onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle })
|
|
2336
|
-
] }) : /* @__PURE__ */ jsxs6(
|
|
2636
|
+
] }) : /* @__PURE__ */ jsxs6(Animated6.View, { style: [leadingStyle, translateStyle], children: [
|
|
2337
2637
|
/* @__PURE__ */ jsx9(ActionBg, { blur, style: actionStyle }),
|
|
2338
2638
|
/* @__PURE__ */ jsx9(Appbar.BackAction, { onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle })
|
|
2339
2639
|
] })),
|
|
2340
2640
|
trailingAction && (trailingActionFixed ? /* @__PURE__ */ jsxs6(View6, { style: trailingStyle, children: [
|
|
2341
2641
|
/* @__PURE__ */ jsx9(ActionBg, { blur, style: actionStyle }),
|
|
2342
2642
|
trailingAction
|
|
2343
|
-
] }) : /* @__PURE__ */ jsxs6(
|
|
2643
|
+
] }) : /* @__PURE__ */ jsxs6(Animated6.View, { style: [trailingStyle, translateStyle], children: [
|
|
2344
2644
|
/* @__PURE__ */ jsx9(ActionBg, { blur, style: actionStyle }),
|
|
2345
2645
|
trailingAction
|
|
2346
2646
|
] }))
|
|
@@ -2364,62 +2664,77 @@ var styles7 = StyleSheet6.create({
|
|
|
2364
2664
|
|
|
2365
2665
|
// src/ScrollViewProvider.tsx
|
|
2366
2666
|
import { useBlur } from "@rific/auto-paper";
|
|
2367
|
-
import { useCallback as
|
|
2667
|
+
import { useCallback as useCallback7, useContext as useContext12, useEffect as useEffect5, useMemo as useMemo5, useRef as useRef7, useState as useState5 } from "react";
|
|
2368
2668
|
import { Dimensions as Dimensions3 } from "react-native";
|
|
2369
|
-
import { useSharedValue as
|
|
2669
|
+
import { useSharedValue as useSharedValue6 } from "react-native-reanimated";
|
|
2370
2670
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2371
2671
|
var ScrollViewProvider = ({ blur, children, fixed = false, footerFixed, headerFixed, snapBack, snapBackFooter, snapBackHeader, tabBarHeight = 60 }) => {
|
|
2372
|
-
const { settings } =
|
|
2672
|
+
const { settings } = useContext12(ScrollViewSettingsContext);
|
|
2373
2673
|
const effectiveBlur = useBlur(blur);
|
|
2374
2674
|
const effectiveSnapBack = snapBack ?? settings.snapBack;
|
|
2375
2675
|
const effectiveSnapBackHeader = snapBackHeader ?? settings.snapBackHeader;
|
|
2376
2676
|
const effectiveSnapBackFooter = snapBackFooter ?? settings.snapBackFooter;
|
|
2377
|
-
const [headerHeight, setHeaderHeightState] =
|
|
2378
|
-
const [footerHeight, setFooterHeightState] =
|
|
2379
|
-
const [progress, setProgress] =
|
|
2380
|
-
const [progressing, setProgressing] =
|
|
2381
|
-
const scrollPosition =
|
|
2382
|
-
const
|
|
2383
|
-
const
|
|
2384
|
-
const
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2387
|
-
const
|
|
2388
|
-
const
|
|
2677
|
+
const [headerHeight, setHeaderHeightState] = useState5(null);
|
|
2678
|
+
const [footerHeight, setFooterHeightState] = useState5(0);
|
|
2679
|
+
const [progress, setProgress] = useState5(null);
|
|
2680
|
+
const [progressing, setProgressing] = useState5(false);
|
|
2681
|
+
const scrollPosition = useSharedValue6(0);
|
|
2682
|
+
const listGeneration = useSharedValue6(0);
|
|
2683
|
+
const jsListGeneration = useRef7(0);
|
|
2684
|
+
const headerHeightShared = useSharedValue6(0);
|
|
2685
|
+
const footerHeightShared = useSharedValue6(0);
|
|
2686
|
+
const headerOffset = useSharedValue6(0);
|
|
2687
|
+
const footerOffset = useSharedValue6(0);
|
|
2688
|
+
const pullSearchHeightShared = useSharedValue6(0);
|
|
2689
|
+
const snapBackHeaderShared = useSharedValue6(false);
|
|
2690
|
+
const snapBackFooterShared = useSharedValue6(false);
|
|
2389
2691
|
useEffect5(() => {
|
|
2390
2692
|
snapBackHeaderShared.value = effectiveSnapBackHeader ?? effectiveSnapBack;
|
|
2391
2693
|
snapBackFooterShared.value = effectiveSnapBackFooter ?? effectiveSnapBack;
|
|
2392
2694
|
}, [effectiveSnapBack, effectiveSnapBackFooter, effectiveSnapBackHeader, snapBackFooterShared, snapBackHeaderShared]);
|
|
2393
|
-
const setHeaderHeight =
|
|
2695
|
+
const setHeaderHeight = useCallback7(
|
|
2394
2696
|
(h) => {
|
|
2395
2697
|
setHeaderHeightState(h);
|
|
2396
|
-
headerHeightShared.value = h;
|
|
2698
|
+
headerHeightShared.value = h ?? 0;
|
|
2397
2699
|
},
|
|
2398
2700
|
[headerHeightShared]
|
|
2399
2701
|
);
|
|
2400
|
-
const
|
|
2702
|
+
const onListUnmount = useCallback7(() => {
|
|
2703
|
+
listGeneration.value += 1;
|
|
2704
|
+
}, [listGeneration]);
|
|
2705
|
+
const onJsListUnmount = useCallback7(() => {
|
|
2706
|
+
jsListGeneration.current += 1;
|
|
2707
|
+
}, []);
|
|
2708
|
+
useEffect5(() => {
|
|
2709
|
+
if (!__DEV__ || headerHeight !== null) return;
|
|
2710
|
+
const timeout = setTimeout(() => {
|
|
2711
|
+
console.warn("[scroll-view] No ScrollViewHeader ever measured inside this ScrollViewProvider \u2014 scroll content stays hidden (opacity: 0) until one does. Render a <ScrollViewHeader> (it can be empty / zero height) inside this provider.");
|
|
2712
|
+
}, 3e3);
|
|
2713
|
+
return () => clearTimeout(timeout);
|
|
2714
|
+
}, [headerHeight]);
|
|
2715
|
+
const setFooterHeight = useCallback7(
|
|
2401
2716
|
(h) => {
|
|
2402
2717
|
setFooterHeightState(h);
|
|
2403
2718
|
footerHeightShared.value = h;
|
|
2404
2719
|
},
|
|
2405
2720
|
[footerHeightShared]
|
|
2406
2721
|
);
|
|
2407
|
-
const scrollHeight = useMemo5(() => Dimensions3.get("window").height - headerHeight - footerHeight, [headerHeight, footerHeight]);
|
|
2722
|
+
const scrollHeight = useMemo5(() => Dimensions3.get("window").height - (headerHeight ?? 0) - footerHeight, [headerHeight, footerHeight]);
|
|
2408
2723
|
const effectiveHeaderFixed = fixed || (headerFixed ?? settings.headerFixed);
|
|
2409
2724
|
const effectiveFooterFixed = fixed || (footerFixed ?? settings.footerFixed);
|
|
2410
|
-
const value = useMemo5(() => ({ blur: effectiveBlur, footerHeight, footerHeightShared, footerFixed: effectiveFooterFixed, footerOffset, headerHeight, headerHeightShared, headerFixed: effectiveHeaderFixed, headerOffset, progress, pullSearchHeightShared, progressing, scrollHeight, scrollPosition, setFooterHeight, setHeaderHeight, setProgress, setProgressing, snapBackFooterShared, snapBackHeaderShared, tabBarHeight }), [effectiveBlur, effectiveFooterFixed, effectiveHeaderFixed, footerHeight, footerHeightShared, footerOffset, headerHeight, headerHeightShared, headerOffset, progress, pullSearchHeightShared, progressing, scrollHeight, scrollPosition, setFooterHeight, setHeaderHeight, snapBackFooterShared, snapBackHeaderShared, tabBarHeight]);
|
|
2725
|
+
const value = useMemo5(() => ({ blur: effectiveBlur, footerHeight, footerHeightShared, footerFixed: effectiveFooterFixed, footerOffset, headerHeight, headerHeightShared, headerFixed: effectiveHeaderFixed, headerOffset, jsListGeneration, listGeneration, onJsListUnmount, onListUnmount, progress, pullSearchHeightShared, progressing, scrollHeight, scrollPosition, setFooterHeight, setHeaderHeight, setProgress, setProgressing, snapBackFooterShared, snapBackHeaderShared, tabBarHeight }), [effectiveBlur, effectiveFooterFixed, effectiveHeaderFixed, footerHeight, footerHeightShared, footerOffset, headerHeight, headerHeightShared, headerOffset, jsListGeneration, listGeneration, onJsListUnmount, onListUnmount, progress, pullSearchHeightShared, progressing, scrollHeight, scrollPosition, setFooterHeight, setHeaderHeight, snapBackFooterShared, snapBackHeaderShared, tabBarHeight]);
|
|
2411
2726
|
return /* @__PURE__ */ jsx10(ScrollViewContext.Provider, { value, children });
|
|
2412
2727
|
};
|
|
2413
2728
|
|
|
2414
2729
|
// src/ScrollViewSettingsProvider.tsx
|
|
2415
|
-
import { useCallback as
|
|
2730
|
+
import { useCallback as useCallback8, useMemo as useMemo6, useState as useState6 } from "react";
|
|
2416
2731
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2417
2732
|
var ScrollViewSettingsProvider = ({ children, onChange, initialValue }) => {
|
|
2418
|
-
const [settings, setSettings] =
|
|
2733
|
+
const [settings, setSettings] = useState6(() => ({
|
|
2419
2734
|
...defaultScrollViewSettings,
|
|
2420
2735
|
...initialValue
|
|
2421
2736
|
}));
|
|
2422
|
-
const set2 =
|
|
2737
|
+
const set2 = useCallback8(
|
|
2423
2738
|
(patch) => {
|
|
2424
2739
|
setSettings((prev) => {
|
|
2425
2740
|
const next = { ...prev, ...patch };
|
|
@@ -2434,27 +2749,27 @@ var ScrollViewSettingsProvider = ({ children, onChange, initialValue }) => {
|
|
|
2434
2749
|
};
|
|
2435
2750
|
|
|
2436
2751
|
// src/SectionList.tsx
|
|
2437
|
-
import { memo as memo4, useCallback as
|
|
2752
|
+
import { memo as memo4, useCallback as useCallback10, useContext as useContext14, useEffect as useEffect6, useLayoutEffect as useLayoutEffect6, useMemo as useMemo7, useRef as useRef9 } from "react";
|
|
2438
2753
|
import { Dimensions as Dimensions4, SectionList as RNSectionList, View as View7 } from "react-native";
|
|
2439
2754
|
import { Gesture as Gesture4, GestureDetector as GestureDetector4 } from "react-native-gesture-handler";
|
|
2440
|
-
import
|
|
2755
|
+
import Animated7, { runOnUI as runOnUI3, useSharedValue as useSharedValue8 } from "react-native-reanimated";
|
|
2441
2756
|
|
|
2442
2757
|
// src/internal/useStickyHeaders.ts
|
|
2443
|
-
import { useCallback as
|
|
2444
|
-
import { runOnJS as runOnJS4, useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as
|
|
2758
|
+
import { useCallback as useCallback9, useContext as useContext13, useLayoutEffect as useLayoutEffect5, useRef as useRef8, useState as useState7 } from "react";
|
|
2759
|
+
import { runOnJS as runOnJS4, useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as useSharedValue7 } from "react-native-reanimated";
|
|
2445
2760
|
import { useSafeAreaInsets as useSafeAreaInsets5 } from "react-native-safe-area-context";
|
|
2446
2761
|
function useStickyHeaders(headerFixed, enabled) {
|
|
2447
|
-
const { headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } =
|
|
2762
|
+
const { headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } = useContext13(ScrollViewContext);
|
|
2448
2763
|
const insetsTop = useSafeAreaInsets5().top;
|
|
2449
|
-
const sectionYPositions =
|
|
2450
|
-
const sectionHeights =
|
|
2451
|
-
const [activeIndex, setActiveIndex] =
|
|
2452
|
-
const contentIndexShared =
|
|
2453
|
-
|
|
2764
|
+
const sectionYPositions = useSharedValue7([]);
|
|
2765
|
+
const sectionHeights = useSharedValue7([]);
|
|
2766
|
+
const [activeIndex, setActiveIndex] = useState7(-1);
|
|
2767
|
+
const contentIndexShared = useSharedValue7(-1);
|
|
2768
|
+
useLayoutEffect5(() => {
|
|
2454
2769
|
contentIndexShared.value = activeIndex;
|
|
2455
2770
|
}, [activeIndex, contentIndexShared]);
|
|
2456
|
-
const positionsCache =
|
|
2457
|
-
const heightsCache =
|
|
2771
|
+
const positionsCache = useRef8([]);
|
|
2772
|
+
const heightsCache = useRef8([]);
|
|
2458
2773
|
useAnimatedReaction2(
|
|
2459
2774
|
() => {
|
|
2460
2775
|
if (!enabled) return -1;
|
|
@@ -2526,7 +2841,7 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
2526
2841
|
}
|
|
2527
2842
|
return { opacity: 1, top: 0, transform: [{ translateY }] };
|
|
2528
2843
|
}, [enabled, headerFixed, insetsTop]);
|
|
2529
|
-
const measureHeader =
|
|
2844
|
+
const measureHeader = useCallback9(
|
|
2530
2845
|
(index, pageY, height) => {
|
|
2531
2846
|
const contentY = pageY + scrollPosition.value;
|
|
2532
2847
|
positionsCache.current[index] = contentY;
|
|
@@ -2536,7 +2851,7 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
2536
2851
|
},
|
|
2537
2852
|
[scrollPosition, sectionHeights, sectionYPositions]
|
|
2538
2853
|
);
|
|
2539
|
-
const resetPositions =
|
|
2854
|
+
const resetPositions = useCallback9(
|
|
2540
2855
|
(count) => {
|
|
2541
2856
|
positionsCache.current = Array.from({ length: count }, () => -1);
|
|
2542
2857
|
sectionYPositions.value = positionsCache.current.slice();
|
|
@@ -2549,18 +2864,27 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
2549
2864
|
}
|
|
2550
2865
|
|
|
2551
2866
|
// src/SectionList.tsx
|
|
2552
|
-
import { Fragment as
|
|
2553
|
-
var AnimatedSectionList = createAnimatedComponent(RNSectionList);
|
|
2867
|
+
import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2868
|
+
var AnimatedSectionList = Animated7.createAnimatedComponent(RNSectionList);
|
|
2554
2869
|
var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }) => {
|
|
2555
|
-
const scrollView =
|
|
2870
|
+
const scrollView = useRef9(null);
|
|
2556
2871
|
const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props;
|
|
2557
2872
|
const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed, headerHeight } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
|
|
2873
|
+
const { listGeneration, onListUnmount } = useContext14(ScrollViewContext);
|
|
2874
|
+
const capturedGeneration = useSharedValue8(-1);
|
|
2875
|
+
useLayoutEffect6(() => {
|
|
2876
|
+
const generation = listGeneration.value;
|
|
2877
|
+
runOnUI3((gen) => {
|
|
2878
|
+
"worklet";
|
|
2879
|
+
capturedGeneration.value = gen;
|
|
2880
|
+
})(generation);
|
|
2881
|
+
}, [capturedGeneration, listGeneration]);
|
|
2558
2882
|
const usesCustomSticky = stickySectionHeadersEnabled && renderSectionHeader != null;
|
|
2559
2883
|
const { activeIndex, clipStyle, measureHeader, overlayStyle, resetPositions } = useStickyHeaders(headerFixed, usesCustomSticky);
|
|
2560
|
-
|
|
2884
|
+
useLayoutEffect6(() => {
|
|
2561
2885
|
if (usesCustomSticky) resetPositions(sections.length);
|
|
2562
2886
|
}, [sections, usesCustomSticky, resetPositions, headerHeight]);
|
|
2563
|
-
const sectionViewRefs =
|
|
2887
|
+
const sectionViewRefs = useRef9(/* @__PURE__ */ new Map());
|
|
2564
2888
|
const wrappedRenderSectionHeader = useMemo7(() => {
|
|
2565
2889
|
if (!usesCustomSticky) return renderSectionHeader ?? void 0;
|
|
2566
2890
|
return (info) => {
|
|
@@ -2582,7 +2906,8 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
2582
2906
|
);
|
|
2583
2907
|
};
|
|
2584
2908
|
}, [usesCustomSticky, renderSectionHeader, sections, measureHeader]);
|
|
2585
|
-
|
|
2909
|
+
useLayoutEffect6(() => () => onListUnmount(), [onListUnmount]);
|
|
2910
|
+
const scrollTo = useCallback10((offset, animated) => {
|
|
2586
2911
|
scrollView.current?.getScrollResponder()?.scrollTo({ y: offset, animated });
|
|
2587
2912
|
}, []);
|
|
2588
2913
|
const {
|
|
@@ -2603,12 +2928,12 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
2603
2928
|
const activeListHeader = useMemo7(() => {
|
|
2604
2929
|
if (!renderFilters) return pullSearchHeader;
|
|
2605
2930
|
const Inner = pullSearchHeader;
|
|
2606
|
-
return () => /* @__PURE__ */ jsxs7(
|
|
2931
|
+
return () => /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2607
2932
|
Inner ? typeof Inner === "function" ? /* @__PURE__ */ jsx12(Inner, {}) : Inner : null,
|
|
2608
2933
|
renderFilters
|
|
2609
2934
|
] });
|
|
2610
2935
|
}, [pullSearchHeader, renderFilters]);
|
|
2611
|
-
const pullSearchSettled =
|
|
2936
|
+
const pullSearchSettled = useRef9(false);
|
|
2612
2937
|
useEffect6(() => {
|
|
2613
2938
|
if (!usesCustomSticky || activeListHeader == null || pullSearchSettled.current) return;
|
|
2614
2939
|
pullSearchSettled.current = true;
|
|
@@ -2622,16 +2947,12 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
2622
2947
|
return () => cancelAnimationFrame(handle);
|
|
2623
2948
|
}, [activeListHeader, usesCustomSticky, measureHeader]);
|
|
2624
2949
|
const contentContainerStyle = useMemo7(() => [{ minHeight: Dimensions4.get("window").height - contentInset.top - contentInset.bottom + pullSearchMinHeight }, externalContentContainerStyle], [contentInset.bottom, contentInset.top, externalContentContainerStyle, pullSearchMinHeight]);
|
|
2625
|
-
const
|
|
2626
|
-
|
|
2627
|
-
scrollTo(-contentInset.top + pullSearchHeight, true);
|
|
2628
|
-
}, [contentInset.top, pullSearchHeight, scrollTo]);
|
|
2629
|
-
const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
|
|
2630
|
-
const handleScrollToTop = useCallback9(() => {
|
|
2950
|
+
const handleScroll = useScrollHandler({ capturedGeneration, chipHidden, chipThreshold, footerFixed, headerFixed, listGeneration });
|
|
2951
|
+
const handleScrollToTop = useCallback10(() => {
|
|
2631
2952
|
const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
|
|
2632
2953
|
scrollView.current?.getScrollResponder()?.scrollTo({ y: offset, animated: true });
|
|
2633
2954
|
}, [contentInset.top, pullSearchHeight]);
|
|
2634
|
-
const handleContentSizeChange =
|
|
2955
|
+
const handleContentSizeChange = useCallback10(
|
|
2635
2956
|
(w, h) => {
|
|
2636
2957
|
if (onContentSizeChange) onContentSizeChange(w, h);
|
|
2637
2958
|
},
|
|
@@ -2670,11 +2991,11 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
2670
2991
|
stickySectionHeadersEnabled: false,
|
|
2671
2992
|
windowSize
|
|
2672
2993
|
},
|
|
2673
|
-
headerHeight > 0 ? 1 : 0
|
|
2994
|
+
headerHeight !== null && headerHeight > 0 ? 1 : 0
|
|
2674
2995
|
),
|
|
2675
2996
|
hiddenHeader && /* @__PURE__ */ jsx12(View7, { pointerEvents: "none", style: styles8.measureContainer, children: hiddenHeader }),
|
|
2676
2997
|
/* @__PURE__ */ jsx12(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
|
|
2677
|
-
usesCustomSticky && /* @__PURE__ */ jsx12(
|
|
2998
|
+
usesCustomSticky && /* @__PURE__ */ jsx12(Animated7.View, { pointerEvents: "none", style: [styles8.stickyClip, clipStyle], children: activeIndex >= 0 && activeIndex < sections.length && /* @__PURE__ */ jsx12(Animated7.View, { style: [styles8.stickyOverlay, overlayStyle], children: renderSectionHeader({ section: sections[activeIndex] }) }) })
|
|
2678
2999
|
] });
|
|
2679
3000
|
return detectorGesture ? /* @__PURE__ */ jsx12(GestureDetector4, { gesture: detectorGesture, children: content }) : content;
|
|
2680
3001
|
};
|
|
@@ -2686,15 +3007,15 @@ var styles8 = {
|
|
|
2686
3007
|
var SectionList = memo4(SectionListInner);
|
|
2687
3008
|
|
|
2688
3009
|
// src/useScrollView.ts
|
|
2689
|
-
import { useContext as
|
|
3010
|
+
import { useContext as useContext15 } from "react";
|
|
2690
3011
|
var useScrollView = () => {
|
|
2691
|
-
const { progress, progressing, scrollHeight, scrollPosition, setProgress, setProgressing } =
|
|
3012
|
+
const { progress, progressing, scrollHeight, scrollPosition, setProgress, setProgressing } = useContext15(ScrollViewContext);
|
|
2692
3013
|
return { progress, progressing, scrollHeight, scrollPosition, setProgress, setProgressing };
|
|
2693
3014
|
};
|
|
2694
3015
|
|
|
2695
3016
|
// src/useScrollViewSettings.ts
|
|
2696
|
-
import { useContext as
|
|
2697
|
-
var useScrollViewSettings = () =>
|
|
3017
|
+
import { useContext as useContext16 } from "react";
|
|
3018
|
+
var useScrollViewSettings = () => useContext16(ScrollViewSettingsContext);
|
|
2698
3019
|
export {
|
|
2699
3020
|
CustomList,
|
|
2700
3021
|
FlatList,
|