@rific/scroll-view 0.6.3 → 0.6.5
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.js +6 -3
- package/dist/index.mjs +16 -13
- package/package.json +1 -1
- package/src/ScrollViewFooter.tsx +20 -4
package/dist/index.js
CHANGED
|
@@ -1072,11 +1072,13 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
1072
1072
|
const { blur, footerAboveKeyboard, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared, tabBarHeight } = (0, import_react13.useContext)(ScrollViewContext);
|
|
1073
1073
|
const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
|
|
1074
1074
|
const keyboardHeight = useKeyboardInset();
|
|
1075
|
+
const setFooterHeightRef = (0, import_react13.useRef)(setFooterHeight);
|
|
1076
|
+
setFooterHeightRef.current = setFooterHeight;
|
|
1075
1077
|
(0, import_react13.useEffect)(
|
|
1076
1078
|
() => () => {
|
|
1077
|
-
|
|
1079
|
+
setFooterHeightRef.current(null);
|
|
1078
1080
|
},
|
|
1079
|
-
[
|
|
1081
|
+
[]
|
|
1080
1082
|
);
|
|
1081
1083
|
const handleLayout = ({
|
|
1082
1084
|
nativeEvent: {
|
|
@@ -1094,9 +1096,10 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
1094
1096
|
}, [footerHeight, footerFixed, headerHeightShared, pullSearchHeightShared, scrollPosition, snapBackFooterShared, footerOffset]);
|
|
1095
1097
|
const containerPaddingBottom = footerFixed && footerAboveKeyboard ? keyboardHeight : 0;
|
|
1096
1098
|
const rowPaddingBottom = footerFixed && footerAboveKeyboard ? Math.max(insets.bottom - keyboardHeight, 0) : insets.bottom;
|
|
1099
|
+
const { paddingBottom: consumerPaddingBottom, ...restStyle } = style ?? {};
|
|
1097
1100
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native_reanimated11.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, { bottom: tabBarHeight, paddingBottom: containerPaddingBottom }, footerStyle], children: [
|
|
1098
1101
|
(footerHeight ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper3.BlurView, { blur, style: import_react_native11.StyleSheet.absoluteFill }),
|
|
1099
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native11.View, { style: [styles6.row, { paddingBottom: rowPaddingBottom }
|
|
1102
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native11.View, { style: [styles6.row, restStyle, { paddingBottom: rowPaddingBottom + (typeof consumerPaddingBottom === "number" ? consumerPaddingBottom : 0) }], children })
|
|
1100
1103
|
] });
|
|
1101
1104
|
};
|
|
1102
1105
|
var styles6 = import_react_native11.StyleSheet.create({
|
package/dist/index.mjs
CHANGED
|
@@ -1005,7 +1005,7 @@ var ScrollView = memo3(ScrollViewInner);
|
|
|
1005
1005
|
|
|
1006
1006
|
// src/ScrollViewFooter.tsx
|
|
1007
1007
|
import { BlurView as BlurView2 } from "@rific/auto-paper";
|
|
1008
|
-
import { useContext as useContext10, useEffect as useEffect4 } from "react";
|
|
1008
|
+
import { useContext as useContext10, useEffect as useEffect4, useRef as useRef7 } from "react";
|
|
1009
1009
|
import { StyleSheet as StyleSheet5, View as View5 } from "react-native";
|
|
1010
1010
|
import Animated5, { useAnimatedStyle as useAnimatedStyle4 } from "react-native-reanimated";
|
|
1011
1011
|
import { useSafeAreaInsets as useSafeAreaInsets3 } from "react-native-safe-area-context";
|
|
@@ -1014,11 +1014,13 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
1014
1014
|
const { blur, footerAboveKeyboard, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared, tabBarHeight } = useContext10(ScrollViewContext);
|
|
1015
1015
|
const insets = useSafeAreaInsets3();
|
|
1016
1016
|
const keyboardHeight = useKeyboardInset();
|
|
1017
|
+
const setFooterHeightRef = useRef7(setFooterHeight);
|
|
1018
|
+
setFooterHeightRef.current = setFooterHeight;
|
|
1017
1019
|
useEffect4(
|
|
1018
1020
|
() => () => {
|
|
1019
|
-
|
|
1021
|
+
setFooterHeightRef.current(null);
|
|
1020
1022
|
},
|
|
1021
|
-
[
|
|
1023
|
+
[]
|
|
1022
1024
|
);
|
|
1023
1025
|
const handleLayout = ({
|
|
1024
1026
|
nativeEvent: {
|
|
@@ -1036,6 +1038,7 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
1036
1038
|
}, [footerHeight, footerFixed, headerHeightShared, pullSearchHeightShared, scrollPosition, snapBackFooterShared, footerOffset]);
|
|
1037
1039
|
const containerPaddingBottom = footerFixed && footerAboveKeyboard ? keyboardHeight : 0;
|
|
1038
1040
|
const rowPaddingBottom = footerFixed && footerAboveKeyboard ? Math.max(insets.bottom - keyboardHeight, 0) : insets.bottom;
|
|
1041
|
+
const { paddingBottom: consumerPaddingBottom, ...restStyle } = style ?? {};
|
|
1039
1042
|
return (
|
|
1040
1043
|
// bottom: tabBarHeight (not the styles.footer default of 0) - a consuming app's own persistent
|
|
1041
1044
|
// tab bar (a fixture outside this package's header/footer concepts entirely, same as
|
|
@@ -1043,7 +1046,7 @@ var ScrollViewFooter = ({ children, style }) => {
|
|
|
1043
1046
|
// bar has to clear it rather than rendering flush against 0 and overlapping/hiding behind it.
|
|
1044
1047
|
/* @__PURE__ */ jsxs5(Animated5.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, { bottom: tabBarHeight, paddingBottom: containerPaddingBottom }, footerStyle], children: [
|
|
1045
1048
|
(footerHeight ?? 0) > 0 && /* @__PURE__ */ jsx8(BlurView2, { blur, style: StyleSheet5.absoluteFill }),
|
|
1046
|
-
/* @__PURE__ */ jsx8(View5, { style: [styles6.row, { paddingBottom: rowPaddingBottom }
|
|
1049
|
+
/* @__PURE__ */ jsx8(View5, { style: [styles6.row, restStyle, { paddingBottom: rowPaddingBottom + (typeof consumerPaddingBottom === "number" ? consumerPaddingBottom : 0) }], children })
|
|
1047
1050
|
] })
|
|
1048
1051
|
);
|
|
1049
1052
|
};
|
|
@@ -1153,7 +1156,7 @@ var styles7 = StyleSheet6.create({
|
|
|
1153
1156
|
|
|
1154
1157
|
// src/ScrollViewProvider.tsx
|
|
1155
1158
|
import { useBlur } from "@rific/auto-paper";
|
|
1156
|
-
import { useCallback as useCallback7, useContext as useContext12, useEffect as useEffect5, useMemo as useMemo5, useRef as
|
|
1159
|
+
import { useCallback as useCallback7, useContext as useContext12, useEffect as useEffect5, useMemo as useMemo5, useRef as useRef8, useState as useState5 } from "react";
|
|
1157
1160
|
import { Dimensions as Dimensions3 } from "react-native";
|
|
1158
1161
|
import { useSharedValue as useSharedValue7 } from "react-native-reanimated";
|
|
1159
1162
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
@@ -1169,7 +1172,7 @@ var ScrollViewProvider = ({ blur, children, fixed = false, footerAboveKeyboard =
|
|
|
1169
1172
|
const [progressing, setProgressing] = useState5(false);
|
|
1170
1173
|
const scrollPosition = useSharedValue7(0);
|
|
1171
1174
|
const listGeneration = useSharedValue7(0);
|
|
1172
|
-
const jsListGeneration =
|
|
1175
|
+
const jsListGeneration = useRef8(0);
|
|
1173
1176
|
const headerHeightShared = useSharedValue7(0);
|
|
1174
1177
|
const footerHeightShared = useSharedValue7(0);
|
|
1175
1178
|
const headerOffset = useSharedValue7(0);
|
|
@@ -1240,13 +1243,13 @@ var ScrollViewSettingsProvider = ({ children, onChange, initialValue }) => {
|
|
|
1240
1243
|
};
|
|
1241
1244
|
|
|
1242
1245
|
// src/SectionList.tsx
|
|
1243
|
-
import { memo as memo4, useCallback as useCallback10, useContext as useContext14, useEffect as useEffect6, useLayoutEffect as useLayoutEffect6, useMemo as useMemo7, useRef as
|
|
1246
|
+
import { memo as memo4, useCallback as useCallback10, useContext as useContext14, useEffect as useEffect6, useLayoutEffect as useLayoutEffect6, useMemo as useMemo7, useRef as useRef10 } from "react";
|
|
1244
1247
|
import { Dimensions as Dimensions4, Platform as Platform5, SectionList as RNSectionList, View as View7 } from "react-native";
|
|
1245
1248
|
import { Gesture as Gesture4, GestureDetector as GestureDetector4 } from "react-native-gesture-handler";
|
|
1246
1249
|
import Animated7, { runOnUI as runOnUI3, useSharedValue as useSharedValue9 } from "react-native-reanimated";
|
|
1247
1250
|
|
|
1248
1251
|
// src/internal/useStickyHeaders.ts
|
|
1249
|
-
import { useCallback as useCallback9, useContext as useContext13, useLayoutEffect as useLayoutEffect5, useRef as
|
|
1252
|
+
import { useCallback as useCallback9, useContext as useContext13, useLayoutEffect as useLayoutEffect5, useRef as useRef9, useState as useState7 } from "react";
|
|
1250
1253
|
import { runOnJS as runOnJS4, useAnimatedReaction as useAnimatedReaction2, useAnimatedStyle as useAnimatedStyle6, useSharedValue as useSharedValue8 } from "react-native-reanimated";
|
|
1251
1254
|
import { useSafeAreaInsets as useSafeAreaInsets5 } from "react-native-safe-area-context";
|
|
1252
1255
|
function useStickyHeaders(headerFixed, enabled) {
|
|
@@ -1259,8 +1262,8 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
1259
1262
|
useLayoutEffect5(() => {
|
|
1260
1263
|
contentIndexShared.value = activeIndex;
|
|
1261
1264
|
}, [activeIndex, contentIndexShared]);
|
|
1262
|
-
const positionsCache =
|
|
1263
|
-
const heightsCache =
|
|
1265
|
+
const positionsCache = useRef9([]);
|
|
1266
|
+
const heightsCache = useRef9([]);
|
|
1264
1267
|
useAnimatedReaction2(
|
|
1265
1268
|
() => {
|
|
1266
1269
|
if (!enabled) return -1;
|
|
@@ -1363,7 +1366,7 @@ function useStickyHeaders(headerFixed, enabled) {
|
|
|
1363
1366
|
import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1364
1367
|
var AnimatedSectionList = Animated7.createAnimatedComponent(RNSectionList);
|
|
1365
1368
|
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 }) => {
|
|
1366
|
-
const scrollView =
|
|
1369
|
+
const scrollView = useRef10(null);
|
|
1367
1370
|
const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props;
|
|
1368
1371
|
const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, contentPadding, footerFixed, headerFixed, headerHeight } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, hideUntilMeasured: true, keyboardAware, pullSearchHeight, style });
|
|
1369
1372
|
const { listGeneration, onListUnmount } = useContext14(ScrollViewContext);
|
|
@@ -1384,7 +1387,7 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1384
1387
|
useLayoutEffect6(() => {
|
|
1385
1388
|
if (usesCustomSticky) resetPositions(sections.length);
|
|
1386
1389
|
}, [sections, usesCustomSticky, resetPositions, headerHeight]);
|
|
1387
|
-
const sectionViewRefs =
|
|
1390
|
+
const sectionViewRefs = useRef10(/* @__PURE__ */ new Map());
|
|
1388
1391
|
const wrappedRenderSectionHeader = useMemo7(() => {
|
|
1389
1392
|
if (!usesCustomSticky) return renderSectionHeader ?? void 0;
|
|
1390
1393
|
return (info) => {
|
|
@@ -1433,7 +1436,7 @@ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: exter
|
|
|
1433
1436
|
renderFilters
|
|
1434
1437
|
] });
|
|
1435
1438
|
}, [pullSearchHeader, renderFilters]);
|
|
1436
|
-
const pullSearchSettled =
|
|
1439
|
+
const pullSearchSettled = useRef10(false);
|
|
1437
1440
|
useEffect6(() => {
|
|
1438
1441
|
if (!usesCustomSticky || activeListHeader == null || pullSearchSettled.current) return;
|
|
1439
1442
|
pullSearchSettled.current = true;
|
package/package.json
CHANGED
package/src/ScrollViewFooter.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BlurView } from '@rific/auto-paper'
|
|
2
|
-
import { type ReactNode, useContext, useEffect } from 'react'
|
|
2
|
+
import { type ReactNode, useContext, useEffect, useRef } from 'react'
|
|
3
3
|
import { type LayoutChangeEvent, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
4
4
|
import Animated, { useAnimatedStyle } from 'react-native-reanimated'
|
|
5
5
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
@@ -16,11 +16,21 @@ export const ScrollViewFooter = ({ children, style }: ScrollViewFooterProps) =>
|
|
|
16
16
|
const { blur, footerAboveKeyboard, footerHeight, footerFixed, footerOffset, headerHeightShared, pullSearchHeightShared, scrollPosition, setFooterHeight, snapBackFooterShared, tabBarHeight } = useContext(ScrollViewContext)
|
|
17
17
|
const insets = useSafeAreaInsets()
|
|
18
18
|
const keyboardHeight = useKeyboardInset()
|
|
19
|
+
// setFooterHeight's own identity changes on every real measurement (ScrollViewProvider's
|
|
20
|
+
// useCallback closes over `footerHeight` itself, so setting it recreates the callback). Depending
|
|
21
|
+
// on it directly here re-ran this effect on every measurement too — tearing down the PREVIOUS
|
|
22
|
+
// closure as a "cleanup" and calling ITS setFooterHeight(null) right after the real height had
|
|
23
|
+
// just been set, permanently clobbering it back to null with no further layout event left to
|
|
24
|
+
// recover it (the DOM node's true size never changed, so onLayout never fires again). Reading
|
|
25
|
+
// through a ref sidesteps that: the effect itself only ever runs once, on mount/unmount, so its
|
|
26
|
+
// cleanup fires exactly when it's meant to (a real unmount) rather than after every measurement.
|
|
27
|
+
const setFooterHeightRef = useRef(setFooterHeight)
|
|
28
|
+
setFooterHeightRef.current = setFooterHeight
|
|
19
29
|
useEffect(
|
|
20
30
|
() => () => {
|
|
21
|
-
|
|
31
|
+
setFooterHeightRef.current(null)
|
|
22
32
|
},
|
|
23
|
-
[
|
|
33
|
+
[]
|
|
24
34
|
)
|
|
25
35
|
const handleLayout = ({
|
|
26
36
|
nativeEvent: {
|
|
@@ -65,6 +75,12 @@ export const ScrollViewFooter = ({ children, style }: ScrollViewFooterProps) =>
|
|
|
65
75
|
// padding's growth cancel out exactly, so the content holds still at the safe-area line instead
|
|
66
76
|
// of dropping past it and correcting back up.
|
|
67
77
|
const rowPaddingBottom = footerFixed && footerAboveKeyboard ? Math.max(insets.bottom - keyboardHeight, 0) : insets.bottom
|
|
78
|
+
// A consumer's own `style.paddingBottom` (e.g. tightening the row's vertical rhythm to match a
|
|
79
|
+
// header's actionMargin) is spread after rowPaddingBottom below, so it has to be added to it
|
|
80
|
+
// rather than assigned after it — plain style-array merge would otherwise let it silently
|
|
81
|
+
// replace the safe-area clearance instead of sitting on top of it, leaving the row's real
|
|
82
|
+
// content (buttons, etc.) flush against the home indicator.
|
|
83
|
+
const { paddingBottom: consumerPaddingBottom, ...restStyle } = style ?? {}
|
|
68
84
|
return (
|
|
69
85
|
// bottom: tabBarHeight (not the styles.footer default of 0) - a consuming app's own persistent
|
|
70
86
|
// tab bar (a fixture outside this package's header/footer concepts entirely, same as
|
|
@@ -72,7 +88,7 @@ export const ScrollViewFooter = ({ children, style }: ScrollViewFooterProps) =>
|
|
|
72
88
|
// bar has to clear it rather than rendering flush against 0 and overlapping/hiding behind it.
|
|
73
89
|
<Animated.View onLayout={handleLayout} pointerEvents='box-none' style={[styles.footer, { bottom: tabBarHeight, paddingBottom: containerPaddingBottom }, footerStyle]}>
|
|
74
90
|
{(footerHeight ?? 0) > 0 && <BlurView blur={blur} style={StyleSheet.absoluteFill} />}
|
|
75
|
-
<View style={[styles.row, { paddingBottom: rowPaddingBottom }
|
|
91
|
+
<View style={[styles.row, restStyle, { paddingBottom: rowPaddingBottom + (typeof consumerPaddingBottom === 'number' ? consumerPaddingBottom : 0) }]}>{children}</View>
|
|
76
92
|
</Animated.View>
|
|
77
93
|
)
|
|
78
94
|
}
|