@onekeyfe/react-native-pager-view 3.0.114 → 3.0.116
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 +40 -0
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +630 -0
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +222 -0
- package/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt +3 -1
- package/android/src/main/java/com/reactnativepagerview/PagerViewViewPackage.kt +1 -1
- package/android/src/main/java/com/reactnativepagerview/event/CollapsibleStateChangedEvent.kt +39 -0
- package/ios/RNCCollapsiblePagerViewComponentView.h +9 -0
- package/ios/RNCCollapsiblePagerViewComponentView.mm +991 -0
- package/ios/RNCPagerViewComponentView.mm +4 -2
- package/lib/module/CollapsiblePagerView.js +167 -0
- package/lib/module/CollapsiblePagerView.web.js +478 -0
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +87 -0
- package/lib/module/PagerView.web.js +177 -0
- package/lib/module/index.js +2 -1
- package/lib/module/index.web.js +6 -0
- package/lib/module/usePagerView.js +1 -1
- package/lib/typescript/src/CollapsiblePagerView.d.ts +58 -0
- package/lib/typescript/src/CollapsiblePagerView.web.d.ts +105 -0
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +51 -0
- package/lib/typescript/src/PagerView.web.d.ts +55 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.web.d.ts +5 -0
- package/package.json +5 -2
- package/src/CollapsiblePagerView.tsx +293 -0
- package/src/CollapsiblePagerView.web.tsx +710 -0
- package/src/CollapsiblePagerViewNativeComponent.ts +87 -0
- package/src/PagerView.web.tsx +280 -0
- package/src/index.tsx +1 -0
- package/src/index.web.tsx +12 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
codegenNativeCommands,
|
|
4
|
+
codegenNativeComponent,
|
|
5
|
+
type HostComponent,
|
|
6
|
+
type ViewProps,
|
|
7
|
+
} from "react-native";
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
DirectEventHandler,
|
|
11
|
+
Double,
|
|
12
|
+
Int32,
|
|
13
|
+
WithDefault,
|
|
14
|
+
} from "react-native/Libraries/Types/CodegenTypes";
|
|
15
|
+
|
|
16
|
+
export type OnPageScrollEventData = Readonly<{
|
|
17
|
+
position: Double;
|
|
18
|
+
offset: Double;
|
|
19
|
+
}>;
|
|
20
|
+
|
|
21
|
+
export type OnPageSelectedEventData = Readonly<{
|
|
22
|
+
position: Double;
|
|
23
|
+
}>;
|
|
24
|
+
|
|
25
|
+
export type OnPageScrollStateChangedEventData = Readonly<{
|
|
26
|
+
pageScrollState: "idle" | "dragging" | "settling";
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export type OnCollapsibleStateChangedEventData = Readonly<{
|
|
30
|
+
position: Int32;
|
|
31
|
+
headerOffset: Double;
|
|
32
|
+
nativePageCount: Int32;
|
|
33
|
+
attachedPageCount: Int32;
|
|
34
|
+
observedScrollableCount: Int32;
|
|
35
|
+
retainedPages: string;
|
|
36
|
+
reason: string;
|
|
37
|
+
}>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Internal native props. Consumers should use CollapsiblePagerViewProps from
|
|
41
|
+
* CollapsiblePagerView instead of mounting this host component directly.
|
|
42
|
+
*/
|
|
43
|
+
export interface NativeProps extends ViewProps {
|
|
44
|
+
scrollEnabled?: WithDefault<boolean, true>;
|
|
45
|
+
layoutDirection?: WithDefault<"ltr" | "rtl", "ltr">;
|
|
46
|
+
initialPage?: Int32;
|
|
47
|
+
offscreenPageLimit?: Int32;
|
|
48
|
+
// OneKey patch: Preserve nested pager gesture coordination for collapsible pages.
|
|
49
|
+
nestedScrollEnabled?: WithDefault<boolean, false>;
|
|
50
|
+
headerHeight?: Int32;
|
|
51
|
+
stickyHeaderHeight?: Int32;
|
|
52
|
+
pageKeys?: string;
|
|
53
|
+
retainedPages?: string;
|
|
54
|
+
onPageScroll?: DirectEventHandler<OnPageScrollEventData>;
|
|
55
|
+
onPageSelected?: DirectEventHandler<OnPageSelectedEventData>;
|
|
56
|
+
onPageScrollStateChanged?: DirectEventHandler<OnPageScrollStateChangedEventData>;
|
|
57
|
+
onCollapsibleStateChanged?: DirectEventHandler<OnCollapsibleStateChangedEventData>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type CollapsiblePagerViewNativeType = HostComponent<NativeProps>;
|
|
61
|
+
|
|
62
|
+
export interface NativeCommands {
|
|
63
|
+
setPage: (
|
|
64
|
+
viewRef: React.ElementRef<CollapsiblePagerViewNativeType>,
|
|
65
|
+
selectedPage: Int32
|
|
66
|
+
) => void;
|
|
67
|
+
setPageWithoutAnimation: (
|
|
68
|
+
viewRef: React.ElementRef<CollapsiblePagerViewNativeType>,
|
|
69
|
+
selectedPage: Int32
|
|
70
|
+
) => void;
|
|
71
|
+
setScrollEnabledImperatively: (
|
|
72
|
+
viewRef: React.ElementRef<CollapsiblePagerViewNativeType>,
|
|
73
|
+
scrollEnabled: boolean
|
|
74
|
+
) => void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
78
|
+
supportedCommands: [
|
|
79
|
+
"setPage",
|
|
80
|
+
"setPageWithoutAnimation",
|
|
81
|
+
"setScrollEnabledImperatively",
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export default codegenNativeComponent<NativeProps>(
|
|
86
|
+
"RNCCollapsiblePagerView"
|
|
87
|
+
) as HostComponent<NativeProps>;
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { I18nManager, Keyboard, StyleSheet, View } from "react-native";
|
|
3
|
+
import type * as ReactNative from "react-native";
|
|
4
|
+
|
|
5
|
+
export type PagerViewOnPageScrollEventData = Readonly<{
|
|
6
|
+
position: number;
|
|
7
|
+
offset: number;
|
|
8
|
+
}>;
|
|
9
|
+
|
|
10
|
+
export type PagerViewOnPageSelectedEventData = Readonly<{
|
|
11
|
+
position: number;
|
|
12
|
+
}>;
|
|
13
|
+
|
|
14
|
+
export type PageScrollStateChangedNativeEventData = Readonly<{
|
|
15
|
+
pageScrollState: "idle" | "dragging" | "settling";
|
|
16
|
+
}>;
|
|
17
|
+
|
|
18
|
+
export interface PagerViewProps extends ReactNative.ViewProps {
|
|
19
|
+
scrollEnabled?: boolean;
|
|
20
|
+
layoutDirection?: "ltr" | "rtl" | "locale";
|
|
21
|
+
initialPage?: number;
|
|
22
|
+
orientation?: "horizontal" | "vertical";
|
|
23
|
+
offscreenPageLimit?: number;
|
|
24
|
+
pageMargin?: number;
|
|
25
|
+
overScrollMode?: "auto" | "always" | "never";
|
|
26
|
+
overdrag?: boolean;
|
|
27
|
+
keyboardDismissMode?: "none" | "on-drag";
|
|
28
|
+
scrollSensitivity?: number;
|
|
29
|
+
nestedScrollEnabled?: boolean;
|
|
30
|
+
onPageScroll?: (
|
|
31
|
+
event: ReactNative.NativeSyntheticEvent<PagerViewOnPageScrollEventData>
|
|
32
|
+
) => void;
|
|
33
|
+
onPageSelected?: (
|
|
34
|
+
event: ReactNative.NativeSyntheticEvent<PagerViewOnPageSelectedEventData>
|
|
35
|
+
) => void;
|
|
36
|
+
onPageScrollStateChanged?: (
|
|
37
|
+
event: ReactNative.NativeSyntheticEvent<PageScrollStateChangedNativeEventData>
|
|
38
|
+
) => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type State = Readonly<{
|
|
42
|
+
selectedPage: number;
|
|
43
|
+
animateTransition: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Web fallback for the ordinary PagerView API. All pages stay mounted, matching
|
|
48
|
+
* the package's pre-existing PagerView lifetime contract.
|
|
49
|
+
*/
|
|
50
|
+
export class PagerView extends React.Component<PagerViewProps, State> {
|
|
51
|
+
state: State = {
|
|
52
|
+
selectedPage: Math.max(0, Math.trunc(this.props.initialPage ?? 0)),
|
|
53
|
+
animateTransition: true,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
private pointerStart: Readonly<{ x: number; y: number }> | null = null;
|
|
57
|
+
private scrollEnabled = this.props.scrollEnabled ?? true;
|
|
58
|
+
|
|
59
|
+
componentDidUpdate(previousProps: PagerViewProps) {
|
|
60
|
+
if (previousProps.scrollEnabled !== this.props.scrollEnabled) {
|
|
61
|
+
this.scrollEnabled = this.props.scrollEnabled ?? true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const pageCount = React.Children.count(this.props.children);
|
|
65
|
+
if (pageCount > 0 && this.state.selectedPage >= pageCount) {
|
|
66
|
+
this.setState({
|
|
67
|
+
selectedPage: pageCount - 1,
|
|
68
|
+
animateTransition: false,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public setPage = (selectedPage: number) => {
|
|
74
|
+
this.selectPage(selectedPage, true);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
public setPageWithoutAnimation = (selectedPage: number) => {
|
|
78
|
+
this.selectPage(selectedPage, false);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
public setScrollEnabled = (scrollEnabled: boolean) => {
|
|
82
|
+
this.scrollEnabled = scrollEnabled;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
private nativeEvent<T>(nativeEvent: T) {
|
|
86
|
+
return { nativeEvent } as ReactNative.NativeSyntheticEvent<T>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private selectPage(selectedPage: number, animated: boolean) {
|
|
90
|
+
const pageCount = React.Children.count(this.props.children);
|
|
91
|
+
const position = Math.trunc(selectedPage);
|
|
92
|
+
if (
|
|
93
|
+
position < 0 ||
|
|
94
|
+
position >= pageCount ||
|
|
95
|
+
position === this.state.selectedPage
|
|
96
|
+
) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.props.onPageScrollStateChanged?.(
|
|
101
|
+
this.nativeEvent<PageScrollStateChangedNativeEventData>({
|
|
102
|
+
pageScrollState: animated ? "settling" : "idle",
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
this.setState(
|
|
106
|
+
{ selectedPage: position, animateTransition: animated },
|
|
107
|
+
() => {
|
|
108
|
+
this.props.onPageScroll?.(
|
|
109
|
+
this.nativeEvent<PagerViewOnPageScrollEventData>({
|
|
110
|
+
position,
|
|
111
|
+
offset: 0,
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
this.props.onPageSelected?.(
|
|
115
|
+
this.nativeEvent<PagerViewOnPageSelectedEventData>({ position })
|
|
116
|
+
);
|
|
117
|
+
if (animated) {
|
|
118
|
+
this.props.onPageScrollStateChanged?.(
|
|
119
|
+
this.nativeEvent<PageScrollStateChangedNativeEventData>({
|
|
120
|
+
pageScrollState: "idle",
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private onTouchStart = (event: ReactNative.GestureResponderEvent) => {
|
|
129
|
+
if (!this.scrollEnabled) return;
|
|
130
|
+
this.pointerStart = {
|
|
131
|
+
x: event.nativeEvent.pageX,
|
|
132
|
+
y: event.nativeEvent.pageY,
|
|
133
|
+
};
|
|
134
|
+
if (this.props.keyboardDismissMode === "on-drag") Keyboard.dismiss();
|
|
135
|
+
this.props.onPageScrollStateChanged?.(
|
|
136
|
+
this.nativeEvent<PageScrollStateChangedNativeEventData>({
|
|
137
|
+
pageScrollState: "dragging",
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
private onTouchEnd = (event: ReactNative.GestureResponderEvent) => {
|
|
143
|
+
const start = this.pointerStart;
|
|
144
|
+
this.pointerStart = null;
|
|
145
|
+
if (!start || !this.scrollEnabled) return;
|
|
146
|
+
|
|
147
|
+
const vertical = this.props.orientation === "vertical";
|
|
148
|
+
const delta = vertical
|
|
149
|
+
? event.nativeEvent.pageY - start.y
|
|
150
|
+
: event.nativeEvent.pageX - start.x;
|
|
151
|
+
const isRTL =
|
|
152
|
+
!vertical &&
|
|
153
|
+
(this.props.layoutDirection === "rtl" ||
|
|
154
|
+
((!this.props.layoutDirection ||
|
|
155
|
+
this.props.layoutDirection === "locale") &&
|
|
156
|
+
I18nManager.isRTL));
|
|
157
|
+
const direction = Math.abs(delta) >= 40 ? (delta < 0 ? 1 : -1) : 0;
|
|
158
|
+
const next = this.state.selectedPage + (isRTL ? -direction : direction);
|
|
159
|
+
if (
|
|
160
|
+
direction === 0 ||
|
|
161
|
+
next < 0 ||
|
|
162
|
+
next >= React.Children.count(this.props.children)
|
|
163
|
+
) {
|
|
164
|
+
this.props.onPageScrollStateChanged?.(
|
|
165
|
+
this.nativeEvent<PageScrollStateChangedNativeEventData>({
|
|
166
|
+
pageScrollState: "idle",
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.selectPage(next, true);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
render() {
|
|
175
|
+
const {
|
|
176
|
+
children,
|
|
177
|
+
style,
|
|
178
|
+
orientation = "horizontal",
|
|
179
|
+
pageMargin = 0,
|
|
180
|
+
scrollEnabled: _scrollEnabled,
|
|
181
|
+
initialPage: _initialPage,
|
|
182
|
+
layoutDirection: _layoutDirection,
|
|
183
|
+
offscreenPageLimit: _offscreenPageLimit,
|
|
184
|
+
overScrollMode: _overScrollMode,
|
|
185
|
+
overdrag: _overdrag,
|
|
186
|
+
keyboardDismissMode: _keyboardDismissMode,
|
|
187
|
+
scrollSensitivity: _scrollSensitivity,
|
|
188
|
+
nestedScrollEnabled: _nestedScrollEnabled,
|
|
189
|
+
onPageScroll: _onPageScroll,
|
|
190
|
+
onPageSelected: _onPageSelected,
|
|
191
|
+
onPageScrollStateChanged: _onPageScrollStateChanged,
|
|
192
|
+
...viewProps
|
|
193
|
+
} = this.props;
|
|
194
|
+
const pages = React.Children.toArray(children);
|
|
195
|
+
const vertical = orientation === "vertical";
|
|
196
|
+
const pageExtent = pages.length > 0 ? `${100 / pages.length}%` : "100%";
|
|
197
|
+
const transform = vertical
|
|
198
|
+
? [
|
|
199
|
+
{
|
|
200
|
+
translateY: `${
|
|
201
|
+
(-this.state.selectedPage * 100) / Math.max(1, pages.length)
|
|
202
|
+
}%`,
|
|
203
|
+
},
|
|
204
|
+
]
|
|
205
|
+
: [
|
|
206
|
+
{
|
|
207
|
+
translateX: `${
|
|
208
|
+
(-this.state.selectedPage * 100) / Math.max(1, pages.length)
|
|
209
|
+
}%`,
|
|
210
|
+
},
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<View {...viewProps} style={[styles.root, style]}>
|
|
215
|
+
<View
|
|
216
|
+
style={[
|
|
217
|
+
styles.track,
|
|
218
|
+
vertical ? styles.verticalTrack : styles.horizontalTrack,
|
|
219
|
+
vertical
|
|
220
|
+
? { height: `${Math.max(1, pages.length) * 100}%` }
|
|
221
|
+
: { width: `${Math.max(1, pages.length) * 100}%` },
|
|
222
|
+
{
|
|
223
|
+
transform,
|
|
224
|
+
transitionProperty: "transform",
|
|
225
|
+
transitionDuration: this.state.animateTransition
|
|
226
|
+
? "240ms"
|
|
227
|
+
: "0ms",
|
|
228
|
+
} as never,
|
|
229
|
+
]}
|
|
230
|
+
onTouchStart={this.onTouchStart}
|
|
231
|
+
onTouchEnd={this.onTouchEnd}
|
|
232
|
+
>
|
|
233
|
+
{pages.map((page, index) => (
|
|
234
|
+
<View
|
|
235
|
+
key={React.isValidElement(page) ? page.key ?? index : index}
|
|
236
|
+
style={[
|
|
237
|
+
styles.page,
|
|
238
|
+
vertical
|
|
239
|
+
? { height: pageExtent, paddingVertical: pageMargin / 2 }
|
|
240
|
+
: { width: pageExtent, paddingHorizontal: pageMargin / 2 },
|
|
241
|
+
]}
|
|
242
|
+
>
|
|
243
|
+
{page}
|
|
244
|
+
</View>
|
|
245
|
+
))}
|
|
246
|
+
</View>
|
|
247
|
+
</View>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const styles = StyleSheet.create({
|
|
253
|
+
root: {
|
|
254
|
+
overflow: "hidden",
|
|
255
|
+
},
|
|
256
|
+
track: {
|
|
257
|
+
flex: 1,
|
|
258
|
+
},
|
|
259
|
+
horizontalTrack: {
|
|
260
|
+
flexDirection: "row",
|
|
261
|
+
height: "100%",
|
|
262
|
+
},
|
|
263
|
+
verticalTrack: {
|
|
264
|
+
flexDirection: "column",
|
|
265
|
+
width: "100%",
|
|
266
|
+
},
|
|
267
|
+
page: {
|
|
268
|
+
flexShrink: 0,
|
|
269
|
+
minWidth: 0,
|
|
270
|
+
minHeight: 0,
|
|
271
|
+
overflow: "hidden",
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
export type PagerViewOnPageScrollEvent =
|
|
276
|
+
ReactNative.NativeSyntheticEvent<PagerViewOnPageScrollEventData>;
|
|
277
|
+
export type PagerViewOnPageSelectedEvent =
|
|
278
|
+
ReactNative.NativeSyntheticEvent<PagerViewOnPageSelectedEventData>;
|
|
279
|
+
export type PageScrollStateChangedNativeEvent =
|
|
280
|
+
ReactNative.NativeSyntheticEvent<PageScrollStateChangedNativeEventData>;
|
package/src/index.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import type * as ReactNative from 'react-native';
|
|
|
2
2
|
import { PagerView } from './PagerView';
|
|
3
3
|
export default PagerView;
|
|
4
4
|
export * from './usePagerView';
|
|
5
|
+
export * from './CollapsiblePagerView';
|
|
5
6
|
|
|
6
7
|
import type {
|
|
7
8
|
OnPageScrollEventData as PagerViewOnPageScrollEventData,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { PagerView as default, PagerView } from "./PagerView.web";
|
|
2
|
+
export type {
|
|
3
|
+
PagerViewProps,
|
|
4
|
+
PagerViewOnPageScrollEvent,
|
|
5
|
+
PagerViewOnPageScrollEventData,
|
|
6
|
+
PagerViewOnPageSelectedEvent,
|
|
7
|
+
PagerViewOnPageSelectedEventData,
|
|
8
|
+
PageScrollStateChangedNativeEvent,
|
|
9
|
+
PageScrollStateChangedNativeEventData,
|
|
10
|
+
} from "./PagerView.web";
|
|
11
|
+
export * from "./usePagerView";
|
|
12
|
+
export * from "./CollapsiblePagerView.web";
|