@onekeyfe/react-native-pager-view 3.0.177 → 3.0.179-alpha.20261015
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/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +10 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerViewManager.kt +4 -0
- package/docs/SPEC.md +75 -1
- package/ios/RNCCollapsiblePagerViewComponentView.mm +835 -138
- package/ios/RNCNativeScrollerComponentView.mm +93 -38
- package/ios/RNCPagerViewComponentView.h +7 -0
- package/ios/RNCPagerViewComponentView.mm +34 -0
- package/lib/module/CollapsiblePagerView.js +27 -1
- package/lib/module/CollapsiblePagerView.web.js +4 -0
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/lib/module/NativeScroller.js +105 -82
- package/lib/module/NativeScroller.web.js +2 -0
- package/lib/module/NativeScrollerNativeComponent.ts +2 -0
- package/lib/typescript/src/CollapsiblePagerView.d.ts +10 -1
- package/lib/typescript/src/CollapsiblePagerView.web.d.ts +4 -0
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/NativeScroller.d.ts +4 -0
- package/lib/typescript/src/NativeScrollerNativeComponent.d.ts +2 -0
- package/package.json +2 -2
- package/src/CollapsiblePagerView.tsx +44 -0
- package/src/CollapsiblePagerView.web.tsx +8 -0
- package/src/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/src/NativeScroller.tsx +27 -2
- package/src/NativeScroller.web.tsx +2 -0
- package/src/NativeScrollerNativeComponent.ts +2 -0
|
@@ -7,6 +7,8 @@ export const NativeScroller = /*#__PURE__*/React.forwardRef(function NativeScrol
|
|
|
7
7
|
const {
|
|
8
8
|
dataSet,
|
|
9
9
|
pagerScrollKey: _pagerScrollKey,
|
|
10
|
+
topOverlay: _topOverlay,
|
|
11
|
+
topScrollEdgeEffect: _topScrollEdgeEffect,
|
|
10
12
|
...props
|
|
11
13
|
} = inputProps;
|
|
12
14
|
const webDataProps = {
|
|
@@ -47,6 +47,8 @@ export interface NativeProps extends ViewProps {
|
|
|
47
47
|
contentInsetRight?: WithDefault<Double, 0>;
|
|
48
48
|
contentInsetBottom?: WithDefault<Double, 0>;
|
|
49
49
|
contentInsetLeft?: WithDefault<Double, 0>;
|
|
50
|
+
topScrollEdgeHard?: WithDefault<boolean, false>;
|
|
51
|
+
topOverlayHeight?: WithDefault<Double, 0>;
|
|
50
52
|
refreshEnabled?: WithDefault<boolean, false>;
|
|
51
53
|
refreshing?: WithDefault<boolean, false>;
|
|
52
54
|
refreshTintColor?: ColorValue;
|
|
@@ -55,7 +55,7 @@ export type CollapsiblePagerNativeSubHeaderConfig = Readonly<{
|
|
|
55
55
|
}>;
|
|
56
56
|
export type CollapsiblePagerViewOnNativeTabPressEvent = ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>;
|
|
57
57
|
export type CollapsiblePagerViewOnNativeSubHeaderPressEvent = ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>;
|
|
58
|
-
export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children" | "headerHeight" | "stickyHeaderHeight" | "pageKeys" | "retainedPages" | "nativeTabBarItems" | "nativeTabBarHeight" | "nativeTabBarContentPaddingHorizontal" | "nativeTabBarItemSpacing" | "nativeTabBarFontSize" | "nativeTabBarFontFamily" | "nativeTabBarBackgroundColor" | "nativeTabBarActiveTextColor" | "nativeTabBarInactiveTextColor" | "nativeTabBarIndicatorColor" | "nativeTabBarIndicatorHeight" | "nativeTabBarIndicatorBottom" | "nativeSubHeaderConfig" | "nativeSubHeaderSelectedBackgroundColor" | "onNativeTabPress" | "onNativeSubHeaderPress" | "layoutDirection"> {
|
|
58
|
+
export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children" | "headerHeight" | "stickyHeaderHeight" | "topScrollEdgeHard" | "topOverlayHeight" | "externalTopOverlayTag" | "pageKeys" | "retainedPages" | "nativeTabBarItems" | "nativeTabBarHeight" | "nativeTabBarContentPaddingHorizontal" | "nativeTabBarItemSpacing" | "nativeTabBarFontSize" | "nativeTabBarFontFamily" | "nativeTabBarBackgroundColor" | "nativeTabBarActiveTextColor" | "nativeTabBarInactiveTextColor" | "nativeTabBarIndicatorColor" | "nativeTabBarIndicatorHeight" | "nativeTabBarIndicatorBottom" | "nativeSubHeaderConfig" | "nativeSubHeaderSelectedBackgroundColor" | "onNativeTabPress" | "onNativeSubHeaderPress" | "layoutDirection"> {
|
|
59
59
|
/** Collapsible content rendered above the sticky bar. */
|
|
60
60
|
header: React.ReactNode;
|
|
61
61
|
/** Bar which remains pinned after the header has collapsed. */
|
|
@@ -64,6 +64,14 @@ export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children"
|
|
|
64
64
|
headerHeight: number;
|
|
65
65
|
/** Measured sticky bar height. */
|
|
66
66
|
stickyHeaderHeight: number;
|
|
67
|
+
/** Fixed content above the collapsible header on iOS 26 and newer. */
|
|
68
|
+
topOverlay?: React.ReactNode;
|
|
69
|
+
/** Existing fixed header shared with a parent pager on iOS 26 and newer. */
|
|
70
|
+
externalTopOverlayTag?: number;
|
|
71
|
+
/** Enables UIKit's hard top scroll-edge effect on iOS 26 and newer. */
|
|
72
|
+
topScrollEdgeEffect?: "hard";
|
|
73
|
+
/** Effective appearance of the fixed overlay or pinned sticky bar. */
|
|
74
|
+
topOverlayColorScheme?: "light" | "dark";
|
|
67
75
|
/**
|
|
68
76
|
* Lets the active native list own vertical gestures that begin on pager headers.
|
|
69
77
|
* Defaults to false and has no effect on Web.
|
|
@@ -93,6 +101,7 @@ export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children"
|
|
|
93
101
|
type State = {
|
|
94
102
|
selectedPage: number;
|
|
95
103
|
transientRetainedPages: readonly number[];
|
|
104
|
+
topOverlayHeight: number;
|
|
96
105
|
};
|
|
97
106
|
/**
|
|
98
107
|
* Pager variant whose vertical header coordination is performed by the native
|
|
@@ -39,6 +39,10 @@ export interface CollapsiblePagerViewProps extends Omit<WebCollapsiblePagerNativ
|
|
|
39
39
|
stickyHeader: React.ReactNode;
|
|
40
40
|
headerHeight: number;
|
|
41
41
|
stickyHeaderHeight: number;
|
|
42
|
+
topOverlay?: React.ReactNode;
|
|
43
|
+
topScrollEdgeEffect?: "hard";
|
|
44
|
+
topOverlayColorScheme?: "light" | "dark";
|
|
45
|
+
externalTopOverlayTag?: number;
|
|
42
46
|
pageRetentionDistance?: number;
|
|
43
47
|
layoutDirection?: "ltr" | "rtl" | "locale";
|
|
44
48
|
children?: React.ReactNode;
|
|
@@ -26,6 +26,9 @@ export type OnNativeTabPressEventData = Readonly<{
|
|
|
26
26
|
position: Int32;
|
|
27
27
|
key: string;
|
|
28
28
|
}>;
|
|
29
|
+
export type OnScrollEdgeCapabilityEventData = Readonly<{
|
|
30
|
+
available: boolean;
|
|
31
|
+
}>;
|
|
29
32
|
/**
|
|
30
33
|
* Internal native props. Consumers should use CollapsiblePagerViewProps from
|
|
31
34
|
* CollapsiblePagerView instead of mounting this host component directly.
|
|
@@ -39,6 +42,10 @@ export interface NativeProps extends ViewProps {
|
|
|
39
42
|
nativeSmoothHeaderScrollEnabled?: WithDefault<boolean, false>;
|
|
40
43
|
headerHeight?: Int32;
|
|
41
44
|
stickyHeaderHeight?: Int32;
|
|
45
|
+
topScrollEdgeHard?: WithDefault<boolean, false>;
|
|
46
|
+
topOverlayColorScheme?: string;
|
|
47
|
+
topOverlayHeight?: WithDefault<Double, 0>;
|
|
48
|
+
externalTopOverlayTag?: WithDefault<Int32, 0>;
|
|
42
49
|
pageKeys?: string;
|
|
43
50
|
retainedPages?: string;
|
|
44
51
|
nativeTabBarItems?: string;
|
|
@@ -61,6 +68,7 @@ export interface NativeProps extends ViewProps {
|
|
|
61
68
|
onCollapsibleStateChanged?: DirectEventHandler<OnCollapsibleStateChangedEventData>;
|
|
62
69
|
onNativeTabPress?: DirectEventHandler<OnNativeTabPressEventData>;
|
|
63
70
|
onNativeSubHeaderPress?: DirectEventHandler<OnNativeTabPressEventData>;
|
|
71
|
+
onScrollEdgeCapability?: DirectEventHandler<OnScrollEdgeCapabilityEventData>;
|
|
64
72
|
}
|
|
65
73
|
type CollapsiblePagerViewNativeType = HostComponent<NativeProps>;
|
|
66
74
|
export interface NativeCommands {
|
|
@@ -5,6 +5,10 @@ export declare const NATIVE_SCROLLER_NATIVE_ID_PREFIX = "rnc-collapsible-pager-n
|
|
|
5
5
|
/** Supported vertical subset; horizontal, snapping, zoom and sticky rows are not supported. */
|
|
6
6
|
export interface NativeScrollerProps extends ViewProps, Pick<ScrollViewProps, "contentContainerStyle" | "onContentSizeChange" | "scrollEnabled" | "nestedScrollEnabled" | "showsVerticalScrollIndicator" | "showsHorizontalScrollIndicator" | "bounces" | "alwaysBounceVertical" | "contentInset" | "keyboardDismissMode" | "keyboardShouldPersistTaps" | "scrollEventThrottle" | "decelerationRate" | "onScroll" | "onScrollBeginDrag" | "onScrollEndDrag" | "onMomentumScrollBegin" | "onMomentumScrollEnd"> {
|
|
7
7
|
pagerScrollKey?: string;
|
|
8
|
+
/** Fixed overlay above scrolling content on iOS 26 and newer. */
|
|
9
|
+
topOverlay?: React.ReactNode;
|
|
10
|
+
/** Enables UIKit's hard top scroll-edge effect on iOS 26 and newer. */
|
|
11
|
+
topScrollEdgeEffect?: "hard";
|
|
8
12
|
/** iOS only. Android retains AndroidX's native fling physics. */
|
|
9
13
|
decelerationRate?: ScrollViewProps["decelerationRate"];
|
|
10
14
|
/** Standard RefreshControl props are mapped to the independently owned native controller. */
|
|
@@ -47,6 +47,8 @@ export interface NativeProps extends ViewProps {
|
|
|
47
47
|
contentInsetRight?: WithDefault<Double, 0>;
|
|
48
48
|
contentInsetBottom?: WithDefault<Double, 0>;
|
|
49
49
|
contentInsetLeft?: WithDefault<Double, 0>;
|
|
50
|
+
topScrollEdgeHard?: WithDefault<boolean, false>;
|
|
51
|
+
topOverlayHeight?: WithDefault<Double, 0>;
|
|
50
52
|
refreshEnabled?: WithDefault<boolean, false>;
|
|
51
53
|
refreshing?: WithDefault<boolean, false>;
|
|
52
54
|
refreshTintColor?: ColorValue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-pager-view",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.179-alpha.20261015",
|
|
4
4
|
"description": "React Native wrapper for Android and iOS ViewPager",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"typescript": "^5.9.2"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"@onekeyfe/react-native-native-logger": "3.0.
|
|
75
|
+
"@onekeyfe/react-native-native-logger": "3.0.179-alpha.20261015",
|
|
76
76
|
"react": "*",
|
|
77
77
|
"react-native": "*"
|
|
78
78
|
},
|
|
@@ -86,6 +86,9 @@ export interface CollapsiblePagerViewProps
|
|
|
86
86
|
| "children"
|
|
87
87
|
| "headerHeight"
|
|
88
88
|
| "stickyHeaderHeight"
|
|
89
|
+
| "topScrollEdgeHard"
|
|
90
|
+
| "topOverlayHeight"
|
|
91
|
+
| "externalTopOverlayTag"
|
|
89
92
|
| "pageKeys"
|
|
90
93
|
| "retainedPages"
|
|
91
94
|
| "nativeTabBarItems"
|
|
@@ -114,6 +117,14 @@ export interface CollapsiblePagerViewProps
|
|
|
114
117
|
headerHeight: number;
|
|
115
118
|
/** Measured sticky bar height. */
|
|
116
119
|
stickyHeaderHeight: number;
|
|
120
|
+
/** Fixed content above the collapsible header on iOS 26 and newer. */
|
|
121
|
+
topOverlay?: React.ReactNode;
|
|
122
|
+
/** Existing fixed header shared with a parent pager on iOS 26 and newer. */
|
|
123
|
+
externalTopOverlayTag?: number;
|
|
124
|
+
/** Enables UIKit's hard top scroll-edge effect on iOS 26 and newer. */
|
|
125
|
+
topScrollEdgeEffect?: "hard";
|
|
126
|
+
/** Effective appearance of the fixed overlay or pinned sticky bar. */
|
|
127
|
+
topOverlayColorScheme?: "light" | "dark";
|
|
117
128
|
/**
|
|
118
129
|
* Lets the active native list own vertical gestures that begin on pager headers.
|
|
119
130
|
* Defaults to false and has no effect on Web.
|
|
@@ -146,6 +157,7 @@ export interface CollapsiblePagerViewProps
|
|
|
146
157
|
type State = {
|
|
147
158
|
selectedPage: number;
|
|
148
159
|
transientRetainedPages: readonly number[];
|
|
160
|
+
topOverlayHeight: number;
|
|
149
161
|
};
|
|
150
162
|
|
|
151
163
|
const pageIndex = (value: number) => {
|
|
@@ -173,6 +185,7 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
173
185
|
State
|
|
174
186
|
> {
|
|
175
187
|
state: State = {
|
|
188
|
+
topOverlayHeight: 0,
|
|
176
189
|
selectedPage: clampedPageIndex(
|
|
177
190
|
this.props.initialPage ?? 0,
|
|
178
191
|
React.Children.toArray(this.props.children).length
|
|
@@ -458,6 +471,10 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
458
471
|
stickyHeader,
|
|
459
472
|
headerHeight,
|
|
460
473
|
stickyHeaderHeight,
|
|
474
|
+
topOverlay,
|
|
475
|
+
externalTopOverlayTag,
|
|
476
|
+
topScrollEdgeEffect,
|
|
477
|
+
topOverlayColorScheme,
|
|
461
478
|
nativeSmoothHeaderScrollEnabled,
|
|
462
479
|
pageRetentionDistance: _pageRetentionDistance,
|
|
463
480
|
onMountedPagesChanged: _onMountedPagesChanged,
|
|
@@ -474,6 +491,10 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
474
491
|
...nativeProps
|
|
475
492
|
} = this.props;
|
|
476
493
|
const pages = this.pages();
|
|
494
|
+
const supportsTopScrollEdge =
|
|
495
|
+
Platform.OS === "ios" && Number(Platform.Version) >= 26;
|
|
496
|
+
const hardScrollEdge = supportsTopScrollEdge && topScrollEdgeEffect === "hard";
|
|
497
|
+
const hasTopOverlay = hardScrollEdge && topOverlay != null;
|
|
477
498
|
const pageKeys = pages.map(pageKey);
|
|
478
499
|
const retained = new Set(this.mountedPages(pages.length));
|
|
479
500
|
const deducedLayoutDirection =
|
|
@@ -514,6 +535,14 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
514
535
|
offscreenPageLimit={Math.max(1, offscreenPageLimit ?? 1)}
|
|
515
536
|
headerHeight={Math.max(0, Math.round(headerHeight))}
|
|
516
537
|
stickyHeaderHeight={Math.max(0, Math.round(stickyHeaderHeight))}
|
|
538
|
+
topScrollEdgeHard={hardScrollEdge}
|
|
539
|
+
topOverlayColorScheme={hardScrollEdge ? topOverlayColorScheme : undefined}
|
|
540
|
+
topOverlayHeight={hasTopOverlay ? this.state.topOverlayHeight : 0}
|
|
541
|
+
externalTopOverlayTag={
|
|
542
|
+
supportsTopScrollEdge && !hasTopOverlay
|
|
543
|
+
? externalTopOverlayTag ?? 0
|
|
544
|
+
: 0
|
|
545
|
+
}
|
|
517
546
|
nativeSmoothHeaderScrollEnabled={nativeSmoothHeaderScrollEnabled}
|
|
518
547
|
pageKeys={JSON.stringify(pageKeys)}
|
|
519
548
|
retainedPages={JSON.stringify([...retained])}
|
|
@@ -603,6 +632,21 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
603
632
|
>
|
|
604
633
|
{stickyHeader}
|
|
605
634
|
</View>
|
|
635
|
+
{hasTopOverlay ? (
|
|
636
|
+
<View
|
|
637
|
+
key="top-overlay"
|
|
638
|
+
collapsable={false}
|
|
639
|
+
style={[styles.slot, { bottom: undefined }]}
|
|
640
|
+
onLayout={(event) => {
|
|
641
|
+
const height = Math.ceil(event.nativeEvent.layout.height);
|
|
642
|
+
if (this.state.topOverlayHeight !== height) {
|
|
643
|
+
this.setState({ topOverlayHeight: height });
|
|
644
|
+
}
|
|
645
|
+
}}
|
|
646
|
+
>
|
|
647
|
+
{topOverlay}
|
|
648
|
+
</View>
|
|
649
|
+
) : null}
|
|
606
650
|
{pages.map((page, index) => (
|
|
607
651
|
<View
|
|
608
652
|
key={pageKeys[index]}
|
|
@@ -66,6 +66,10 @@ export interface CollapsiblePagerViewProps
|
|
|
66
66
|
stickyHeader: React.ReactNode;
|
|
67
67
|
headerHeight: number;
|
|
68
68
|
stickyHeaderHeight: number;
|
|
69
|
+
topOverlay?: React.ReactNode;
|
|
70
|
+
topScrollEdgeEffect?: "hard";
|
|
71
|
+
topOverlayColorScheme?: "light" | "dark";
|
|
72
|
+
externalTopOverlayTag?: number;
|
|
69
73
|
pageRetentionDistance?: number;
|
|
70
74
|
layoutDirection?: "ltr" | "rtl" | "locale";
|
|
71
75
|
children?: React.ReactNode;
|
|
@@ -759,6 +763,10 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
759
763
|
children: _children,
|
|
760
764
|
header,
|
|
761
765
|
stickyHeader,
|
|
766
|
+
topOverlay: _topOverlay,
|
|
767
|
+
topScrollEdgeEffect: _topScrollEdgeEffect,
|
|
768
|
+
topOverlayColorScheme: _topOverlayColorScheme,
|
|
769
|
+
externalTopOverlayTag: _externalTopOverlayTag,
|
|
762
770
|
headerHeight: _headerHeight,
|
|
763
771
|
stickyHeaderHeight: _stickyHeaderHeight,
|
|
764
772
|
pageRetentionDistance: _pageRetentionDistance,
|
|
@@ -43,6 +43,7 @@ export type OnNativeTabPressEventData = Readonly<{
|
|
|
43
43
|
position: Int32;
|
|
44
44
|
key: string;
|
|
45
45
|
}>;
|
|
46
|
+
export type OnScrollEdgeCapabilityEventData = Readonly<{ available: boolean }>;
|
|
46
47
|
|
|
47
48
|
/**
|
|
48
49
|
* Internal native props. Consumers should use CollapsiblePagerViewProps from
|
|
@@ -58,6 +59,10 @@ export interface NativeProps extends ViewProps {
|
|
|
58
59
|
nativeSmoothHeaderScrollEnabled?: WithDefault<boolean, false>;
|
|
59
60
|
headerHeight?: Int32;
|
|
60
61
|
stickyHeaderHeight?: Int32;
|
|
62
|
+
topScrollEdgeHard?: WithDefault<boolean, false>;
|
|
63
|
+
topOverlayColorScheme?: string;
|
|
64
|
+
topOverlayHeight?: WithDefault<Double, 0>;
|
|
65
|
+
externalTopOverlayTag?: WithDefault<Int32, 0>;
|
|
61
66
|
pageKeys?: string;
|
|
62
67
|
retainedPages?: string;
|
|
63
68
|
nativeTabBarItems?: string;
|
|
@@ -80,6 +85,7 @@ export interface NativeProps extends ViewProps {
|
|
|
80
85
|
onCollapsibleStateChanged?: DirectEventHandler<OnCollapsibleStateChangedEventData>;
|
|
81
86
|
onNativeTabPress?: DirectEventHandler<OnNativeTabPressEventData>;
|
|
82
87
|
onNativeSubHeaderPress?: DirectEventHandler<OnNativeTabPressEventData>;
|
|
88
|
+
onScrollEdgeCapability?: DirectEventHandler<OnScrollEdgeCapabilityEventData>;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
type CollapsiblePagerViewNativeType = HostComponent<NativeProps>;
|
package/src/NativeScroller.tsx
CHANGED
|
@@ -44,6 +44,10 @@ export interface NativeScrollerProps
|
|
|
44
44
|
| "onMomentumScrollEnd"
|
|
45
45
|
> {
|
|
46
46
|
pagerScrollKey?: string;
|
|
47
|
+
/** Fixed overlay above scrolling content on iOS 26 and newer. */
|
|
48
|
+
topOverlay?: React.ReactNode;
|
|
49
|
+
/** Enables UIKit's hard top scroll-edge effect on iOS 26 and newer. */
|
|
50
|
+
topScrollEdgeEffect?: "hard";
|
|
47
51
|
/** iOS only. Android retains AndroidX's native fling physics. */
|
|
48
52
|
decelerationRate?: ScrollViewProps["decelerationRate"];
|
|
49
53
|
/** Standard RefreshControl props are mapped to the independently owned native controller. */
|
|
@@ -81,6 +85,8 @@ export const NativeScroller = React.forwardRef<
|
|
|
81
85
|
>(function NativeScroller(
|
|
82
86
|
{
|
|
83
87
|
children,
|
|
88
|
+
topOverlay,
|
|
89
|
+
topScrollEdgeEffect,
|
|
84
90
|
nativeID,
|
|
85
91
|
pagerScrollKey,
|
|
86
92
|
style,
|
|
@@ -109,6 +115,10 @@ export const NativeScroller = React.forwardRef<
|
|
|
109
115
|
const generatedId = React.useId();
|
|
110
116
|
const [contentViewportHeight, setContentViewportHeight] = React.useState(0);
|
|
111
117
|
const [contentSize, setContentSize] = React.useState({ width: 0, height: 0 });
|
|
118
|
+
const [topOverlayHeight, setTopOverlayHeight] = React.useState(0);
|
|
119
|
+
const hasTopOverlay =
|
|
120
|
+
Platform.OS === "ios" && Number(Platform.Version) >= 26 &&
|
|
121
|
+
topScrollEdgeEffect === "hard" && topOverlay != null;
|
|
112
122
|
const [refreshEpoch, requestRefreshSync] = React.useReducer(
|
|
113
123
|
(value: number) => value + 1,
|
|
114
124
|
0
|
|
@@ -187,13 +197,14 @@ export const NativeScroller = React.forwardRef<
|
|
|
187
197
|
);
|
|
188
198
|
|
|
189
199
|
return (
|
|
200
|
+
<View collapsable={false} style={[styles.viewport, style]} onLayout={onLayout}>
|
|
190
201
|
<NativeScrollerHost
|
|
191
202
|
{...props}
|
|
192
203
|
ref={hostRef}
|
|
193
204
|
nativeID={`${NATIVE_SCROLLER_NATIVE_ID_PREFIX}:${
|
|
194
205
|
pagerScrollKey ?? nativeID ?? generatedId
|
|
195
206
|
}`}
|
|
196
|
-
style={
|
|
207
|
+
style={StyleSheet.absoluteFill}
|
|
197
208
|
nestedScrollEnabled={nestedScrollEnabled}
|
|
198
209
|
contentWidth={contentSize.width}
|
|
199
210
|
contentHeight={contentSize.height}
|
|
@@ -201,6 +212,8 @@ export const NativeScroller = React.forwardRef<
|
|
|
201
212
|
contentInsetRight={contentInset?.right ?? 0}
|
|
202
213
|
contentInsetBottom={contentInset?.bottom ?? 0}
|
|
203
214
|
contentInsetLeft={contentInset?.left ?? 0}
|
|
215
|
+
topScrollEdgeHard={hasTopOverlay}
|
|
216
|
+
topOverlayHeight={hasTopOverlay ? topOverlayHeight : 0}
|
|
204
217
|
decelerationRate={rate}
|
|
205
218
|
keyboardShouldPersistTaps={persistTaps}
|
|
206
219
|
refreshEnabled={Boolean(refresh) && refresh?.enabled !== false}
|
|
@@ -219,7 +232,6 @@ export const NativeScroller = React.forwardRef<
|
|
|
219
232
|
requestRefreshSync();
|
|
220
233
|
}
|
|
221
234
|
}}
|
|
222
|
-
onLayout={onLayout}
|
|
223
235
|
onContentViewportChange={(event) => {
|
|
224
236
|
const height = event.nativeEvent.height;
|
|
225
237
|
if (!Number.isFinite(height) || height < 0) return;
|
|
@@ -306,6 +318,19 @@ export const NativeScroller = React.forwardRef<
|
|
|
306
318
|
{children}
|
|
307
319
|
</View>
|
|
308
320
|
</NativeScrollerHost>
|
|
321
|
+
{hasTopOverlay ? (
|
|
322
|
+
<View
|
|
323
|
+
collapsable={false}
|
|
324
|
+
style={{ position: "absolute", top: 0, left: 0, right: 0 }}
|
|
325
|
+
onLayout={(event) => {
|
|
326
|
+
const height = Math.ceil(event.nativeEvent.layout.height);
|
|
327
|
+
setTopOverlayHeight((previous) => previous === height ? previous : height);
|
|
328
|
+
}}
|
|
329
|
+
>
|
|
330
|
+
{topOverlay}
|
|
331
|
+
</View>
|
|
332
|
+
) : null}
|
|
333
|
+
</View>
|
|
309
334
|
);
|
|
310
335
|
});
|
|
311
336
|
|
|
@@ -14,6 +14,8 @@ export const NativeScroller = React.forwardRef<
|
|
|
14
14
|
const {
|
|
15
15
|
dataSet,
|
|
16
16
|
pagerScrollKey: _pagerScrollKey,
|
|
17
|
+
topOverlay: _topOverlay,
|
|
18
|
+
topScrollEdgeEffect: _topScrollEdgeEffect,
|
|
17
19
|
...props
|
|
18
20
|
} = inputProps as NativeScrollerWebProps;
|
|
19
21
|
const webDataProps = {
|
|
@@ -47,6 +47,8 @@ export interface NativeProps extends ViewProps {
|
|
|
47
47
|
contentInsetRight?: WithDefault<Double, 0>;
|
|
48
48
|
contentInsetBottom?: WithDefault<Double, 0>;
|
|
49
49
|
contentInsetLeft?: WithDefault<Double, 0>;
|
|
50
|
+
topScrollEdgeHard?: WithDefault<boolean, false>;
|
|
51
|
+
topOverlayHeight?: WithDefault<Double, 0>;
|
|
50
52
|
refreshEnabled?: WithDefault<boolean, false>;
|
|
51
53
|
refreshing?: WithDefault<boolean, false>;
|
|
52
54
|
refreshTintColor?: ColorValue;
|