@rific/scroll-view 0.8.3 → 0.9.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/README.md +175 -1
- package/dist/index.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +332 -153
- package/dist/index.mjs +308 -133
- package/package.json +1 -1
- package/src/ScrollViewChromeContext.ts +37 -0
- package/src/ScrollViewChromeProvider.tsx +65 -0
- package/src/ScrollViewContext.ts +16 -0
- package/src/ScrollViewFooter.tsx +51 -15
- package/src/ScrollViewHeader.tsx +24 -3
- package/src/ScrollViewProvider.tsx +96 -23
- package/src/index.ts +3 -0
- package/src/internal/ChromeRegistrar.tsx +37 -0
- package/src/internal/chrome.ts +19 -0
- package/src/internal/useScrollHandler.ts +26 -5
- package/src/internal/useScrollHandlerJS.ts +31 -7
- package/src/internal/useScrollList.ts +22 -5
- package/src/useScrollViewChrome.ts +41 -0
package/dist/index.mjs
CHANGED
|
@@ -38,6 +38,9 @@ import { runOnJS, useAnimatedScrollHandler, useSharedValue as useSharedValue2, w
|
|
|
38
38
|
import { createContext } from "react";
|
|
39
39
|
var ScrollViewContext = createContext({
|
|
40
40
|
blur: true,
|
|
41
|
+
chromeHosted: false,
|
|
42
|
+
chromeOverhang: 0,
|
|
43
|
+
chromeWritable: null,
|
|
41
44
|
footerAboveKeyboard: false,
|
|
42
45
|
footerHeight: null,
|
|
43
46
|
footerHeightShared: null,
|
|
@@ -68,6 +71,7 @@ var ScrollViewContext = createContext({
|
|
|
68
71
|
},
|
|
69
72
|
snapBackFooterShared: null,
|
|
70
73
|
snapBackHeaderShared: null,
|
|
74
|
+
stackHeightShared: null,
|
|
71
75
|
tabBarHeight: 0
|
|
72
76
|
});
|
|
73
77
|
|
|
@@ -259,9 +263,20 @@ function useScrollInit({ listHeaderComponent, onMomentumScrollEnd: externalMomen
|
|
|
259
263
|
return { activeListHeader, handleMomentumScrollEnd, handleScrollBeginDrag, handleScrollEndDrag, hiddenHeader, onRemountSyncRetry, onRemountSynced, pullSearchMinHeight: pullSearchHeight ?? 0, remountSyncTarget, remountTarget, scrollReady };
|
|
260
264
|
}
|
|
261
265
|
|
|
266
|
+
// src/internal/chrome.ts
|
|
267
|
+
var CHROME_SLACK = 2;
|
|
268
|
+
var chromeTravel = (maxScroll, headerHeight) => {
|
|
269
|
+
"worklet";
|
|
270
|
+
return usesContentInset ? maxScroll + headerHeight : maxScroll;
|
|
271
|
+
};
|
|
272
|
+
var chromeSettleTarget = (offset, stackHeight) => {
|
|
273
|
+
"worklet";
|
|
274
|
+
return offset > stackHeight / 2 ? stackHeight : 0;
|
|
275
|
+
};
|
|
276
|
+
|
|
262
277
|
// src/internal/useScrollHandler.ts
|
|
263
278
|
function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, listGeneration, onRemountSyncRetry, onRemountSynced, remountSyncTarget }) {
|
|
264
|
-
const {
|
|
279
|
+
const { chromeHosted, chromeWritable, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared, stackHeightShared } = useContext2(ScrollViewContext);
|
|
265
280
|
const snapUpAccum = useSharedValue2(0);
|
|
266
281
|
const fromBottomBounce = useSharedValue2(false);
|
|
267
282
|
return useAnimatedScrollHandler(
|
|
@@ -296,7 +311,9 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
|
|
|
296
311
|
fromBottomBounce.value = false;
|
|
297
312
|
}
|
|
298
313
|
const snapHeader = snapBackHeaderShared.value && !headerFixed;
|
|
299
|
-
const
|
|
314
|
+
const hideable = !chromeHosted || chromeTravel(maxScroll, headerHeightShared.value) >= stackHeightShared.value;
|
|
315
|
+
if (chromeHosted && !hideable && chromeWritable.value && footerOffset.value !== 0) footerOffset.value = 0;
|
|
316
|
+
const snapFooter = snapBackFooterShared.value && !footerFixed && chromeWritable.value && hideable;
|
|
300
317
|
if (snapHeader || snapFooter) {
|
|
301
318
|
if (yn <= -headerHeightShared.value) {
|
|
302
319
|
snapUpAccum.value = 0;
|
|
@@ -306,7 +323,7 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
|
|
|
306
323
|
snapUpAccum.value = 0;
|
|
307
324
|
if (yn >= -headerHeightShared.value + pullSearchHeightShared.value) {
|
|
308
325
|
if (snapHeader) headerOffset.value = Math.max(-headerHeightShared.value, Math.min(0, headerOffset.value - delta));
|
|
309
|
-
if (snapFooter) footerOffset.value = Math.max(0, Math.min(
|
|
326
|
+
if (snapFooter) footerOffset.value = Math.max(0, Math.min(stackHeightShared.value, footerOffset.value + delta));
|
|
310
327
|
}
|
|
311
328
|
} else if (delta < 0 && !fromBottomBounce.value) {
|
|
312
329
|
if (yn >= -headerHeightShared.value + pullSearchHeightShared.value) snapUpAccum.value -= delta;
|
|
@@ -323,21 +340,29 @@ function useScrollHandler({ capturedGeneration, chipHidden, chipThreshold = 100,
|
|
|
323
340
|
fromBottomBounce.value = false;
|
|
324
341
|
snapUpAccum.value = 0;
|
|
325
342
|
},
|
|
326
|
-
onEndDrag: ({ contentOffset: { y }, contentSize: { height: contentHeight }, layoutMeasurement: { height: layoutHeight } }) => {
|
|
343
|
+
onEndDrag: ({ contentOffset: { y }, contentSize: { height: contentHeight }, layoutMeasurement: { height: layoutHeight }, velocity }) => {
|
|
327
344
|
"worklet";
|
|
328
345
|
if (isHorizontal) return;
|
|
346
|
+
const revealing = snapUpAccum.value >= 10;
|
|
329
347
|
if (y >= contentHeight - layoutHeight - 10) {
|
|
330
348
|
fromBottomBounce.value = true;
|
|
331
349
|
snapUpAccum.value = 0;
|
|
332
350
|
}
|
|
351
|
+
if (chromeHosted && !footerFixed && chromeWritable.value && (velocity === void 0 || Math.abs(velocity.y) < 0.1)) {
|
|
352
|
+
footerOffset.value = withTiming(revealing ? 0 : chromeSettleTarget(footerOffset.value, stackHeightShared.value), { duration: 200 });
|
|
353
|
+
}
|
|
333
354
|
},
|
|
334
355
|
onMomentumEnd: () => {
|
|
335
356
|
"worklet";
|
|
357
|
+
const revealing = snapUpAccum.value >= 10;
|
|
336
358
|
fromBottomBounce.value = false;
|
|
337
359
|
snapUpAccum.value = 0;
|
|
360
|
+
if (chromeHosted && !isHorizontal && !footerFixed && chromeWritable.value) {
|
|
361
|
+
footerOffset.value = withTiming(revealing ? 0 : chromeSettleTarget(footerOffset.value, stackHeightShared.value), { duration: 200 });
|
|
362
|
+
}
|
|
338
363
|
}
|
|
339
364
|
},
|
|
340
|
-
[capturedGeneration, headerFixed, footerFixed, isHorizontal, chipThreshold, listGeneration, onRemountSyncRetry, onRemountSynced, remountSyncTarget]
|
|
365
|
+
[capturedGeneration, chromeHosted, headerFixed, footerFixed, isHorizontal, chipThreshold, listGeneration, onRemountSyncRetry, onRemountSynced, remountSyncTarget]
|
|
341
366
|
);
|
|
342
367
|
}
|
|
343
368
|
|
|
@@ -379,18 +404,20 @@ var CHIP_SLIDE = 48;
|
|
|
379
404
|
function useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, hideUntilMeasured, isHorizontal, keyboardAware, pullSearchHeight, style } = {}) {
|
|
380
405
|
const insets = useSafeAreaInsets();
|
|
381
406
|
const keyboardHeight = useKeyboardInset();
|
|
382
|
-
const { footerAboveKeyboard, footerHeight, footerFixed: contextFooterFixed, headerHeight, headerHeightShared, headerFixed: contextHeaderFixed, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared, tabBarHeight } = useContext3(ScrollViewContext);
|
|
407
|
+
const { chromeHosted, chromeOverhang, footerAboveKeyboard, footerHeight, footerFixed: contextFooterFixed, headerHeight, headerHeightShared, headerFixed: contextHeaderFixed, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared, tabBarHeight } = useContext3(ScrollViewContext);
|
|
383
408
|
const headerFixed = isHorizontal ? true : headerFixedProp ?? contextHeaderFixed;
|
|
384
|
-
const footerFixed = isHorizontal ? true : footerFixedProp ?? contextFooterFixed;
|
|
409
|
+
const footerFixed = isHorizontal ? true : chromeHosted ? contextFooterFixed : footerFixedProp ?? contextFooterFixed;
|
|
385
410
|
useEffect2(() => {
|
|
386
411
|
pullSearchHeightShared.value = usesContentInset ? pullSearchHeight ?? 0 : 0;
|
|
387
412
|
}, [pullSearchHeight, pullSearchHeightShared]);
|
|
388
413
|
const containerStyle = useMemo(() => headerHeight === null ? [{ flex: 1, opacity: hideUntilMeasured ? 0 : 1 }, style] : [StyleSheet2.absoluteFill, style], [headerHeight, hideUntilMeasured, style]);
|
|
389
414
|
const insetGeometry = useMemo(() => {
|
|
390
|
-
const
|
|
391
|
-
const
|
|
415
|
+
const baseReserve = chromeHosted ? chromeOverhang : insets.bottom;
|
|
416
|
+
const footerReserve = chromeHosted ? Math.max(footerHeight ?? 0, baseReserve) : footerFixed ? footerHeight || baseReserve : baseReserve;
|
|
417
|
+
const barReserve = chromeHosted && footerFixed && footerAboveKeyboard ? Math.max(tabBarHeight - keyboardHeight, 0) : tabBarHeight;
|
|
418
|
+
const bottom = (!keyboardAware || footerFixed && footerAboveKeyboard ? footerReserve : Math.max(footerReserve, keyboardHeight)) + barReserve;
|
|
392
419
|
return { bottom, top: headerHeight ?? 0 };
|
|
393
|
-
}, [footerAboveKeyboard, footerFixed, footerHeight, insets.bottom, tabBarHeight, headerHeight, keyboardAware, keyboardHeight]);
|
|
420
|
+
}, [chromeHosted, chromeOverhang, footerAboveKeyboard, footerFixed, footerHeight, insets.bottom, tabBarHeight, headerHeight, keyboardAware, keyboardHeight]);
|
|
394
421
|
const contentInset = usesContentInset ? insetGeometry : ZERO_INSET;
|
|
395
422
|
const contentPadding = useMemo(() => usesContentInset || isHorizontal ? null : { paddingBottom: insetGeometry.bottom, paddingTop: insetGeometry.top }, [insetGeometry, isHorizontal]);
|
|
396
423
|
const [startedWithHeader] = useState3(headerHeight !== null);
|
|
@@ -579,7 +606,7 @@ import { withTiming as withTiming3 } from "react-native-reanimated";
|
|
|
579
606
|
var REMOUNT_RETRY_TOLERANCE = 1;
|
|
580
607
|
var REMOUNT_RETRY_MAX_ATTEMPTS = 8;
|
|
581
608
|
function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, jsListGeneration, remountTarget = null, scrollTo }) {
|
|
582
|
-
const {
|
|
609
|
+
const { chromeHosted, chromeWritable, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared, stackHeightShared } = useContext6(ScrollViewContext);
|
|
583
610
|
const snapUpAccum = useRef3(0);
|
|
584
611
|
const fromBottomBounce = useRef3(false);
|
|
585
612
|
const pendingRemountTarget = useRef3(remountTarget);
|
|
@@ -623,7 +650,9 @@ function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 10
|
|
|
623
650
|
fromBottomBounce.current = false;
|
|
624
651
|
}
|
|
625
652
|
const snapHeader = snapBackHeaderShared.value && !headerFixed;
|
|
626
|
-
const
|
|
653
|
+
const hideable = !chromeHosted || chromeTravel(maxScroll, headerHeightShared.value) >= stackHeightShared.value;
|
|
654
|
+
if (chromeHosted && !hideable && chromeWritable.value && footerOffset.value !== 0) footerOffset.value = 0;
|
|
655
|
+
const snapFooter = snapBackFooterShared.value && !footerFixed && chromeWritable.value && hideable;
|
|
627
656
|
if (snapHeader || snapFooter) {
|
|
628
657
|
if (yn <= -headerHeightShared.value) {
|
|
629
658
|
snapUpAccum.current = 0;
|
|
@@ -633,7 +662,7 @@ function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 10
|
|
|
633
662
|
snapUpAccum.current = 0;
|
|
634
663
|
if (yn >= -headerHeightShared.value + pullSearchHeightShared.value) {
|
|
635
664
|
if (snapHeader) headerOffset.value = Math.max(-headerHeightShared.value, Math.min(0, headerOffset.value - delta));
|
|
636
|
-
if (snapFooter) footerOffset.value = Math.max(0, Math.min(
|
|
665
|
+
if (snapFooter) footerOffset.value = Math.max(0, Math.min(stackHeightShared.value, footerOffset.value + delta));
|
|
637
666
|
}
|
|
638
667
|
} else if (delta < 0 && !fromBottomBounce.current) {
|
|
639
668
|
if (yn >= -headerHeightShared.value + pullSearchHeightShared.value) snapUpAccum.current -= delta;
|
|
@@ -645,7 +674,7 @@ function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 10
|
|
|
645
674
|
}
|
|
646
675
|
}
|
|
647
676
|
},
|
|
648
|
-
[capturedGeneration, chipHidden, chipThreshold,
|
|
677
|
+
[capturedGeneration, chipHidden, chipThreshold, chromeHosted, chromeWritable, footerFixed, footerOffset, headerFixed, headerHeightShared, headerOffset, isHorizontal, jsListGeneration, pullSearchHeightShared, scrollPosition, scrollTo, snapBackFooterShared, snapBackHeaderShared, stackHeightShared]
|
|
649
678
|
);
|
|
650
679
|
const onScrollBeginDrag = useCallback3(() => {
|
|
651
680
|
fromBottomBounce.current = false;
|
|
@@ -653,25 +682,37 @@ function useScrollHandlerJS({ capturedGeneration, chipHidden, chipThreshold = 10
|
|
|
653
682
|
}, []);
|
|
654
683
|
const onMomentumScrollBegin = useCallback3(() => {
|
|
655
684
|
}, []);
|
|
685
|
+
const settle = useCallback3(
|
|
686
|
+
(revealing) => {
|
|
687
|
+
if (!chromeHosted || footerFixed || !chromeWritable.value) return;
|
|
688
|
+
footerOffset.value = withTiming3(revealing ? 0 : chromeSettleTarget(footerOffset.value, stackHeightShared.value), { duration: 200 });
|
|
689
|
+
},
|
|
690
|
+
[chromeHosted, chromeWritable, footerFixed, footerOffset, stackHeightShared]
|
|
691
|
+
);
|
|
656
692
|
const onScrollEndDrag = useCallback3(
|
|
657
693
|
(event) => {
|
|
658
694
|
if (isHorizontal) return;
|
|
659
695
|
const {
|
|
660
696
|
contentOffset: { y },
|
|
661
697
|
contentSize: { height: contentHeight },
|
|
662
|
-
layoutMeasurement: { height: layoutHeight }
|
|
698
|
+
layoutMeasurement: { height: layoutHeight },
|
|
699
|
+
velocity
|
|
663
700
|
} = event.nativeEvent;
|
|
701
|
+
const revealing = snapUpAccum.current >= 10;
|
|
664
702
|
if (y >= contentHeight - layoutHeight - 10) {
|
|
665
703
|
fromBottomBounce.current = true;
|
|
666
704
|
snapUpAccum.current = 0;
|
|
667
705
|
}
|
|
706
|
+
if (velocity === void 0 || Math.abs(velocity.y) < 0.1) settle(revealing);
|
|
668
707
|
},
|
|
669
|
-
[isHorizontal]
|
|
708
|
+
[isHorizontal, settle]
|
|
670
709
|
);
|
|
671
710
|
const onMomentumScrollEnd = useCallback3(() => {
|
|
711
|
+
const revealing = snapUpAccum.current >= 10;
|
|
672
712
|
fromBottomBounce.current = false;
|
|
673
713
|
snapUpAccum.current = 0;
|
|
674
|
-
|
|
714
|
+
if (!isHorizontal) settle(revealing);
|
|
715
|
+
}, [isHorizontal, settle]);
|
|
675
716
|
return { onMomentumScrollBegin, onMomentumScrollEnd, onScroll, onScrollBeginDrag, onScrollEndDrag };
|
|
676
717
|
}
|
|
677
718
|
|
|
@@ -1000,22 +1041,56 @@ var ScrollViewInner = ({ chipProps, chipThreshold, children, contentContainerSty
|
|
|
1000
1041
|
};
|
|
1001
1042
|
var ScrollView = memo3(ScrollViewInner);
|
|
1002
1043
|
|
|
1044
|
+
// src/ScrollViewChromeProvider.tsx
|
|
1045
|
+
import { useCallback as useCallback7, useEffect as useEffect4, useMemo as useMemo5, useState as useState5 } from "react";
|
|
1046
|
+
import { useSharedValue as useSharedValue6, withTiming as withTiming4 } from "react-native-reanimated";
|
|
1047
|
+
|
|
1048
|
+
// src/ScrollViewChromeContext.ts
|
|
1049
|
+
import { createContext as createContext2 } from "react";
|
|
1050
|
+
var ScrollViewChromeHostContext = createContext2(null);
|
|
1051
|
+
var ScrollViewChromeContext = createContext2(null);
|
|
1052
|
+
|
|
1053
|
+
// src/ScrollViewChromeProvider.tsx
|
|
1054
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1055
|
+
var REVEAL_DURATION = 200;
|
|
1056
|
+
var alwaysActive = () => true;
|
|
1057
|
+
var ScrollViewChromeProvider = ({ children, footprint, overhang = 0, snapBack = true, useIsActive = alwaysActive }) => {
|
|
1058
|
+
const offset = useSharedValue6(0);
|
|
1059
|
+
const [claims, setClaims] = useState5([]);
|
|
1060
|
+
const [pins, setPins] = useState5(0);
|
|
1061
|
+
const activeId = claims.length > 0 ? claims[claims.length - 1] : null;
|
|
1062
|
+
const pinned = pins > 0;
|
|
1063
|
+
const claim = useCallback7((id) => setClaims((current) => [...current.filter((c) => c !== id), id]), []);
|
|
1064
|
+
const release = useCallback7((id) => setClaims((current) => current.filter((c) => c !== id)), []);
|
|
1065
|
+
const addPin = useCallback7(() => setPins((current) => current + 1), []);
|
|
1066
|
+
const removePin = useCallback7(() => setPins((current) => Math.max(0, current - 1)), []);
|
|
1067
|
+
const reveal = useCallback7(() => {
|
|
1068
|
+
offset.value = withTiming4(0, { duration: REVEAL_DURATION });
|
|
1069
|
+
}, [offset]);
|
|
1070
|
+
useEffect4(() => {
|
|
1071
|
+
reveal();
|
|
1072
|
+
}, [activeId, pinned, reveal]);
|
|
1073
|
+
const host = useMemo5(() => ({ activeId, claim, footprint, offset, overhang, pinned, release, reveal, snapBack, useIsActive }), [activeId, claim, footprint, offset, overhang, pinned, release, reveal, snapBack, useIsActive]);
|
|
1074
|
+
const chrome = useMemo5(() => ({ addPin, footprint, offset, overhang, removePin, reveal }), [addPin, footprint, offset, overhang, removePin, reveal]);
|
|
1075
|
+
return /* @__PURE__ */ jsx8(ScrollViewChromeContext.Provider, { value: chrome, children: /* @__PURE__ */ jsx8(ScrollViewChromeHostContext.Provider, { value: host, children }) });
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1003
1078
|
// src/ScrollViewFooter.tsx
|
|
1004
1079
|
import { BlurView as BlurView2 } from "@rific/auto-paper";
|
|
1005
|
-
import { useContext as useContext10, useEffect as
|
|
1006
|
-
import { StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
1080
|
+
import { useContext as useContext10, useEffect as useEffect5, useLayoutEffect as useLayoutEffect5, useRef as useRef7 } from "react";
|
|
1081
|
+
import { Platform as Platform5, StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
1007
1082
|
import Animated5, { useAnimatedStyle as useAnimatedStyle4 } from "react-native-reanimated";
|
|
1008
1083
|
import { useSafeAreaInsets as useSafeAreaInsets3 } from "react-native-safe-area-context";
|
|
1009
|
-
import { jsx as
|
|
1084
|
+
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1010
1085
|
var ScrollViewFooter = ({ children, style }) => {
|
|
1011
|
-
const { blur, footerAboveKeyboard, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared, tabBarHeight } = useContext10(ScrollViewContext);
|
|
1086
|
+
const { blur, chromeHosted, chromeOverhang, footerAboveKeyboard, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared, stackHeightShared, tabBarHeight } = useContext10(ScrollViewContext);
|
|
1012
1087
|
const insets = useSafeAreaInsets3();
|
|
1013
1088
|
const keyboardHeight = useKeyboardInset();
|
|
1014
1089
|
const setFooterHeightRef = useRef7(setFooterHeight);
|
|
1015
|
-
|
|
1090
|
+
useEffect5(() => {
|
|
1016
1091
|
setFooterHeightRef.current = setFooterHeight;
|
|
1017
1092
|
});
|
|
1018
|
-
|
|
1093
|
+
useEffect5(
|
|
1019
1094
|
() => () => {
|
|
1020
1095
|
setFooterHeightRef.current(null);
|
|
1021
1096
|
},
|
|
@@ -1029,23 +1104,33 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
1029
1104
|
if (footerHeight !== height) setFooterHeight(height);
|
|
1030
1105
|
};
|
|
1031
1106
|
const footerStyle = useAnimatedStyle4(() => {
|
|
1107
|
+
if (chromeHosted) return { transform: [{ translateY: Math.min(Math.max(footerOffset.value, 0), stackHeightShared.value) }] };
|
|
1032
1108
|
if (footerFixed) return { transform: [{ translateY: 0 }] };
|
|
1033
1109
|
if (snapBackFooterShared.value) return { transform: [{ translateY: footerOffset.value }] };
|
|
1034
1110
|
const effective = scrollPosition.value + headerHeightShared.value - pullSearchHeightShared.value;
|
|
1035
1111
|
if (effective <= 0) return { transform: [{ translateY: 0 }] };
|
|
1036
1112
|
return { transform: [{ translateY: Math.min(effective, footerHeight ?? 0) }] };
|
|
1037
|
-
}, [footerHeight, footerFixed, headerHeightShared, pullSearchHeightShared, scrollPosition, snapBackFooterShared, footerOffset]);
|
|
1113
|
+
}, [chromeHosted, footerHeight, footerFixed, headerHeightShared, pullSearchHeightShared, scrollPosition, snapBackFooterShared, footerOffset, stackHeightShared]);
|
|
1038
1114
|
const containerPaddingBottom = footerFixed && footerAboveKeyboard ? keyboardHeight : 0;
|
|
1039
|
-
const
|
|
1115
|
+
const rowRef = useRef7(null);
|
|
1116
|
+
useLayoutEffect5(() => {
|
|
1117
|
+
if (Platform5.OS !== "web" || footerHeight) return;
|
|
1118
|
+
const height = rowRef.current?.offsetHeight;
|
|
1119
|
+
if (typeof height !== "number" || height <= 0) return;
|
|
1120
|
+
setFooterHeight(height + containerPaddingBottom);
|
|
1121
|
+
}, []);
|
|
1122
|
+
const bottomPadding = chromeHosted ? chromeOverhang : insets.bottom;
|
|
1123
|
+
const rowPaddingBottom = footerFixed && footerAboveKeyboard ? Math.max(bottomPadding - keyboardHeight, 0) : bottomPadding;
|
|
1124
|
+
const footerBottom = chromeHosted && footerFixed && footerAboveKeyboard ? Math.max(tabBarHeight - keyboardHeight, 0) : tabBarHeight;
|
|
1040
1125
|
const { paddingBottom: consumerPaddingBottom, ...restStyle } = style ?? {};
|
|
1041
1126
|
return (
|
|
1042
1127
|
// bottom: tabBarHeight (not the styles.footer default of 0) - a consuming app's own persistent
|
|
1043
1128
|
// tab bar (a fixture outside this package's header/footer concepts entirely, same as
|
|
1044
1129
|
// useScrollList's content-inset reservation) sits below this at the true screen bottom, so this
|
|
1045
1130
|
// bar has to clear it rather than rendering flush against 0 and overlapping/hiding behind it.
|
|
1046
|
-
/* @__PURE__ */ jsxs5(Animated5.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, { bottom:
|
|
1047
|
-
(footerHeight ?? 0) > 0 && /* @__PURE__ */
|
|
1048
|
-
/* @__PURE__ */
|
|
1131
|
+
/* @__PURE__ */ jsxs5(Animated5.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, { bottom: footerBottom, paddingBottom: containerPaddingBottom }, footerStyle], children: [
|
|
1132
|
+
(footerHeight ?? 0) > 0 && /* @__PURE__ */ jsx9(BlurView2, { blur, style: StyleSheet5.absoluteFill }),
|
|
1133
|
+
/* @__PURE__ */ jsx9(View5, { ref: rowRef, style: [styles6.row, restStyle, { paddingBottom: rowPaddingBottom + (typeof consumerPaddingBottom === "number" ? consumerPaddingBottom : 0) }], children })
|
|
1049
1134
|
] })
|
|
1050
1135
|
);
|
|
1051
1136
|
};
|
|
@@ -1056,13 +1141,13 @@ var styles6 = StyleSheet5.create({
|
|
|
1056
1141
|
|
|
1057
1142
|
// src/ScrollViewHeader.tsx
|
|
1058
1143
|
import { BlurView as BlurView3 } from "@rific/auto-paper";
|
|
1059
|
-
import { useContext as useContext11 } from "react";
|
|
1060
|
-
import { StyleSheet as StyleSheet6, Text, View as View6 } from "react-native";
|
|
1144
|
+
import { useContext as useContext11, useLayoutEffect as useLayoutEffect6, useRef as useRef8 } from "react";
|
|
1145
|
+
import { Platform as Platform6, StyleSheet as StyleSheet6, Text, View as View6 } from "react-native";
|
|
1061
1146
|
import { Appbar, ProgressBar, Surface, useTheme as useTheme4 } from "react-native-paper";
|
|
1062
|
-
import Animated6, { useAnimatedStyle as useAnimatedStyle5, useSharedValue as
|
|
1147
|
+
import Animated6, { useAnimatedStyle as useAnimatedStyle5, useSharedValue as useSharedValue7 } from "react-native-reanimated";
|
|
1063
1148
|
import { useSafeAreaInsets as useSafeAreaInsets4 } from "react-native-safe-area-context";
|
|
1064
|
-
import { Fragment as Fragment4, jsx as
|
|
1065
|
-
var ActionBg = ({ blur, style }) => blur ? /* @__PURE__ */
|
|
1149
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1150
|
+
var ActionBg = ({ blur, style }) => blur ? /* @__PURE__ */ jsx10(View6, { style: [StyleSheet6.absoluteFill, styles7.actionBg, style], children: /* @__PURE__ */ jsx10(BlurView3, { blur: true, style: StyleSheet6.absoluteFill }) }) : /* @__PURE__ */ jsx10(View6, { style: [StyleSheet6.absoluteFill, styles7.actionBg, style], pointerEvents: "none", children: /* @__PURE__ */ jsx10(Surface, { style: StyleSheet6.absoluteFill, elevation: 1, children: null }) });
|
|
1066
1151
|
var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAccessibilityLabel, backActionFixed, caption, centerContent, children, iconSize, style, title, topInset = true, trailingAction, trailingActionFixed = true }) => {
|
|
1067
1152
|
const { blur, headerHeight, headerFixed, headerHeightShared, headerOffset, progress, progressing, pullSearchHeightShared, scrollPosition, setHeaderHeight, snapBackHeaderShared } = useContext11(ScrollViewContext);
|
|
1068
1153
|
const { settings } = useContext11(ScrollViewSettingsContext);
|
|
@@ -1070,7 +1155,7 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
|
|
|
1070
1155
|
const insets = useSafeAreaInsets4();
|
|
1071
1156
|
const theme = useTheme4();
|
|
1072
1157
|
const top = topInset ? insets.top : 0;
|
|
1073
|
-
const measuredShared =
|
|
1158
|
+
const measuredShared = useSharedValue7(false);
|
|
1074
1159
|
const handleLayout = ({
|
|
1075
1160
|
nativeEvent: {
|
|
1076
1161
|
layout: { height }
|
|
@@ -1079,6 +1164,14 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
|
|
|
1079
1164
|
measuredShared.value = true;
|
|
1080
1165
|
if (headerHeight !== height) setHeaderHeight(height);
|
|
1081
1166
|
};
|
|
1167
|
+
const contentRef = useRef8(null);
|
|
1168
|
+
useLayoutEffect6(() => {
|
|
1169
|
+
if (Platform6.OS !== "web" || headerHeight) return;
|
|
1170
|
+
const height = contentRef.current?.offsetHeight;
|
|
1171
|
+
if (typeof height !== "number" || height <= 0) return;
|
|
1172
|
+
measuredShared.value = true;
|
|
1173
|
+
setHeaderHeight(height);
|
|
1174
|
+
}, []);
|
|
1082
1175
|
const actionMargin = 4;
|
|
1083
1176
|
const contentMinHeight = actionSize + 2 * actionMargin;
|
|
1084
1177
|
const unmeasuredHeight = top + contentMinHeight;
|
|
@@ -1108,31 +1201,31 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionAc
|
|
|
1108
1201
|
const leadingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", left: actionMargin, position: "absolute", top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
|
|
1109
1202
|
const trailingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", position: "absolute", right: actionMargin, top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
|
|
1110
1203
|
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1111
|
-
/* @__PURE__ */
|
|
1204
|
+
/* @__PURE__ */ jsx10(Animated6.View, { pointerEvents: "none", style: [styles7.blur, blurStyle], children: headerHeight !== 0 && /* @__PURE__ */ jsx10(BlurView3, { blur, style: [styles7.blurInner, { height: headerHeight ?? unmeasuredHeight }] }) }),
|
|
1112
1205
|
/* @__PURE__ */ jsxs6(Animated6.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [headerHeight === null ? styles7.headerInit : styles7.header, translateStyle], children: [
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1116
|
-
(centerContent || title || caption) && /* @__PURE__ */
|
|
1117
|
-
title && /* @__PURE__ */
|
|
1118
|
-
caption && /* @__PURE__ */
|
|
1206
|
+
/* @__PURE__ */ jsx10(View6, { ref: contentRef, style: [{ paddingTop: top }, style], children: children ?? /* @__PURE__ */ jsxs6(View6, { style: [styles7.content, { minHeight: contentMinHeight }], children: [
|
|
1207
|
+
/* @__PURE__ */ jsx10(View6, { style: styles7.side }),
|
|
1208
|
+
/* @__PURE__ */ jsx10(View6, { style: styles7.spacer }),
|
|
1209
|
+
(centerContent || title || caption) && /* @__PURE__ */ jsx10(View6, { style: [StyleSheet6.absoluteFill, styles7.titleContainer], pointerEvents: centerContent ? "box-none" : "none", children: centerContent ?? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1210
|
+
title && /* @__PURE__ */ jsx10(Text, { numberOfLines: 1, style: [styles7.title, { color: theme.colors.onSurface }], children: title }),
|
|
1211
|
+
caption && /* @__PURE__ */ jsx10(Text, { numberOfLines: 1, style: [styles7.caption, { color: theme.colors.onSurfaceVariant }], children: caption })
|
|
1119
1212
|
] }) })
|
|
1120
1213
|
] }) }),
|
|
1121
|
-
!blur && /* @__PURE__ */
|
|
1214
|
+
!blur && /* @__PURE__ */ jsx10(View6, { style: [styles7.divider, { backgroundColor: theme.colors.outlineVariant }] })
|
|
1122
1215
|
] }),
|
|
1123
|
-
/* @__PURE__ */
|
|
1216
|
+
/* @__PURE__ */ jsx10(Animated6.View, { pointerEvents: "none", style: [styles7.progress, progressStyle], children: /* @__PURE__ */ jsx10(ProgressBar, { indeterminate: progress === null, visible: progressing, progress: progress ?? void 0 }) }),
|
|
1124
1217
|
backAction && (effectiveBackActionFixed ? /* @__PURE__ */ jsxs6(Animated6.View, { style: leadingStyle, children: [
|
|
1125
|
-
/* @__PURE__ */
|
|
1126
|
-
typeof backAction === "function" ? /* @__PURE__ */
|
|
1218
|
+
/* @__PURE__ */ jsx10(ActionBg, { blur, style: actionStyle }),
|
|
1219
|
+
typeof backAction === "function" ? /* @__PURE__ */ jsx10(Appbar.BackAction, { accessibilityLabel: backActionAccessibilityLabel, onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle }) : backAction
|
|
1127
1220
|
] }) : /* @__PURE__ */ jsxs6(Animated6.View, { style: [leadingStyle, translateStyle], children: [
|
|
1128
|
-
/* @__PURE__ */
|
|
1129
|
-
typeof backAction === "function" ? /* @__PURE__ */
|
|
1221
|
+
/* @__PURE__ */ jsx10(ActionBg, { blur, style: actionStyle }),
|
|
1222
|
+
typeof backAction === "function" ? /* @__PURE__ */ jsx10(Appbar.BackAction, { accessibilityLabel: backActionAccessibilityLabel, onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle }) : backAction
|
|
1130
1223
|
] })),
|
|
1131
1224
|
trailingAction && (trailingActionFixed ? /* @__PURE__ */ jsxs6(View6, { style: trailingStyle, children: [
|
|
1132
|
-
/* @__PURE__ */
|
|
1225
|
+
/* @__PURE__ */ jsx10(ActionBg, { blur, style: actionStyle }),
|
|
1133
1226
|
trailingAction
|
|
1134
1227
|
] }) : /* @__PURE__ */ jsxs6(Animated6.View, { style: [trailingStyle, translateStyle], children: [
|
|
1135
|
-
/* @__PURE__ */
|
|
1228
|
+
/* @__PURE__ */ jsx10(ActionBg, { blur, style: actionStyle }),
|
|
1136
1229
|
trailingAction
|
|
1137
1230
|
] }))
|
|
1138
1231
|
] });
|
|
@@ -1155,57 +1248,101 @@ var styles7 = StyleSheet6.create({
|
|
|
1155
1248
|
|
|
1156
1249
|
// src/ScrollViewProvider.tsx
|
|
1157
1250
|
import { useBlur } from "@rific/auto-paper";
|
|
1158
|
-
import { useCallback as
|
|
1159
|
-
import { Dimensions as Dimensions3, Platform as
|
|
1160
|
-
import { useSharedValue as
|
|
1161
|
-
|
|
1162
|
-
|
|
1251
|
+
import { useCallback as useCallback8, useContext as useContext12, useEffect as useEffect7, useLayoutEffect as useLayoutEffect7, useMemo as useMemo6, useRef as useRef9, useState as useState6 } from "react";
|
|
1252
|
+
import { Dimensions as Dimensions3, Platform as Platform7 } from "react-native";
|
|
1253
|
+
import { useSharedValue as useSharedValue8 } from "react-native-reanimated";
|
|
1254
|
+
|
|
1255
|
+
// src/internal/ChromeRegistrar.tsx
|
|
1256
|
+
import { useEffect as useEffect6, useId } from "react";
|
|
1257
|
+
var ChromeRegistrar = ({ footerFixed, host, writable }) => {
|
|
1258
|
+
const id = useId();
|
|
1259
|
+
const active = host.useIsActive();
|
|
1260
|
+
const { activeId, claim, pinned, release, reveal } = host;
|
|
1261
|
+
useEffect6(() => {
|
|
1262
|
+
if (!active) return void 0;
|
|
1263
|
+
claim(id);
|
|
1264
|
+
return () => release(id);
|
|
1265
|
+
}, [active, claim, id, release]);
|
|
1266
|
+
const owner = activeId === id;
|
|
1267
|
+
useEffect6(() => {
|
|
1268
|
+
writable.value = owner && !pinned;
|
|
1269
|
+
}, [owner, pinned, writable]);
|
|
1270
|
+
useEffect6(() => {
|
|
1271
|
+
if (owner && footerFixed) reveal();
|
|
1272
|
+
}, [footerFixed, owner, reveal]);
|
|
1273
|
+
return null;
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
// src/ScrollViewProvider.tsx
|
|
1277
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1278
|
+
var ScrollViewProvider = ({ blur, chrome, children, fixed = false, footerAboveKeyboard = false, footerFixed, headerFixed, snapBack, snapBackFooter, snapBackHeader, tabBarHeight = 0 }) => {
|
|
1163
1279
|
const { settings } = useContext12(ScrollViewSettingsContext);
|
|
1280
|
+
const enclosingHost = useContext12(ScrollViewChromeHostContext);
|
|
1281
|
+
const chromeHost = chrome === false ? null : enclosingHost;
|
|
1282
|
+
const chromeHosted = chromeHost !== null;
|
|
1283
|
+
const chromeFootprint = chromeHost?.footprint ?? 0;
|
|
1284
|
+
const chromeOverhang = chromeHost?.overhang ?? 0;
|
|
1285
|
+
const chromeSnapBack = chromeHost?.snapBack ?? false;
|
|
1164
1286
|
const effectiveBlur = useBlur(blur);
|
|
1165
1287
|
const effectiveSnapBack = snapBack ?? settings.snapBack;
|
|
1166
1288
|
const effectiveSnapBackHeader = snapBackHeader ?? settings.snapBackHeader;
|
|
1167
1289
|
const effectiveSnapBackFooter = snapBackFooter ?? settings.snapBackFooter;
|
|
1168
|
-
const [headerHeight, setHeaderHeightState] =
|
|
1169
|
-
const [footerHeight, setFooterHeightState] =
|
|
1170
|
-
const [progress, setProgress] =
|
|
1171
|
-
const [progressing, setProgressing] =
|
|
1172
|
-
const scrollPosition =
|
|
1173
|
-
const listGeneration =
|
|
1174
|
-
const jsListGeneration =
|
|
1175
|
-
const headerHeightShared =
|
|
1176
|
-
const footerHeightShared =
|
|
1177
|
-
const headerOffset =
|
|
1178
|
-
const
|
|
1179
|
-
const
|
|
1180
|
-
const
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1290
|
+
const [headerHeight, setHeaderHeightState] = useState6(null);
|
|
1291
|
+
const [footerHeight, setFooterHeightState] = useState6(null);
|
|
1292
|
+
const [progress, setProgress] = useState6(null);
|
|
1293
|
+
const [progressing, setProgressing] = useState6(false);
|
|
1294
|
+
const scrollPosition = useSharedValue8(0);
|
|
1295
|
+
const listGeneration = useSharedValue8(0);
|
|
1296
|
+
const jsListGeneration = useRef9(0);
|
|
1297
|
+
const headerHeightShared = useSharedValue8(0);
|
|
1298
|
+
const footerHeightShared = useSharedValue8(0);
|
|
1299
|
+
const headerOffset = useSharedValue8(0);
|
|
1300
|
+
const ownFooterOffset = useSharedValue8(0);
|
|
1301
|
+
const ownStackHeight = useSharedValue8(0);
|
|
1302
|
+
const footerOffset = chromeHost ? chromeHost.offset : ownFooterOffset;
|
|
1303
|
+
const chromeWritable = useSharedValue8(!chromeHosted);
|
|
1304
|
+
useEffect7(() => {
|
|
1305
|
+
if (!chromeHosted) chromeWritable.value = true;
|
|
1306
|
+
}, [chromeHosted, chromeWritable]);
|
|
1307
|
+
const revealChrome = chromeHost?.reveal;
|
|
1308
|
+
const stackHeightShared = chromeHosted ? ownStackHeight : footerHeightShared;
|
|
1309
|
+
const pullSearchHeightShared = useSharedValue8(0);
|
|
1310
|
+
const snapBackHeaderShared = useSharedValue8(false);
|
|
1311
|
+
const snapBackFooterShared = useSharedValue8(false);
|
|
1312
|
+
useEffect7(() => {
|
|
1183
1313
|
snapBackHeaderShared.value = effectiveSnapBackHeader ?? effectiveSnapBack;
|
|
1184
|
-
snapBackFooterShared.value = effectiveSnapBackFooter ?? effectiveSnapBack;
|
|
1185
|
-
}, [effectiveSnapBack, effectiveSnapBackFooter, effectiveSnapBackHeader, snapBackFooterShared, snapBackHeaderShared]);
|
|
1186
|
-
|
|
1187
|
-
(
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1314
|
+
snapBackFooterShared.value = chromeHosted ? chromeSnapBack : effectiveSnapBackFooter ?? effectiveSnapBack;
|
|
1315
|
+
}, [chromeHosted, chromeSnapBack, effectiveSnapBack, effectiveSnapBackFooter, effectiveSnapBackHeader, snapBackFooterShared, snapBackHeaderShared]);
|
|
1316
|
+
useEffect7(() => {
|
|
1317
|
+
if (!chromeHosted) return;
|
|
1318
|
+
ownStackHeight.value = chromeFootprint + Math.max(footerHeight ?? 0, chromeOverhang) + CHROME_SLACK;
|
|
1319
|
+
}, [chromeFootprint, chromeHosted, chromeOverhang, footerHeight, ownStackHeight]);
|
|
1320
|
+
const headerHeightRef = useRef9(null);
|
|
1321
|
+
const footerHeightRef = useRef9(null);
|
|
1322
|
+
const setHeaderHeight = useCallback8((h) => {
|
|
1323
|
+
if (h === 0 && headerHeightRef.current) return;
|
|
1324
|
+
headerHeightRef.current = h;
|
|
1325
|
+
setHeaderHeightState(h);
|
|
1326
|
+
}, []);
|
|
1327
|
+
useLayoutEffect7(() => {
|
|
1328
|
+
headerHeightShared.value = headerHeight ?? 0;
|
|
1329
|
+
}, [headerHeight, headerHeightShared]);
|
|
1330
|
+
const onListUnmount = useCallback8(() => {
|
|
1195
1331
|
listGeneration.value += 1;
|
|
1196
|
-
|
|
1197
|
-
|
|
1332
|
+
if (revealChrome && chromeWritable.value) revealChrome();
|
|
1333
|
+
}, [chromeWritable, listGeneration, revealChrome]);
|
|
1334
|
+
const onJsListUnmount = useCallback8(() => {
|
|
1198
1335
|
jsListGeneration.current += 1;
|
|
1199
1336
|
}, []);
|
|
1200
|
-
|
|
1337
|
+
useEffect7(() => {
|
|
1201
1338
|
if (!__DEV__ || headerHeight !== null) return;
|
|
1202
1339
|
const timeout = setTimeout(() => {
|
|
1203
1340
|
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.");
|
|
1204
1341
|
}, 3e3);
|
|
1205
1342
|
return () => clearTimeout(timeout);
|
|
1206
1343
|
}, [headerHeight]);
|
|
1207
|
-
|
|
1208
|
-
if (
|
|
1344
|
+
useEffect7(() => {
|
|
1345
|
+
if (Platform7.OS !== "web" || headerHeight !== null) return;
|
|
1209
1346
|
let raf2 = 0;
|
|
1210
1347
|
const raf1 = requestAnimationFrame(() => {
|
|
1211
1348
|
raf2 = requestAnimationFrame(() => setHeaderHeight(0));
|
|
@@ -1215,46 +1352,54 @@ var ScrollViewProvider = ({ blur, children, fixed = false, footerAboveKeyboard =
|
|
|
1215
1352
|
cancelAnimationFrame(raf2);
|
|
1216
1353
|
};
|
|
1217
1354
|
}, [headerHeight, setHeaderHeight]);
|
|
1218
|
-
const setFooterHeight =
|
|
1355
|
+
const setFooterHeight = useCallback8(
|
|
1219
1356
|
(h) => {
|
|
1220
|
-
if (h === 0 &&
|
|
1357
|
+
if (h === 0 && footerHeightRef.current) return;
|
|
1358
|
+
footerHeightRef.current = h;
|
|
1221
1359
|
setFooterHeightState(h);
|
|
1222
1360
|
footerHeightShared.value = h ?? 0;
|
|
1223
1361
|
},
|
|
1224
|
-
[
|
|
1362
|
+
[footerHeightShared]
|
|
1225
1363
|
);
|
|
1226
|
-
const scrollHeight =
|
|
1364
|
+
const scrollHeight = useMemo6(() => Dimensions3.get("window").height - (headerHeight ?? 0) - (footerHeight ?? 0), [headerHeight, footerHeight]);
|
|
1227
1365
|
const effectiveHeaderFixed = fixed || (headerFixed ?? settings.headerFixed);
|
|
1228
1366
|
const effectiveFooterFixed = fixed || (footerFixed ?? settings.footerFixed);
|
|
1229
|
-
const
|
|
1230
|
-
|
|
1367
|
+
const effectiveTabBarHeight = chromeHosted ? chromeFootprint : tabBarHeight;
|
|
1368
|
+
const value = useMemo6(
|
|
1369
|
+
() => ({ blur: effectiveBlur, chromeHosted, chromeOverhang, chromeWritable, footerAboveKeyboard, 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, stackHeightShared, tabBarHeight: effectiveTabBarHeight }),
|
|
1370
|
+
[effectiveBlur, chromeHosted, chromeOverhang, chromeWritable, footerAboveKeyboard, effectiveFooterFixed, effectiveHeaderFixed, footerHeight, footerHeightShared, footerOffset, headerHeight, headerHeightShared, headerOffset, jsListGeneration, listGeneration, onJsListUnmount, onListUnmount, progress, pullSearchHeightShared, progressing, scrollHeight, scrollPosition, setFooterHeight, setHeaderHeight, snapBackFooterShared, snapBackHeaderShared, stackHeightShared, effectiveTabBarHeight]
|
|
1371
|
+
);
|
|
1372
|
+
return /* @__PURE__ */ jsx11(ScrollViewContext.Provider, { value, children: /* @__PURE__ */ jsxs7(ScrollViewChromeHostContext.Provider, { value: null, children: [
|
|
1373
|
+
children,
|
|
1374
|
+
chromeHost ? /* @__PURE__ */ jsx11(ChromeRegistrar, { footerFixed: effectiveFooterFixed, host: chromeHost, writable: chromeWritable }) : null
|
|
1375
|
+
] }) });
|
|
1231
1376
|
};
|
|
1232
1377
|
|
|
1233
1378
|
// src/ScrollViewSettingsProvider.tsx
|
|
1234
1379
|
var ScrollViewSettingsProvider = scrollViewSettingsProvider;
|
|
1235
1380
|
|
|
1236
1381
|
// src/SectionList.tsx
|
|
1237
|
-
import { memo as memo4, useCallback as
|
|
1238
|
-
import { Dimensions as Dimensions4, Platform as
|
|
1382
|
+
import { memo as memo4, useCallback as useCallback10, useContext as useContext14, useEffect as useEffect8, useLayoutEffect as useLayoutEffect9, useMemo as useMemo7, useRef as useRef11 } from "react";
|
|
1383
|
+
import { Dimensions as Dimensions4, Platform as Platform8, SectionList as RNSectionList, View as View7 } from "react-native";
|
|
1239
1384
|
import { Gesture as Gesture4, GestureDetector as GestureDetector4 } from "react-native-gesture-handler";
|
|
1240
|
-
import Animated7, { runOnUI as runOnUI3, useSharedValue as
|
|
1385
|
+
import Animated7, { runOnUI as runOnUI3, useSharedValue as useSharedValue10 } from "react-native-reanimated";
|
|
1241
1386
|
|
|
1242
1387
|
// src/internal/useStickyHeaders.ts
|
|
1243
|
-
import { useCallback as
|
|
1244
|
-
import { runOnJS as runOnJS4, useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as
|
|
1388
|
+
import { useCallback as useCallback9, useContext as useContext13, useLayoutEffect as useLayoutEffect8, useRef as useRef10, useState as useState7 } from "react";
|
|
1389
|
+
import { runOnJS as runOnJS4, useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as useSharedValue9 } from "react-native-reanimated";
|
|
1245
1390
|
import { useSafeAreaInsets as useSafeAreaInsets5 } from "react-native-safe-area-context";
|
|
1246
1391
|
function useStickyHeaders(headerFixed, enabled) {
|
|
1247
1392
|
const { headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackHeaderShared } = useContext13(ScrollViewContext);
|
|
1248
1393
|
const insetsTop = useSafeAreaInsets5().top;
|
|
1249
|
-
const sectionYPositions =
|
|
1250
|
-
const sectionHeights =
|
|
1251
|
-
const [activeIndex, setActiveIndex] =
|
|
1252
|
-
const contentIndexShared =
|
|
1253
|
-
|
|
1394
|
+
const sectionYPositions = useSharedValue9([]);
|
|
1395
|
+
const sectionHeights = useSharedValue9([]);
|
|
1396
|
+
const [activeIndex, setActiveIndex] = useState7(-1);
|
|
1397
|
+
const contentIndexShared = useSharedValue9(-1);
|
|
1398
|
+
useLayoutEffect8(() => {
|
|
1254
1399
|
contentIndexShared.value = activeIndex;
|
|
1255
1400
|
}, [activeIndex, contentIndexShared]);
|
|
1256
|
-
const positionsCache =
|
|
1257
|
-
const heightsCache =
|
|
1401
|
+
const positionsCache = useRef10([]);
|
|
1402
|
+
const heightsCache = useRef10([]);
|
|
1258
1403
|
useAnimatedReaction2(
|
|
1259
1404
|
() => {
|
|
1260
1405
|
if (!enabled) return -1;
|
|
@@ -1331,7 +1476,7 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
1331
1476
|
}
|
|
1332
1477
|
return { opacity: 1, top: 0, transform: [{ translateY }] };
|
|
1333
1478
|
}, [enabled, headerFixed, insetsTop, contentIndexShared, sectionYPositions, headerHeightShared, scrollPosition, snapBackHeaderShared, headerOffset, pullSearchHeightShared, sectionHeights]);
|
|
1334
|
-
const measureHeader =
|
|
1479
|
+
const measureHeader = useCallback9(
|
|
1335
1480
|
(index, pageY, height) => {
|
|
1336
1481
|
const contentY = pageY + scrollPosition.value;
|
|
1337
1482
|
positionsCache.current[index] = contentY;
|
|
@@ -1341,7 +1486,7 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
1341
1486
|
},
|
|
1342
1487
|
[scrollPosition, sectionHeights, sectionYPositions]
|
|
1343
1488
|
);
|
|
1344
|
-
const resetPositions =
|
|
1489
|
+
const resetPositions = useCallback9(
|
|
1345
1490
|
(count) => {
|
|
1346
1491
|
positionsCache.current = Array.from({ length: count }, () => -1);
|
|
1347
1492
|
sectionYPositions.value = positionsCache.current.slice();
|
|
@@ -1354,17 +1499,17 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
1354
1499
|
}
|
|
1355
1500
|
|
|
1356
1501
|
// src/SectionList.tsx
|
|
1357
|
-
import { Fragment as Fragment5, jsx as
|
|
1502
|
+
import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1358
1503
|
var AnimatedSectionList = Animated7.createAnimatedComponent(RNSectionList);
|
|
1359
1504
|
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 }) => {
|
|
1360
|
-
const scrollView =
|
|
1505
|
+
const scrollView = useRef11(null);
|
|
1361
1506
|
const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props;
|
|
1362
1507
|
const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, contentPadding, footerFixed, headerFixed, headerHeight } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, hideUntilMeasured: true, keyboardAware, pullSearchHeight, style });
|
|
1363
1508
|
const { listGeneration, onListUnmount } = useContext14(ScrollViewContext);
|
|
1364
|
-
const capturedGeneration =
|
|
1365
|
-
|
|
1509
|
+
const capturedGeneration = useSharedValue10(-1);
|
|
1510
|
+
useLayoutEffect9(() => {
|
|
1366
1511
|
const generation = listGeneration.value;
|
|
1367
|
-
if (
|
|
1512
|
+
if (Platform8.OS === "web") {
|
|
1368
1513
|
capturedGeneration.value = generation;
|
|
1369
1514
|
return;
|
|
1370
1515
|
}
|
|
@@ -1375,15 +1520,15 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1375
1520
|
}, [capturedGeneration, listGeneration]);
|
|
1376
1521
|
const usesCustomSticky = stickySectionHeadersEnabled && renderSectionHeader != null;
|
|
1377
1522
|
const { activeIndex, clipStyle, measureHeader, overlayStyle, resetPositions } = useStickyHeaders(headerFixed, usesCustomSticky);
|
|
1378
|
-
|
|
1523
|
+
useLayoutEffect9(() => {
|
|
1379
1524
|
if (usesCustomSticky) resetPositions(sections.length);
|
|
1380
1525
|
}, [sections, usesCustomSticky, resetPositions, headerHeight]);
|
|
1381
|
-
const sectionViewRefs =
|
|
1382
|
-
const wrappedRenderSectionHeader =
|
|
1526
|
+
const sectionViewRefs = useRef11(/* @__PURE__ */ new Map());
|
|
1527
|
+
const wrappedRenderSectionHeader = useMemo7(() => {
|
|
1383
1528
|
if (!usesCustomSticky) return renderSectionHeader ?? void 0;
|
|
1384
1529
|
return (info) => {
|
|
1385
1530
|
const idx = sections.findIndex((s) => s === info.section);
|
|
1386
|
-
return /* @__PURE__ */
|
|
1531
|
+
return /* @__PURE__ */ jsx12(
|
|
1387
1532
|
View7,
|
|
1388
1533
|
{
|
|
1389
1534
|
ref: (el) => {
|
|
@@ -1400,8 +1545,8 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1400
1545
|
);
|
|
1401
1546
|
};
|
|
1402
1547
|
}, [usesCustomSticky, renderSectionHeader, sections, measureHeader]);
|
|
1403
|
-
|
|
1404
|
-
const scrollTo =
|
|
1548
|
+
useLayoutEffect9(() => () => onListUnmount(), [onListUnmount]);
|
|
1549
|
+
const scrollTo = useCallback10((offset, animated) => {
|
|
1405
1550
|
scrollView.current?.getScrollResponder()?.scrollTo({ y: offset, animated });
|
|
1406
1551
|
}, []);
|
|
1407
1552
|
const {
|
|
@@ -1419,16 +1564,16 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1419
1564
|
pullSearchHeight,
|
|
1420
1565
|
scrollTo
|
|
1421
1566
|
});
|
|
1422
|
-
const activeListHeader =
|
|
1567
|
+
const activeListHeader = useMemo7(() => {
|
|
1423
1568
|
if (!renderFilters) return pullSearchHeader;
|
|
1424
1569
|
const Inner = pullSearchHeader;
|
|
1425
|
-
return () => /* @__PURE__ */
|
|
1426
|
-
Inner ? typeof Inner === "function" ? /* @__PURE__ */
|
|
1570
|
+
return () => /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
1571
|
+
Inner ? typeof Inner === "function" ? /* @__PURE__ */ jsx12(Inner, {}) : Inner : null,
|
|
1427
1572
|
renderFilters
|
|
1428
1573
|
] });
|
|
1429
1574
|
}, [pullSearchHeader, renderFilters]);
|
|
1430
|
-
const pullSearchSettled =
|
|
1431
|
-
|
|
1575
|
+
const pullSearchSettled = useRef11(false);
|
|
1576
|
+
useEffect8(() => {
|
|
1432
1577
|
if (!usesCustomSticky || activeListHeader == null || pullSearchSettled.current) return;
|
|
1433
1578
|
pullSearchSettled.current = true;
|
|
1434
1579
|
const handle = requestAnimationFrame(() => {
|
|
@@ -1440,24 +1585,24 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1440
1585
|
});
|
|
1441
1586
|
return () => cancelAnimationFrame(handle);
|
|
1442
1587
|
}, [activeListHeader, usesCustomSticky, measureHeader]);
|
|
1443
|
-
const contentContainerStyle =
|
|
1588
|
+
const contentContainerStyle = useMemo7(() => [{ minHeight: Dimensions4.get("window").height - contentInset.top - contentInset.bottom + pullSearchMinHeight }, externalContentContainerStyle, contentPadding], [contentInset.bottom, contentInset.top, contentPadding, externalContentContainerStyle, pullSearchMinHeight]);
|
|
1444
1589
|
const handleScroll = useScrollHandler({ capturedGeneration, chipHidden, chipThreshold, footerFixed, headerFixed, listGeneration });
|
|
1445
|
-
const handleScrollToTop =
|
|
1590
|
+
const handleScrollToTop = useCallback10(() => {
|
|
1446
1591
|
const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
|
|
1447
1592
|
scrollView.current?.getScrollResponder()?.scrollTo({ y: offset, animated: true });
|
|
1448
1593
|
}, [contentInset.top, pullSearchHeight]);
|
|
1449
|
-
const handleContentSizeChange =
|
|
1594
|
+
const handleContentSizeChange = useCallback10(
|
|
1450
1595
|
(w, h) => {
|
|
1451
1596
|
if (onContentSizeChange) onContentSizeChange(w, h);
|
|
1452
1597
|
},
|
|
1453
1598
|
[onContentSizeChange]
|
|
1454
1599
|
);
|
|
1455
|
-
const refreshControl =
|
|
1456
|
-
const nativeGesture =
|
|
1457
|
-
const combinedGesture =
|
|
1600
|
+
const refreshControl = useMemo7(() => onRefresh ? /* @__PURE__ */ jsx12(RefreshControl, { onRefresh, refreshing: refreshing ?? false }) : /* @__PURE__ */ jsx12(RefreshControl, {}), [onRefresh, refreshing]);
|
|
1601
|
+
const nativeGesture = useMemo7(() => Gesture4.Native(), []);
|
|
1602
|
+
const combinedGesture = useMemo7(() => gesture !== void 0 ? Gesture4.Simultaneous(gesture, nativeGesture) : nativeGesture, [gesture, nativeGesture]);
|
|
1458
1603
|
const detectorGesture = gesture !== void 0 ? combinedGesture : void 0;
|
|
1459
|
-
const content = /* @__PURE__ */
|
|
1460
|
-
/* @__PURE__ */
|
|
1604
|
+
const content = /* @__PURE__ */ jsxs8(View7, { style: containerStyle, children: [
|
|
1605
|
+
/* @__PURE__ */ jsx12(
|
|
1461
1606
|
AnimatedSectionList,
|
|
1462
1607
|
{
|
|
1463
1608
|
...passThroughProps,
|
|
@@ -1487,11 +1632,11 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1487
1632
|
},
|
|
1488
1633
|
headerHeight !== null && headerHeight > 0 ? 1 : 0
|
|
1489
1634
|
),
|
|
1490
|
-
hiddenHeader && /* @__PURE__ */
|
|
1491
|
-
/* @__PURE__ */
|
|
1492
|
-
usesCustomSticky && /* @__PURE__ */
|
|
1635
|
+
hiddenHeader && /* @__PURE__ */ jsx12(View7, { pointerEvents: "none", style: styles8.measureContainer, children: hiddenHeader }),
|
|
1636
|
+
/* @__PURE__ */ jsx12(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
|
|
1637
|
+
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] }) }) })
|
|
1493
1638
|
] });
|
|
1494
|
-
return detectorGesture ? /* @__PURE__ */
|
|
1639
|
+
return detectorGesture ? /* @__PURE__ */ jsx12(GestureDetector4, { gesture: detectorGesture, children: content }) : content;
|
|
1495
1640
|
};
|
|
1496
1641
|
var styles8 = {
|
|
1497
1642
|
measureContainer: { left: 0, opacity: 0, position: "absolute", right: 0, top: -9999 },
|
|
@@ -1507,6 +1652,32 @@ var useScrollView = () => {
|
|
|
1507
1652
|
return { progress, progressing, scrollHeight, scrollPosition, setProgress, setProgressing };
|
|
1508
1653
|
};
|
|
1509
1654
|
|
|
1655
|
+
// src/useScrollViewChrome.ts
|
|
1656
|
+
import { useContext as useContext16, useEffect as useEffect9 } from "react";
|
|
1657
|
+
import { useAnimatedStyle as useAnimatedStyle7, useSharedValue as useSharedValue11 } from "react-native-reanimated";
|
|
1658
|
+
var noop = () => {
|
|
1659
|
+
};
|
|
1660
|
+
var useScrollViewChromeStyle = () => {
|
|
1661
|
+
const chrome = useContext16(ScrollViewChromeContext);
|
|
1662
|
+
const fallback = useSharedValue11(0);
|
|
1663
|
+
const offset = chrome?.offset ?? fallback;
|
|
1664
|
+
return useAnimatedStyle7(() => ({ transform: [{ translateY: offset.value }] }), [offset]);
|
|
1665
|
+
};
|
|
1666
|
+
var useScrollViewChromePin = (active) => {
|
|
1667
|
+
const chrome = useContext16(ScrollViewChromeContext);
|
|
1668
|
+
const addPin = chrome?.addPin;
|
|
1669
|
+
const removePin = chrome?.removePin;
|
|
1670
|
+
useEffect9(() => {
|
|
1671
|
+
if (!active || !addPin || !removePin) return void 0;
|
|
1672
|
+
addPin();
|
|
1673
|
+
return removePin;
|
|
1674
|
+
}, [active, addPin, removePin]);
|
|
1675
|
+
};
|
|
1676
|
+
var useScrollViewChromeReveal = () => {
|
|
1677
|
+
const chrome = useContext16(ScrollViewChromeContext);
|
|
1678
|
+
return chrome?.reveal ?? noop;
|
|
1679
|
+
};
|
|
1680
|
+
|
|
1510
1681
|
// src/useScrollViewSettings.ts
|
|
1511
1682
|
var useScrollViewSettings = scrollViewUseSettings;
|
|
1512
1683
|
export {
|
|
@@ -1514,6 +1685,7 @@ export {
|
|
|
1514
1685
|
FlatList,
|
|
1515
1686
|
PullSearch,
|
|
1516
1687
|
ScrollView,
|
|
1688
|
+
ScrollViewChromeProvider,
|
|
1517
1689
|
ScrollViewContext,
|
|
1518
1690
|
ScrollViewFooter,
|
|
1519
1691
|
ScrollViewHeader,
|
|
@@ -1526,5 +1698,8 @@ export {
|
|
|
1526
1698
|
scrollViewReducer,
|
|
1527
1699
|
useKeyboardInset,
|
|
1528
1700
|
useScrollView,
|
|
1701
|
+
useScrollViewChromePin,
|
|
1702
|
+
useScrollViewChromeReveal,
|
|
1703
|
+
useScrollViewChromeStyle,
|
|
1529
1704
|
useScrollViewSettings
|
|
1530
1705
|
};
|