@onekeyfe/react-native-pager-view 6.7.0-2 → 6.7.0-21

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.
Files changed (43) hide show
  1. package/README.md +14 -0
  2. package/android/src/androidTest/AndroidManifest.xml +7 -0
  3. package/android/src/androidTest/java/com/reactnativepagerview/CollapsiblePagerTabReservationTest.kt +306 -0
  4. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +130 -30
  5. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerNativeHeaders.kt +72 -7
  6. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +27 -0
  7. package/android/src/main/java/com/reactnativepagerview/NativeScrollerScrollAwayInsets.kt +19 -0
  8. package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +50 -6
  9. package/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt +8 -2
  10. package/android/src/test/java/com/reactnativepagerview/NativeScrollerScrollAwayInsetsTest.kt +40 -0
  11. package/docs/SPEC.md +257 -10
  12. package/ios/RNCCollapsiblePagerViewComponentView.mm +614 -42
  13. package/ios/RNCNativeScrollerComponentView.h +2 -0
  14. package/ios/RNCNativeScrollerComponentView.mm +42 -0
  15. package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +403 -1
  16. package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +338 -0
  17. package/ios/tests/RNCCollapsiblePagerPressCancellationTests.mm +74 -9
  18. package/ios/tests/RNCCollapsiblePagerRefreshControlTests.mm +50 -0
  19. package/lib/module/CollapsiblePagerView.js +32 -7
  20. package/lib/module/CollapsiblePagerView.web.js +439 -39
  21. package/lib/module/CollapsiblePagerViewNativeComponent.ts +13 -0
  22. package/lib/module/NativeScroller.web.js +16 -3
  23. package/lib/module/WebCollapsiblePagerPage.js +182 -0
  24. package/lib/module/index.js +2 -0
  25. package/lib/module/index.native.js +9 -0
  26. package/lib/module/index.web.js +2 -0
  27. package/lib/typescript/src/CollapsiblePagerView.d.ts +10 -3
  28. package/lib/typescript/src/CollapsiblePagerView.web.d.ts +66 -3
  29. package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +5 -0
  30. package/lib/typescript/src/WebCollapsiblePagerPage.d.ts +42 -0
  31. package/lib/typescript/src/index.d.ts +4 -0
  32. package/lib/typescript/src/index.native.d.ts +13 -0
  33. package/lib/typescript/src/index.web.d.ts +4 -0
  34. package/package.json +6 -4
  35. package/react-native-pager-view.podspec +1 -0
  36. package/src/CollapsiblePagerView.tsx +99 -8
  37. package/src/CollapsiblePagerView.web.tsx +657 -51
  38. package/src/CollapsiblePagerViewNativeComponent.ts +13 -0
  39. package/src/NativeScroller.web.tsx +24 -2
  40. package/src/WebCollapsiblePagerPage.tsx +258 -0
  41. package/src/index.native.tsx +30 -0
  42. package/src/index.tsx +4 -0
  43. package/src/index.web.tsx +4 -0
@@ -32,8 +32,11 @@ export type CollapsiblePagerNativeTabBarItem = Readonly<{
32
32
  }>;
33
33
 
34
34
  export type CollapsiblePagerNativeTabBarStyle = Readonly<{
35
+ variant?: "underline" | "segmented";
35
36
  height?: number;
37
+ trailingReservedWidth?: number;
36
38
  contentPaddingHorizontal?: number;
39
+ contentPaddingVertical?: number;
37
40
  itemSpacing?: number;
38
41
  fontSize?: number;
39
42
  fontFamily?: string;
@@ -94,7 +97,10 @@ export interface CollapsiblePagerViewProps
94
97
  | "retainedPages"
95
98
  | "nativeTabBarItems"
96
99
  | "nativeTabBarHeight"
100
+ | "nativeTabBarVariant"
101
+ | "nativeTabBarTrailingReservedWidth"
97
102
  | "nativeTabBarContentPaddingHorizontal"
103
+ | "nativeTabBarContentPaddingVertical"
98
104
  | "nativeTabBarItemSpacing"
99
105
  | "nativeTabBarFontSize"
100
106
  | "nativeTabBarFontFamily"
@@ -120,6 +126,8 @@ export interface CollapsiblePagerViewProps
120
126
  stickyHeaderHeight: number;
121
127
  /** Fixed content above the collapsible header on iOS 26 and newer. */
122
128
  topOverlay?: React.ReactNode;
129
+ /** Known overlay height to reserve until its first layout measurement. */
130
+ topOverlayHeightHint?: number;
123
131
  /** Existing fixed header shared with a parent pager on iOS 26 and newer. */
124
132
  externalTopOverlayTag?: number;
125
133
  /** Selects UIKit's top scroll-edge effect on iOS 26 and newer. */
@@ -158,7 +166,7 @@ export interface CollapsiblePagerViewProps
158
166
  type State = {
159
167
  selectedPage: number;
160
168
  transientRetainedPages: readonly number[];
161
- topOverlayHeight: number;
169
+ topOverlayHeight: number | null;
162
170
  };
163
171
 
164
172
  const pageIndex = (value: number) => {
@@ -186,7 +194,7 @@ export class CollapsiblePagerView extends React.PureComponent<
186
194
  State
187
195
  > {
188
196
  state: State = {
189
- topOverlayHeight: 0,
197
+ topOverlayHeight: null,
190
198
  selectedPage: clampedPageIndex(
191
199
  this.props.initialPage ?? 0,
192
200
  React.Children.toArray(this.props.children).length
@@ -219,7 +227,22 @@ export class CollapsiblePagerView extends React.PureComponent<
219
227
  this.notifyMountedPagesChanged();
220
228
  }
221
229
 
222
- componentDidUpdate() {
230
+ componentDidUpdate(previousProps: CollapsiblePagerViewProps) {
231
+ const previousOverlayEnabled =
232
+ previousProps.topOverlay != null &&
233
+ (previousProps.topScrollEdgeEffect === "hard" ||
234
+ previousProps.topScrollEdgeEffect === "soft");
235
+ const overlayEnabled =
236
+ this.props.topOverlay != null &&
237
+ (this.props.topScrollEdgeEffect === "hard" ||
238
+ this.props.topScrollEdgeEffect === "soft");
239
+ if (
240
+ previousOverlayEnabled &&
241
+ !overlayEnabled &&
242
+ this.state.topOverlayHeight !== null
243
+ ) {
244
+ this.setState({ topOverlayHeight: null });
245
+ }
223
246
  const pageCount = this.pages().length;
224
247
  const selectedPage = clampedPageIndex(this.state.selectedPage, pageCount);
225
248
  if (selectedPage !== this.state.selectedPage) {
@@ -273,6 +296,22 @@ export class CollapsiblePagerView extends React.PureComponent<
273
296
  );
274
297
  };
275
298
 
299
+ public scrollHeaderBy = (delta: number) => {
300
+ if (this.nativeRef && Number.isFinite(delta))
301
+ CollapsiblePagerViewNativeCommands.scrollHeaderBy(
302
+ this.nativeRef,
303
+ delta
304
+ );
305
+ };
306
+
307
+ public scrollHeaderToOffset = (offset: number) => {
308
+ if (this.nativeRef && Number.isFinite(offset))
309
+ CollapsiblePagerViewNativeCommands.scrollHeaderToOffset(
310
+ this.nativeRef,
311
+ offset
312
+ );
313
+ };
314
+
276
315
  public scrollToStickyTop = (options?: Readonly<{ animated?: boolean }>) => {
277
316
  if (this.nativeRef)
278
317
  CollapsiblePagerViewNativeCommands.scrollToTop(
@@ -302,7 +341,11 @@ export class CollapsiblePagerView extends React.PureComponent<
302
341
  );
303
342
  }
304
343
 
305
- private dispatchNativeTabPageCommand(position: number, animated: boolean) {
344
+ private dispatchNativeTabPageCommand(
345
+ position: number,
346
+ animated: boolean,
347
+ expectedKey?: string
348
+ ) {
306
349
  const commandId = ++this.nativeTabCommandId;
307
350
  this.nativeTabCommandQueuedDuringScroll =
308
351
  this.nativePagerScrollState !== "idle";
@@ -315,7 +358,13 @@ export class CollapsiblePagerView extends React.PureComponent<
315
358
  }),
316
359
  () => {
317
360
  requestAnimationFrame(() => {
318
- if (commandId !== this.nativeTabCommandId || !this.nativeRef) {
361
+ if (
362
+ commandId !== this.nativeTabCommandId ||
363
+ !this.nativeRef ||
364
+ (expectedKey !== undefined &&
365
+ (!this.nativeTabBarEnabled() ||
366
+ this.props.nativeTabBar?.items[position]?.key !== expectedKey))
367
+ ) {
319
368
  return;
320
369
  }
321
370
  this.dispatchedNativeTabTarget = position;
@@ -441,7 +490,13 @@ export class CollapsiblePagerView extends React.PureComponent<
441
490
  ) => {
442
491
  const position = pageIndex(event.nativeEvent.position);
443
492
  if (
444
- position !== null &&
493
+ !this.nativeTabBarEnabled() ||
494
+ position === null ||
495
+ this.props.nativeTabBar?.items[position]?.key !== event.nativeEvent.key
496
+ ) {
497
+ return;
498
+ }
499
+ if (
445
500
  position >= 0 &&
446
501
  position < this.pages().length &&
447
502
  (position !== this.state.selectedPage ||
@@ -453,7 +508,8 @@ export class CollapsiblePagerView extends React.PureComponent<
453
508
  this.dispatchNativeTabPageCommand(
454
509
  position,
455
510
  this.props.nativeTabPressAnimationEnabled ??
456
- Math.abs(position - currentPage) <= 1
511
+ Math.abs(position - currentPage) <= 1,
512
+ event.nativeEvent.key
457
513
  );
458
514
  }
459
515
  this.props.onNativeTabPress?.(event);
@@ -473,6 +529,7 @@ export class CollapsiblePagerView extends React.PureComponent<
473
529
  headerHeight,
474
530
  stickyHeaderHeight,
475
531
  topOverlay,
532
+ topOverlayHeightHint,
476
533
  externalTopOverlayTag,
477
534
  topScrollEdgeEffect,
478
535
  topOverlayColorScheme,
@@ -498,6 +555,11 @@ export class CollapsiblePagerView extends React.PureComponent<
498
555
  supportsTopScrollEdge &&
499
556
  (topScrollEdgeEffect === "hard" || topScrollEdgeEffect === "soft");
500
557
  const hasTopOverlay = scrollEdgeEnabled && topOverlay != null;
558
+ const initialTopOverlayHeight =
559
+ typeof topOverlayHeightHint === "number" &&
560
+ Number.isFinite(topOverlayHeightHint)
561
+ ? Math.max(0, Math.ceil(topOverlayHeightHint))
562
+ : 0;
501
563
  const pageKeys = pages.map(pageKey);
502
564
  const retained = new Set(this.mountedPages(pages.length));
503
565
  const deducedLayoutDirection =
@@ -510,6 +572,22 @@ export class CollapsiblePagerView extends React.PureComponent<
510
572
  (Platform.OS === "ios" || Platform.OS === "android") &&
511
573
  !!nativeTabBar?.items.length;
512
574
  const nativeTabBarStyle = nativeTabBar?.style;
575
+ const requestedContentPaddingVertical =
576
+ nativeTabBarStyle?.contentPaddingVertical;
577
+ const nativeTabBarContentPaddingVertical =
578
+ typeof requestedContentPaddingVertical === "number" &&
579
+ Number.isFinite(requestedContentPaddingVertical) &&
580
+ requestedContentPaddingVertical >= 0
581
+ ? requestedContentPaddingVertical
582
+ : 0;
583
+ const requestedTrailingReservedWidth =
584
+ nativeTabBarStyle?.trailingReservedWidth;
585
+ const nativeTabBarTrailingReservedWidth =
586
+ typeof requestedTrailingReservedWidth === "number" &&
587
+ Number.isFinite(requestedTrailingReservedWidth) &&
588
+ requestedTrailingReservedWidth >= 0
589
+ ? requestedTrailingReservedWidth
590
+ : 0;
513
591
  const nativeSubHeaderEnabled =
514
592
  (Platform.OS === "ios" || Platform.OS === "android") &&
515
593
  !!nativeSubHeader?.items.length;
@@ -542,7 +620,11 @@ export class CollapsiblePagerView extends React.PureComponent<
542
620
  topOverlayColorScheme={
543
621
  scrollEdgeEnabled ? topOverlayColorScheme : undefined
544
622
  }
545
- topOverlayHeight={hasTopOverlay ? this.state.topOverlayHeight : 0}
623
+ topOverlayHeight={
624
+ hasTopOverlay
625
+ ? this.state.topOverlayHeight ?? initialTopOverlayHeight
626
+ : 0
627
+ }
546
628
  externalTopOverlayTag={
547
629
  supportsTopScrollEdge && !hasTopOverlay
548
630
  ? externalTopOverlayTag ?? 0
@@ -559,11 +641,20 @@ export class CollapsiblePagerView extends React.PureComponent<
559
641
  nativeTabBarHeight={
560
642
  nativeTabBarEnabled ? nativeTabBarStyle?.height ?? 44 : undefined
561
643
  }
644
+ nativeTabBarVariant={
645
+ nativeTabBarEnabled ? nativeTabBarStyle?.variant ?? "underline" : undefined
646
+ }
647
+ nativeTabBarTrailingReservedWidth={
648
+ nativeTabBarEnabled ? nativeTabBarTrailingReservedWidth : 0
649
+ }
562
650
  nativeTabBarContentPaddingHorizontal={
563
651
  nativeTabBarEnabled
564
652
  ? nativeTabBarStyle?.contentPaddingHorizontal ?? 20
565
653
  : undefined
566
654
  }
655
+ nativeTabBarContentPaddingVertical={
656
+ nativeTabBarEnabled ? nativeTabBarContentPaddingVertical : undefined
657
+ }
567
658
  nativeTabBarItemSpacing={
568
659
  nativeTabBarEnabled ? nativeTabBarStyle?.itemSpacing ?? 8 : undefined
569
660
  }