@onekeyfe/react-native-pager-view 3.0.117 → 3.0.119
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 +42 -0
- package/ios/RNCCollapsiblePagerViewComponentView.mm +1886 -64
- package/lib/module/CollapsiblePagerView.js +85 -6
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +23 -0
- package/lib/module/PagerView.web.js +17 -8
- package/lib/typescript/src/CollapsiblePagerView.d.ts +67 -2
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +22 -1
- package/lib/typescript/src/PagerView.web.d.ts +1 -0
- package/package.json +1 -1
- package/src/CollapsiblePagerView.tsx +263 -13
- package/src/CollapsiblePagerViewNativeComponent.ts +23 -0
- package/src/PagerView.web.tsx +26 -7
|
@@ -6,6 +6,7 @@ import CollapsiblePagerViewNativeComponent, {
|
|
|
6
6
|
Commands as CollapsiblePagerViewNativeCommands,
|
|
7
7
|
type NativeProps,
|
|
8
8
|
type OnCollapsibleStateChangedEventData,
|
|
9
|
+
type OnNativeTabPressEventData,
|
|
9
10
|
} from "./CollapsiblePagerViewNativeComponent";
|
|
10
11
|
import type {
|
|
11
12
|
OnPageScrollEventData,
|
|
@@ -22,6 +23,63 @@ export type CollapsiblePagerMountState = Readonly<{
|
|
|
22
23
|
pageKeys: readonly string[];
|
|
23
24
|
}>;
|
|
24
25
|
|
|
26
|
+
export type CollapsiblePagerNativeTabBarItem = Readonly<{
|
|
27
|
+
key: string;
|
|
28
|
+
title: string;
|
|
29
|
+
accessibilityLabel?: string;
|
|
30
|
+
testID?: string;
|
|
31
|
+
}>;
|
|
32
|
+
|
|
33
|
+
export type CollapsiblePagerNativeTabBarStyle = Readonly<{
|
|
34
|
+
height?: number;
|
|
35
|
+
contentPaddingHorizontal?: number;
|
|
36
|
+
itemSpacing?: number;
|
|
37
|
+
fontSize?: number;
|
|
38
|
+
fontFamily?: string;
|
|
39
|
+
backgroundColor?: ReactNative.ColorValue;
|
|
40
|
+
activeTextColor?: ReactNative.ColorValue;
|
|
41
|
+
inactiveTextColor?: ReactNative.ColorValue;
|
|
42
|
+
indicatorColor?: ReactNative.ColorValue;
|
|
43
|
+
indicatorHeight?: number;
|
|
44
|
+
indicatorBottom?: number;
|
|
45
|
+
}>;
|
|
46
|
+
|
|
47
|
+
export type CollapsiblePagerNativeTabBarConfig = Readonly<{
|
|
48
|
+
items: readonly CollapsiblePagerNativeTabBarItem[];
|
|
49
|
+
style?: CollapsiblePagerNativeTabBarStyle;
|
|
50
|
+
}>;
|
|
51
|
+
|
|
52
|
+
export type CollapsiblePagerNativeSubHeaderColumns = Readonly<{
|
|
53
|
+
leading: string;
|
|
54
|
+
middle: string;
|
|
55
|
+
trailing: string;
|
|
56
|
+
}>;
|
|
57
|
+
|
|
58
|
+
export type CollapsiblePagerNativeSubHeaderStyle = Readonly<{
|
|
59
|
+
height?: number;
|
|
60
|
+
tabsHeight?: number;
|
|
61
|
+
contentPaddingHorizontal?: number;
|
|
62
|
+
itemSpacing?: number;
|
|
63
|
+
fontSize?: number;
|
|
64
|
+
columnFontSize?: number;
|
|
65
|
+
trailingColumnWidth?: number;
|
|
66
|
+
columnGap?: number;
|
|
67
|
+
selectedBackgroundColor?: ReactNative.ColorValue;
|
|
68
|
+
}>;
|
|
69
|
+
|
|
70
|
+
export type CollapsiblePagerNativeSubHeaderConfig = Readonly<{
|
|
71
|
+
items: readonly CollapsiblePagerNativeTabBarItem[];
|
|
72
|
+
selectedKey: string;
|
|
73
|
+
columns: CollapsiblePagerNativeSubHeaderColumns;
|
|
74
|
+
style?: CollapsiblePagerNativeSubHeaderStyle;
|
|
75
|
+
}>;
|
|
76
|
+
|
|
77
|
+
export type CollapsiblePagerViewOnNativeTabPressEvent =
|
|
78
|
+
ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>;
|
|
79
|
+
|
|
80
|
+
export type CollapsiblePagerViewOnNativeSubHeaderPressEvent =
|
|
81
|
+
ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>;
|
|
82
|
+
|
|
25
83
|
export interface CollapsiblePagerViewProps
|
|
26
84
|
extends Omit<
|
|
27
85
|
NativeProps,
|
|
@@ -30,6 +88,22 @@ export interface CollapsiblePagerViewProps
|
|
|
30
88
|
| "stickyHeaderHeight"
|
|
31
89
|
| "pageKeys"
|
|
32
90
|
| "retainedPages"
|
|
91
|
+
| "nativeTabBarItems"
|
|
92
|
+
| "nativeTabBarHeight"
|
|
93
|
+
| "nativeTabBarContentPaddingHorizontal"
|
|
94
|
+
| "nativeTabBarItemSpacing"
|
|
95
|
+
| "nativeTabBarFontSize"
|
|
96
|
+
| "nativeTabBarFontFamily"
|
|
97
|
+
| "nativeTabBarBackgroundColor"
|
|
98
|
+
| "nativeTabBarActiveTextColor"
|
|
99
|
+
| "nativeTabBarInactiveTextColor"
|
|
100
|
+
| "nativeTabBarIndicatorColor"
|
|
101
|
+
| "nativeTabBarIndicatorHeight"
|
|
102
|
+
| "nativeTabBarIndicatorBottom"
|
|
103
|
+
| "nativeSubHeaderConfig"
|
|
104
|
+
| "nativeSubHeaderSelectedBackgroundColor"
|
|
105
|
+
| "onNativeTabPress"
|
|
106
|
+
| "onNativeSubHeaderPress"
|
|
33
107
|
| "layoutDirection"
|
|
34
108
|
> {
|
|
35
109
|
/** Collapsible content rendered above the sticky bar. */
|
|
@@ -40,6 +114,11 @@ export interface CollapsiblePagerViewProps
|
|
|
40
114
|
headerHeight: number;
|
|
41
115
|
/** Measured sticky bar height. */
|
|
42
116
|
stickyHeaderHeight: number;
|
|
117
|
+
/**
|
|
118
|
+
* Lets the active iOS list own vertical gestures that begin on pager headers.
|
|
119
|
+
* Defaults to false and currently has no effect on Android or Web.
|
|
120
|
+
*/
|
|
121
|
+
nativeSmoothHeaderScrollEnabled?: boolean;
|
|
43
122
|
/**
|
|
44
123
|
* Number of pages retained on either side of the selected page. Page slots
|
|
45
124
|
* remain stable, while distant React/native list subtrees are really
|
|
@@ -47,12 +126,21 @@ export interface CollapsiblePagerViewProps
|
|
|
47
126
|
*/
|
|
48
127
|
pageRetentionDistance?: number;
|
|
49
128
|
layoutDirection?: "ltr" | "rtl" | "locale";
|
|
129
|
+
/** Optional native tab bar. It is currently rendered on iOS only. */
|
|
130
|
+
nativeTabBar?: CollapsiblePagerNativeTabBarConfig;
|
|
131
|
+
onNativeTabPress?: (event: CollapsiblePagerViewOnNativeTabPressEvent) => void;
|
|
132
|
+
/** Optional native secondary sticky header. It is currently rendered on iOS only. */
|
|
133
|
+
nativeSubHeader?: CollapsiblePagerNativeSubHeaderConfig;
|
|
134
|
+
onNativeSubHeaderPress?: (
|
|
135
|
+
event: CollapsiblePagerViewOnNativeSubHeaderPressEvent
|
|
136
|
+
) => void;
|
|
50
137
|
children?: React.ReactNode;
|
|
51
138
|
onMountedPagesChanged?: (state: CollapsiblePagerMountState) => void;
|
|
52
139
|
}
|
|
53
140
|
|
|
54
141
|
type State = {
|
|
55
142
|
selectedPage: number;
|
|
143
|
+
transientRetainedPages: readonly number[];
|
|
56
144
|
};
|
|
57
145
|
|
|
58
146
|
const pageIndex = (value: number) => {
|
|
@@ -61,10 +149,7 @@ const pageIndex = (value: number) => {
|
|
|
61
149
|
};
|
|
62
150
|
|
|
63
151
|
const clampedPageIndex = (value: number, pageCount: number) =>
|
|
64
|
-
Math.min(
|
|
65
|
-
Math.max(0, pageIndex(value) ?? 0),
|
|
66
|
-
Math.max(0, pageCount - 1)
|
|
67
|
-
);
|
|
152
|
+
Math.min(Math.max(0, pageIndex(value) ?? 0), Math.max(0, pageCount - 1));
|
|
68
153
|
|
|
69
154
|
const pageKey = (child: React.ReactNode, index: number) => {
|
|
70
155
|
if (React.isValidElement(child) && child.key != null) {
|
|
@@ -87,6 +172,7 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
87
172
|
this.props.initialPage ?? 0,
|
|
88
173
|
React.Children.toArray(this.props.children).length
|
|
89
174
|
),
|
|
175
|
+
transientRetainedPages: [],
|
|
90
176
|
};
|
|
91
177
|
|
|
92
178
|
private nativeRef: React.ElementRef<
|
|
@@ -95,6 +181,10 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
95
181
|
|
|
96
182
|
private lastMountSignature: string | null = null;
|
|
97
183
|
|
|
184
|
+
private nativeTabCommandId = 0;
|
|
185
|
+
|
|
186
|
+
private latestNativeTabTarget: number | null = null;
|
|
187
|
+
|
|
98
188
|
componentDidMount() {
|
|
99
189
|
this.notifyMountedPagesChanged();
|
|
100
190
|
}
|
|
@@ -117,7 +207,11 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
117
207
|
position >= 0 &&
|
|
118
208
|
position < this.pages().length
|
|
119
209
|
) {
|
|
120
|
-
|
|
210
|
+
if (this.nativeTabBarEnabled()) {
|
|
211
|
+
this.dispatchNativeTabPageCommand(position, true);
|
|
212
|
+
} else {
|
|
213
|
+
CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, position);
|
|
214
|
+
}
|
|
121
215
|
}
|
|
122
216
|
};
|
|
123
217
|
|
|
@@ -129,10 +223,14 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
129
223
|
position >= 0 &&
|
|
130
224
|
position < this.pages().length
|
|
131
225
|
) {
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
|
|
226
|
+
if (this.nativeTabBarEnabled()) {
|
|
227
|
+
this.dispatchNativeTabPageCommand(position, false);
|
|
228
|
+
} else {
|
|
229
|
+
CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(
|
|
230
|
+
this.nativeRef,
|
|
231
|
+
position
|
|
232
|
+
);
|
|
233
|
+
}
|
|
136
234
|
}
|
|
137
235
|
};
|
|
138
236
|
|
|
@@ -149,6 +247,40 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
149
247
|
return React.Children.toArray(this.props.children);
|
|
150
248
|
}
|
|
151
249
|
|
|
250
|
+
private nativeTabBarEnabled() {
|
|
251
|
+
return Platform.OS === "ios" && !!this.props.nativeTabBar?.items.length;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private dispatchNativeTabPageCommand(position: number, animated: boolean) {
|
|
255
|
+
const commandId = ++this.nativeTabCommandId;
|
|
256
|
+
this.latestNativeTabTarget = position;
|
|
257
|
+
this.setState(
|
|
258
|
+
(state) => ({
|
|
259
|
+
transientRetainedPages: state.transientRetainedPages.includes(position)
|
|
260
|
+
? state.transientRetainedPages
|
|
261
|
+
: [...state.transientRetainedPages, position],
|
|
262
|
+
}),
|
|
263
|
+
() => {
|
|
264
|
+
requestAnimationFrame(() => {
|
|
265
|
+
if (commandId !== this.nativeTabCommandId || !this.nativeRef) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (animated) {
|
|
269
|
+
CollapsiblePagerViewNativeCommands.setPage(
|
|
270
|
+
this.nativeRef,
|
|
271
|
+
position
|
|
272
|
+
);
|
|
273
|
+
} else {
|
|
274
|
+
CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(
|
|
275
|
+
this.nativeRef,
|
|
276
|
+
position
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
152
284
|
private retentionDistance() {
|
|
153
285
|
return Math.max(0, Math.floor(this.props.pageRetentionDistance ?? 1));
|
|
154
286
|
}
|
|
@@ -161,7 +293,10 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
161
293
|
);
|
|
162
294
|
const mounted: number[] = [];
|
|
163
295
|
for (let index = 0; index < pageCount; index += 1) {
|
|
164
|
-
if (
|
|
296
|
+
if (
|
|
297
|
+
Math.abs(index - selected) <= distance ||
|
|
298
|
+
this.state.transientRetainedPages.includes(index)
|
|
299
|
+
) {
|
|
165
300
|
mounted.push(index);
|
|
166
301
|
}
|
|
167
302
|
}
|
|
@@ -193,12 +328,41 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
193
328
|
event.nativeEvent.position,
|
|
194
329
|
this.pages().length
|
|
195
330
|
);
|
|
196
|
-
if (
|
|
197
|
-
|
|
331
|
+
if (
|
|
332
|
+
position !== this.state.selectedPage ||
|
|
333
|
+
this.state.transientRetainedPages.length > 0
|
|
334
|
+
) {
|
|
335
|
+
const pendingTarget = this.latestNativeTabTarget;
|
|
336
|
+
const transitionComplete = pendingTarget === position;
|
|
337
|
+
if (transitionComplete) {
|
|
338
|
+
this.latestNativeTabTarget = null;
|
|
339
|
+
}
|
|
340
|
+
this.setState(
|
|
341
|
+
{
|
|
342
|
+
selectedPage: position,
|
|
343
|
+
transientRetainedPages:
|
|
344
|
+
!transitionComplete && pendingTarget !== null
|
|
345
|
+
? [pendingTarget]
|
|
346
|
+
: [],
|
|
347
|
+
},
|
|
348
|
+
this.notifyMountedPagesChanged
|
|
349
|
+
);
|
|
198
350
|
}
|
|
199
351
|
this.props.onPageSelected?.(event);
|
|
200
352
|
};
|
|
201
353
|
|
|
354
|
+
private onNativeTabPress = (
|
|
355
|
+
event: ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>
|
|
356
|
+
) => {
|
|
357
|
+
this.props.onNativeTabPress?.(event);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
private onNativeSubHeaderPress = (
|
|
361
|
+
event: ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>
|
|
362
|
+
) => {
|
|
363
|
+
this.props.onNativeSubHeaderPress?.(event);
|
|
364
|
+
};
|
|
365
|
+
|
|
202
366
|
render() {
|
|
203
367
|
const {
|
|
204
368
|
children: _children,
|
|
@@ -206,10 +370,16 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
206
370
|
stickyHeader,
|
|
207
371
|
headerHeight,
|
|
208
372
|
stickyHeaderHeight,
|
|
373
|
+
nativeSmoothHeaderScrollEnabled,
|
|
209
374
|
pageRetentionDistance: _pageRetentionDistance,
|
|
210
375
|
onMountedPagesChanged: _onMountedPagesChanged,
|
|
211
376
|
onPageSelected: _onPageSelected,
|
|
377
|
+
nativeTabBar,
|
|
378
|
+
onNativeTabPress: _onNativeTabPress,
|
|
379
|
+
nativeSubHeader,
|
|
380
|
+
onNativeSubHeaderPress: _onNativeSubHeaderPress,
|
|
212
381
|
layoutDirection,
|
|
382
|
+
initialPage: _initialPage,
|
|
213
383
|
offscreenPageLimit,
|
|
214
384
|
...nativeProps
|
|
215
385
|
} = this.props;
|
|
@@ -222,6 +392,21 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
222
392
|
? "rtl"
|
|
223
393
|
: "ltr"
|
|
224
394
|
: layoutDirection;
|
|
395
|
+
const nativeTabBarEnabled =
|
|
396
|
+
Platform.OS === "ios" && !!nativeTabBar?.items.length;
|
|
397
|
+
const nativeTabBarStyle = nativeTabBar?.style;
|
|
398
|
+
const nativeSubHeaderEnabled =
|
|
399
|
+
Platform.OS === "ios" && !!nativeSubHeader?.items.length;
|
|
400
|
+
const nativeSubHeaderStyle = nativeSubHeader?.style;
|
|
401
|
+
const nativeSubHeaderConfig = nativeSubHeaderEnabled
|
|
402
|
+
? JSON.stringify({
|
|
403
|
+
...nativeSubHeader,
|
|
404
|
+
style: {
|
|
405
|
+
...nativeSubHeaderStyle,
|
|
406
|
+
selectedBackgroundColor: undefined,
|
|
407
|
+
},
|
|
408
|
+
})
|
|
409
|
+
: undefined;
|
|
225
410
|
|
|
226
411
|
return (
|
|
227
412
|
<CollapsiblePagerViewNativeComponent
|
|
@@ -230,18 +415,83 @@ export class CollapsiblePagerView extends React.PureComponent<
|
|
|
230
415
|
this.nativeRef = ref;
|
|
231
416
|
}}
|
|
232
417
|
layoutDirection={deducedLayoutDirection}
|
|
418
|
+
initialPage={clampedPageIndex(
|
|
419
|
+
this.props.initialPage ?? 0,
|
|
420
|
+
pages.length
|
|
421
|
+
)}
|
|
233
422
|
offscreenPageLimit={Math.max(1, offscreenPageLimit ?? 1)}
|
|
234
423
|
headerHeight={Math.max(0, Math.round(headerHeight))}
|
|
235
424
|
stickyHeaderHeight={Math.max(0, Math.round(stickyHeaderHeight))}
|
|
425
|
+
nativeSmoothHeaderScrollEnabled={nativeSmoothHeaderScrollEnabled}
|
|
236
426
|
pageKeys={JSON.stringify(pageKeys)}
|
|
237
427
|
retainedPages={JSON.stringify([...retained])}
|
|
238
428
|
onPageSelected={this.onPageSelected}
|
|
429
|
+
nativeTabBarItems={
|
|
430
|
+
nativeTabBarEnabled ? JSON.stringify(nativeTabBar.items) : undefined
|
|
431
|
+
}
|
|
432
|
+
nativeTabBarHeight={
|
|
433
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.height ?? 44 : undefined
|
|
434
|
+
}
|
|
435
|
+
nativeTabBarContentPaddingHorizontal={
|
|
436
|
+
nativeTabBarEnabled
|
|
437
|
+
? nativeTabBarStyle?.contentPaddingHorizontal ?? 20
|
|
438
|
+
: undefined
|
|
439
|
+
}
|
|
440
|
+
nativeTabBarItemSpacing={
|
|
441
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.itemSpacing ?? 8 : undefined
|
|
442
|
+
}
|
|
443
|
+
nativeTabBarFontSize={
|
|
444
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.fontSize ?? 16 : undefined
|
|
445
|
+
}
|
|
446
|
+
nativeTabBarFontFamily={
|
|
447
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.fontFamily : undefined
|
|
448
|
+
}
|
|
449
|
+
nativeTabBarBackgroundColor={
|
|
450
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.backgroundColor : undefined
|
|
451
|
+
}
|
|
452
|
+
nativeTabBarActiveTextColor={
|
|
453
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.activeTextColor : undefined
|
|
454
|
+
}
|
|
455
|
+
nativeTabBarInactiveTextColor={
|
|
456
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.inactiveTextColor : undefined
|
|
457
|
+
}
|
|
458
|
+
nativeTabBarIndicatorColor={
|
|
459
|
+
nativeTabBarEnabled ? nativeTabBarStyle?.indicatorColor : undefined
|
|
460
|
+
}
|
|
461
|
+
nativeTabBarIndicatorHeight={
|
|
462
|
+
nativeTabBarEnabled
|
|
463
|
+
? nativeTabBarStyle?.indicatorHeight ?? 2
|
|
464
|
+
: undefined
|
|
465
|
+
}
|
|
466
|
+
nativeTabBarIndicatorBottom={
|
|
467
|
+
nativeTabBarEnabled
|
|
468
|
+
? nativeTabBarStyle?.indicatorBottom ?? 0
|
|
469
|
+
: undefined
|
|
470
|
+
}
|
|
471
|
+
nativeSubHeaderConfig={nativeSubHeaderConfig}
|
|
472
|
+
nativeSubHeaderSelectedBackgroundColor={
|
|
473
|
+
nativeSubHeaderEnabled
|
|
474
|
+
? nativeSubHeaderStyle?.selectedBackgroundColor
|
|
475
|
+
: undefined
|
|
476
|
+
}
|
|
477
|
+
onNativeTabPress={
|
|
478
|
+
nativeTabBarEnabled ? this.onNativeTabPress : undefined
|
|
479
|
+
}
|
|
480
|
+
onNativeSubHeaderPress={
|
|
481
|
+
nativeSubHeaderEnabled ? this.onNativeSubHeaderPress : undefined
|
|
482
|
+
}
|
|
239
483
|
>
|
|
240
484
|
<View
|
|
241
485
|
key="collapsible-header"
|
|
242
486
|
collapsable={false}
|
|
243
487
|
pointerEvents="box-none"
|
|
244
|
-
style={[
|
|
488
|
+
style={[
|
|
489
|
+
styles.slot,
|
|
490
|
+
{
|
|
491
|
+
bottom: undefined,
|
|
492
|
+
height: Math.max(0, Math.round(headerHeight)),
|
|
493
|
+
},
|
|
494
|
+
]}
|
|
245
495
|
>
|
|
246
496
|
{header}
|
|
247
497
|
</View>
|
|
@@ -2,6 +2,7 @@ import type * as React from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
codegenNativeCommands,
|
|
4
4
|
codegenNativeComponent,
|
|
5
|
+
type ColorValue,
|
|
5
6
|
type HostComponent,
|
|
6
7
|
type ViewProps,
|
|
7
8
|
} from "react-native";
|
|
@@ -36,6 +37,11 @@ export type OnCollapsibleStateChangedEventData = Readonly<{
|
|
|
36
37
|
reason: string;
|
|
37
38
|
}>;
|
|
38
39
|
|
|
40
|
+
export type OnNativeTabPressEventData = Readonly<{
|
|
41
|
+
position: Int32;
|
|
42
|
+
key: string;
|
|
43
|
+
}>;
|
|
44
|
+
|
|
39
45
|
/**
|
|
40
46
|
* Internal native props. Consumers should use CollapsiblePagerViewProps from
|
|
41
47
|
* CollapsiblePagerView instead of mounting this host component directly.
|
|
@@ -47,14 +53,31 @@ export interface NativeProps extends ViewProps {
|
|
|
47
53
|
offscreenPageLimit?: Int32;
|
|
48
54
|
// OneKey patch: Preserve nested pager gesture coordination for collapsible pages.
|
|
49
55
|
nestedScrollEnabled?: WithDefault<boolean, false>;
|
|
56
|
+
nativeSmoothHeaderScrollEnabled?: WithDefault<boolean, false>;
|
|
50
57
|
headerHeight?: Int32;
|
|
51
58
|
stickyHeaderHeight?: Int32;
|
|
52
59
|
pageKeys?: string;
|
|
53
60
|
retainedPages?: string;
|
|
61
|
+
nativeTabBarItems?: string;
|
|
62
|
+
nativeTabBarHeight?: Double;
|
|
63
|
+
nativeTabBarContentPaddingHorizontal?: Double;
|
|
64
|
+
nativeTabBarItemSpacing?: Double;
|
|
65
|
+
nativeTabBarFontSize?: Double;
|
|
66
|
+
nativeTabBarFontFamily?: string;
|
|
67
|
+
nativeTabBarBackgroundColor?: ColorValue;
|
|
68
|
+
nativeTabBarActiveTextColor?: ColorValue;
|
|
69
|
+
nativeTabBarInactiveTextColor?: ColorValue;
|
|
70
|
+
nativeTabBarIndicatorColor?: ColorValue;
|
|
71
|
+
nativeTabBarIndicatorHeight?: Double;
|
|
72
|
+
nativeTabBarIndicatorBottom?: Double;
|
|
73
|
+
nativeSubHeaderConfig?: string;
|
|
74
|
+
nativeSubHeaderSelectedBackgroundColor?: ColorValue;
|
|
54
75
|
onPageScroll?: DirectEventHandler<OnPageScrollEventData>;
|
|
55
76
|
onPageSelected?: DirectEventHandler<OnPageSelectedEventData>;
|
|
56
77
|
onPageScrollStateChanged?: DirectEventHandler<OnPageScrollStateChangedEventData>;
|
|
57
78
|
onCollapsibleStateChanged?: DirectEventHandler<OnCollapsibleStateChangedEventData>;
|
|
79
|
+
onNativeTabPress?: DirectEventHandler<OnNativeTabPressEventData>;
|
|
80
|
+
onNativeSubHeaderPress?: DirectEventHandler<OnNativeTabPressEventData>;
|
|
58
81
|
}
|
|
59
82
|
|
|
60
83
|
type CollapsiblePagerViewNativeType = HostComponent<NativeProps>;
|
package/src/PagerView.web.tsx
CHANGED
|
@@ -43,13 +43,27 @@ type State = Readonly<{
|
|
|
43
43
|
animateTransition: boolean;
|
|
44
44
|
}>;
|
|
45
45
|
|
|
46
|
+
const pageIndex = (value: number) => {
|
|
47
|
+
const index = Math.trunc(value);
|
|
48
|
+
return Number.isFinite(index) ? index : null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const clampedPageIndex = (value: number, pageCount: number) =>
|
|
52
|
+
Math.min(
|
|
53
|
+
Math.max(0, pageIndex(value) ?? 0),
|
|
54
|
+
Math.max(0, pageCount - 1)
|
|
55
|
+
);
|
|
56
|
+
|
|
46
57
|
/**
|
|
47
58
|
* Web fallback for the ordinary PagerView API. All pages stay mounted, matching
|
|
48
59
|
* the package's pre-existing PagerView lifetime contract.
|
|
49
60
|
*/
|
|
50
61
|
export class PagerView extends React.Component<PagerViewProps, State> {
|
|
51
62
|
state: State = {
|
|
52
|
-
selectedPage:
|
|
63
|
+
selectedPage: clampedPageIndex(
|
|
64
|
+
this.props.initialPage ?? 0,
|
|
65
|
+
React.Children.toArray(this.props.children).length
|
|
66
|
+
),
|
|
53
67
|
animateTransition: true,
|
|
54
68
|
};
|
|
55
69
|
|
|
@@ -61,7 +75,7 @@ export class PagerView extends React.Component<PagerViewProps, State> {
|
|
|
61
75
|
this.scrollEnabled = this.props.scrollEnabled ?? true;
|
|
62
76
|
}
|
|
63
77
|
|
|
64
|
-
const pageCount =
|
|
78
|
+
const pageCount = this.pages().length;
|
|
65
79
|
if (pageCount > 0 && this.state.selectedPage >= pageCount) {
|
|
66
80
|
this.setState({
|
|
67
81
|
selectedPage: pageCount - 1,
|
|
@@ -86,10 +100,15 @@ export class PagerView extends React.Component<PagerViewProps, State> {
|
|
|
86
100
|
return { nativeEvent } as ReactNative.NativeSyntheticEvent<T>;
|
|
87
101
|
}
|
|
88
102
|
|
|
103
|
+
private pages() {
|
|
104
|
+
return React.Children.toArray(this.props.children);
|
|
105
|
+
}
|
|
106
|
+
|
|
89
107
|
private selectPage(selectedPage: number, animated: boolean) {
|
|
90
|
-
const pageCount =
|
|
91
|
-
const position =
|
|
108
|
+
const pageCount = this.pages().length;
|
|
109
|
+
const position = pageIndex(selectedPage);
|
|
92
110
|
if (
|
|
111
|
+
position === null ||
|
|
93
112
|
position < 0 ||
|
|
94
113
|
position >= pageCount ||
|
|
95
114
|
position === this.state.selectedPage
|
|
@@ -159,7 +178,7 @@ export class PagerView extends React.Component<PagerViewProps, State> {
|
|
|
159
178
|
if (
|
|
160
179
|
direction === 0 ||
|
|
161
180
|
next < 0 ||
|
|
162
|
-
next >=
|
|
181
|
+
next >= this.pages().length
|
|
163
182
|
) {
|
|
164
183
|
this.props.onPageScrollStateChanged?.(
|
|
165
184
|
this.nativeEvent<PageScrollStateChangedNativeEventData>({
|
|
@@ -173,7 +192,7 @@ export class PagerView extends React.Component<PagerViewProps, State> {
|
|
|
173
192
|
|
|
174
193
|
render() {
|
|
175
194
|
const {
|
|
176
|
-
children,
|
|
195
|
+
children: _children,
|
|
177
196
|
style,
|
|
178
197
|
orientation = "horizontal",
|
|
179
198
|
pageMargin = 0,
|
|
@@ -191,7 +210,7 @@ export class PagerView extends React.Component<PagerViewProps, State> {
|
|
|
191
210
|
onPageScrollStateChanged: _onPageScrollStateChanged,
|
|
192
211
|
...viewProps
|
|
193
212
|
} = this.props;
|
|
194
|
-
const pages =
|
|
213
|
+
const pages = this.pages();
|
|
195
214
|
const vertical = orientation === "vertical";
|
|
196
215
|
const pageExtent = pages.length > 0 ? `${100 / pages.length}%` : "100%";
|
|
197
216
|
const transform = vertical
|