@onekeyfe/react-native-pager-view 3.0.118 → 3.0.120

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.
@@ -23,10 +23,13 @@ const pageKey = (child, index) => {
23
23
  */
24
24
  export class CollapsiblePagerView extends React.PureComponent {
25
25
  state = {
26
- selectedPage: clampedPageIndex(this.props.initialPage ?? 0, React.Children.toArray(this.props.children).length)
26
+ selectedPage: clampedPageIndex(this.props.initialPage ?? 0, React.Children.toArray(this.props.children).length),
27
+ transientRetainedPages: []
27
28
  };
28
29
  nativeRef = null;
29
30
  lastMountSignature = null;
31
+ nativeTabCommandId = 0;
32
+ latestNativeTabTarget = null;
30
33
  componentDidMount() {
31
34
  this.notifyMountedPagesChanged();
32
35
  }
@@ -44,13 +47,21 @@ export class CollapsiblePagerView extends React.PureComponent {
44
47
  setPage = selectedPage => {
45
48
  const position = pageIndex(selectedPage);
46
49
  if (this.nativeRef && position !== null && position >= 0 && position < this.pages().length) {
47
- CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, position);
50
+ if (this.nativeTabBarEnabled()) {
51
+ this.dispatchNativeTabPageCommand(position, true);
52
+ } else {
53
+ CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, position);
54
+ }
48
55
  }
49
56
  };
50
57
  setPageWithoutAnimation = selectedPage => {
51
58
  const position = pageIndex(selectedPage);
52
59
  if (this.nativeRef && position !== null && position >= 0 && position < this.pages().length) {
53
- CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(this.nativeRef, position);
60
+ if (this.nativeTabBarEnabled()) {
61
+ this.dispatchNativeTabPageCommand(position, false);
62
+ } else {
63
+ CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(this.nativeRef, position);
64
+ }
54
65
  }
55
66
  };
56
67
  setScrollEnabled = scrollEnabled => {
@@ -61,6 +72,27 @@ export class CollapsiblePagerView extends React.PureComponent {
61
72
  pages() {
62
73
  return React.Children.toArray(this.props.children);
63
74
  }
75
+ nativeTabBarEnabled() {
76
+ return (Platform.OS === "ios" || Platform.OS === "android") && !!this.props.nativeTabBar?.items.length;
77
+ }
78
+ dispatchNativeTabPageCommand(position, animated) {
79
+ const commandId = ++this.nativeTabCommandId;
80
+ this.latestNativeTabTarget = position;
81
+ this.setState(state => ({
82
+ transientRetainedPages: state.transientRetainedPages.includes(position) ? state.transientRetainedPages : [...state.transientRetainedPages, position]
83
+ }), () => {
84
+ requestAnimationFrame(() => {
85
+ if (commandId !== this.nativeTabCommandId || !this.nativeRef) {
86
+ return;
87
+ }
88
+ if (animated) {
89
+ CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, position);
90
+ } else {
91
+ CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(this.nativeRef, position);
92
+ }
93
+ });
94
+ });
95
+ }
64
96
  retentionDistance() {
65
97
  return Math.max(0, Math.floor(this.props.pageRetentionDistance ?? 1));
66
98
  }
@@ -69,7 +101,7 @@ export class CollapsiblePagerView extends React.PureComponent {
69
101
  const selected = Math.min(Math.max(0, this.state.selectedPage), Math.max(0, pageCount - 1));
70
102
  const mounted = [];
71
103
  for (let index = 0; index < pageCount; index += 1) {
72
- if (Math.abs(index - selected) <= distance) {
104
+ if (Math.abs(index - selected) <= distance || this.state.transientRetainedPages.includes(index)) {
73
105
  mounted.push(index);
74
106
  }
75
107
  }
@@ -94,13 +126,25 @@ export class CollapsiblePagerView extends React.PureComponent {
94
126
  };
95
127
  onPageSelected = event => {
96
128
  const position = clampedPageIndex(event.nativeEvent.position, this.pages().length);
97
- if (position !== this.state.selectedPage) {
129
+ if (position !== this.state.selectedPage || this.state.transientRetainedPages.length > 0) {
130
+ const pendingTarget = this.latestNativeTabTarget;
131
+ const transitionComplete = pendingTarget === position;
132
+ if (transitionComplete) {
133
+ this.latestNativeTabTarget = null;
134
+ }
98
135
  this.setState({
99
- selectedPage: position
136
+ selectedPage: position,
137
+ transientRetainedPages: !transitionComplete && pendingTarget !== null ? [pendingTarget] : []
100
138
  }, this.notifyMountedPagesChanged);
101
139
  }
102
140
  this.props.onPageSelected?.(event);
103
141
  };
142
+ onNativeTabPress = event => {
143
+ this.props.onNativeTabPress?.(event);
144
+ };
145
+ onNativeSubHeaderPress = event => {
146
+ this.props.onNativeSubHeaderPress?.(event);
147
+ };
104
148
  render() {
105
149
  const {
106
150
  children: _children,
@@ -108,9 +152,14 @@ export class CollapsiblePagerView extends React.PureComponent {
108
152
  stickyHeader,
109
153
  headerHeight,
110
154
  stickyHeaderHeight,
155
+ nativeSmoothHeaderScrollEnabled,
111
156
  pageRetentionDistance: _pageRetentionDistance,
112
157
  onMountedPagesChanged: _onMountedPagesChanged,
113
158
  onPageSelected: _onPageSelected,
159
+ nativeTabBar,
160
+ onNativeTabPress: _onNativeTabPress,
161
+ nativeSubHeader,
162
+ onNativeSubHeaderPress: _onNativeSubHeaderPress,
114
163
  layoutDirection,
115
164
  initialPage: _initialPage,
116
165
  offscreenPageLimit,
@@ -120,6 +169,17 @@ export class CollapsiblePagerView extends React.PureComponent {
120
169
  const pageKeys = pages.map(pageKey);
121
170
  const retained = new Set(this.mountedPages(pages.length));
122
171
  const deducedLayoutDirection = !layoutDirection || layoutDirection === "locale" ? I18nManager.isRTL ? "rtl" : "ltr" : layoutDirection;
172
+ const nativeTabBarEnabled = (Platform.OS === "ios" || Platform.OS === "android") && !!nativeTabBar?.items.length;
173
+ const nativeTabBarStyle = nativeTabBar?.style;
174
+ const nativeSubHeaderEnabled = (Platform.OS === "ios" || Platform.OS === "android") && !!nativeSubHeader?.items.length;
175
+ const nativeSubHeaderStyle = nativeSubHeader?.style;
176
+ const nativeSubHeaderConfig = nativeSubHeaderEnabled ? JSON.stringify({
177
+ ...nativeSubHeader,
178
+ style: {
179
+ ...nativeSubHeaderStyle,
180
+ selectedBackgroundColor: undefined
181
+ }
182
+ }) : undefined;
123
183
  return /*#__PURE__*/_jsxs(CollapsiblePagerViewNativeComponent, {
124
184
  ...nativeProps,
125
185
  ref: ref => {
@@ -130,9 +190,26 @@ export class CollapsiblePagerView extends React.PureComponent {
130
190
  offscreenPageLimit: Math.max(1, offscreenPageLimit ?? 1),
131
191
  headerHeight: Math.max(0, Math.round(headerHeight)),
132
192
  stickyHeaderHeight: Math.max(0, Math.round(stickyHeaderHeight)),
193
+ nativeSmoothHeaderScrollEnabled: nativeSmoothHeaderScrollEnabled,
133
194
  pageKeys: JSON.stringify(pageKeys),
134
195
  retainedPages: JSON.stringify([...retained]),
135
196
  onPageSelected: this.onPageSelected,
197
+ nativeTabBarItems: nativeTabBarEnabled ? JSON.stringify(nativeTabBar.items) : undefined,
198
+ nativeTabBarHeight: nativeTabBarEnabled ? nativeTabBarStyle?.height ?? 44 : undefined,
199
+ nativeTabBarContentPaddingHorizontal: nativeTabBarEnabled ? nativeTabBarStyle?.contentPaddingHorizontal ?? 20 : undefined,
200
+ nativeTabBarItemSpacing: nativeTabBarEnabled ? nativeTabBarStyle?.itemSpacing ?? 8 : undefined,
201
+ nativeTabBarFontSize: nativeTabBarEnabled ? nativeTabBarStyle?.fontSize ?? 16 : undefined,
202
+ nativeTabBarFontFamily: nativeTabBarEnabled ? nativeTabBarStyle?.fontFamily : undefined,
203
+ nativeTabBarBackgroundColor: nativeTabBarEnabled ? nativeTabBarStyle?.backgroundColor : undefined,
204
+ nativeTabBarActiveTextColor: nativeTabBarEnabled ? nativeTabBarStyle?.activeTextColor : undefined,
205
+ nativeTabBarInactiveTextColor: nativeTabBarEnabled ? nativeTabBarStyle?.inactiveTextColor : undefined,
206
+ nativeTabBarIndicatorColor: nativeTabBarEnabled ? nativeTabBarStyle?.indicatorColor : undefined,
207
+ nativeTabBarIndicatorHeight: nativeTabBarEnabled ? nativeTabBarStyle?.indicatorHeight ?? 2 : undefined,
208
+ nativeTabBarIndicatorBottom: nativeTabBarEnabled ? nativeTabBarStyle?.indicatorBottom ?? 0 : undefined,
209
+ nativeSubHeaderConfig: nativeSubHeaderConfig,
210
+ nativeSubHeaderSelectedBackgroundColor: nativeSubHeaderEnabled ? nativeSubHeaderStyle?.selectedBackgroundColor : undefined,
211
+ onNativeTabPress: nativeTabBarEnabled ? this.onNativeTabPress : undefined,
212
+ onNativeSubHeaderPress: nativeSubHeaderEnabled ? this.onNativeSubHeaderPress : undefined,
136
213
  children: [/*#__PURE__*/_jsx(View, {
137
214
  collapsable: false,
138
215
  pointerEvents: "box-none",
@@ -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>;
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type * as ReactNative from "react-native";
3
- import { type NativeProps, type OnCollapsibleStateChangedEventData } from "./CollapsiblePagerViewNativeComponent";
3
+ import { type NativeProps, type OnCollapsibleStateChangedEventData, type OnNativeTabPressEventData } from "./CollapsiblePagerViewNativeComponent";
4
4
  import type { OnPageScrollEventData, OnPageScrollStateChangedEventData, OnPageSelectedEventData } from "./PagerViewNativeComponent";
5
5
  export type CollapsiblePagerDiagnostics = ReactNative.NativeSyntheticEvent<OnCollapsibleStateChangedEventData>;
6
6
  export type CollapsiblePagerMountState = Readonly<{
@@ -8,7 +8,54 @@ export type CollapsiblePagerMountState = Readonly<{
8
8
  mountedPages: readonly number[];
9
9
  pageKeys: readonly string[];
10
10
  }>;
11
- export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children" | "headerHeight" | "stickyHeaderHeight" | "pageKeys" | "retainedPages" | "layoutDirection"> {
11
+ export type CollapsiblePagerNativeTabBarItem = Readonly<{
12
+ key: string;
13
+ title: string;
14
+ accessibilityLabel?: string;
15
+ testID?: string;
16
+ }>;
17
+ export type CollapsiblePagerNativeTabBarStyle = Readonly<{
18
+ height?: number;
19
+ contentPaddingHorizontal?: number;
20
+ itemSpacing?: number;
21
+ fontSize?: number;
22
+ fontFamily?: string;
23
+ backgroundColor?: ReactNative.ColorValue;
24
+ activeTextColor?: ReactNative.ColorValue;
25
+ inactiveTextColor?: ReactNative.ColorValue;
26
+ indicatorColor?: ReactNative.ColorValue;
27
+ indicatorHeight?: number;
28
+ indicatorBottom?: number;
29
+ }>;
30
+ export type CollapsiblePagerNativeTabBarConfig = Readonly<{
31
+ items: readonly CollapsiblePagerNativeTabBarItem[];
32
+ style?: CollapsiblePagerNativeTabBarStyle;
33
+ }>;
34
+ export type CollapsiblePagerNativeSubHeaderColumns = Readonly<{
35
+ leading: string;
36
+ middle: string;
37
+ trailing: string;
38
+ }>;
39
+ export type CollapsiblePagerNativeSubHeaderStyle = Readonly<{
40
+ height?: number;
41
+ tabsHeight?: number;
42
+ contentPaddingHorizontal?: number;
43
+ itemSpacing?: number;
44
+ fontSize?: number;
45
+ columnFontSize?: number;
46
+ trailingColumnWidth?: number;
47
+ columnGap?: number;
48
+ selectedBackgroundColor?: ReactNative.ColorValue;
49
+ }>;
50
+ export type CollapsiblePagerNativeSubHeaderConfig = Readonly<{
51
+ items: readonly CollapsiblePagerNativeTabBarItem[];
52
+ selectedKey: string;
53
+ columns: CollapsiblePagerNativeSubHeaderColumns;
54
+ style?: CollapsiblePagerNativeSubHeaderStyle;
55
+ }>;
56
+ export type CollapsiblePagerViewOnNativeTabPressEvent = ReactNative.NativeSyntheticEvent<OnNativeTabPressEventData>;
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"> {
12
59
  /** Collapsible content rendered above the sticky bar. */
13
60
  header: React.ReactNode;
14
61
  /** Bar which remains pinned after the header has collapsed. */
@@ -17,6 +64,11 @@ export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children"
17
64
  headerHeight: number;
18
65
  /** Measured sticky bar height. */
19
66
  stickyHeaderHeight: number;
67
+ /**
68
+ * Lets the active native list own vertical gestures that begin on pager headers.
69
+ * Defaults to false and has no effect on Web.
70
+ */
71
+ nativeSmoothHeaderScrollEnabled?: boolean;
20
72
  /**
21
73
  * Number of pages retained on either side of the selected page. Page slots
22
74
  * remain stable, while distant React/native list subtrees are really
@@ -24,11 +76,18 @@ export interface CollapsiblePagerViewProps extends Omit<NativeProps, "children"
24
76
  */
25
77
  pageRetentionDistance?: number;
26
78
  layoutDirection?: "ltr" | "rtl" | "locale";
79
+ /** Optional native tab bar for iOS and Android. */
80
+ nativeTabBar?: CollapsiblePagerNativeTabBarConfig;
81
+ onNativeTabPress?: (event: CollapsiblePagerViewOnNativeTabPressEvent) => void;
82
+ /** Optional native secondary sticky header for iOS and Android. */
83
+ nativeSubHeader?: CollapsiblePagerNativeSubHeaderConfig;
84
+ onNativeSubHeaderPress?: (event: CollapsiblePagerViewOnNativeSubHeaderPressEvent) => void;
27
85
  children?: React.ReactNode;
28
86
  onMountedPagesChanged?: (state: CollapsiblePagerMountState) => void;
29
87
  }
30
88
  type State = {
31
89
  selectedPage: number;
90
+ transientRetainedPages: readonly number[];
32
91
  };
33
92
  /**
34
93
  * Pager variant whose vertical header coordination is performed by the native
@@ -39,16 +98,22 @@ export declare class CollapsiblePagerView extends React.PureComponent<Collapsibl
39
98
  state: State;
40
99
  private nativeRef;
41
100
  private lastMountSignature;
101
+ private nativeTabCommandId;
102
+ private latestNativeTabTarget;
42
103
  componentDidMount(): void;
43
104
  componentDidUpdate(): void;
44
105
  setPage: (selectedPage: number) => void;
45
106
  setPageWithoutAnimation: (selectedPage: number) => void;
46
107
  setScrollEnabled: (scrollEnabled: boolean) => void;
47
108
  private pages;
109
+ private nativeTabBarEnabled;
110
+ private dispatchNativeTabPageCommand;
48
111
  private retentionDistance;
49
112
  private mountedPages;
50
113
  private notifyMountedPagesChanged;
51
114
  private onPageSelected;
115
+ private onNativeTabPress;
116
+ private onNativeSubHeaderPress;
52
117
  render(): import("react/jsx-runtime").JSX.Element;
53
118
  }
54
119
  export type CollapsiblePagerViewOnPageScrollEvent = ReactNative.NativeSyntheticEvent<OnPageScrollEventData>;
@@ -1,5 +1,5 @@
1
1
  import type * as React from "react";
2
- import { type HostComponent, type ViewProps } from "react-native";
2
+ import { type ColorValue, type HostComponent, type ViewProps } from "react-native";
3
3
  import type { DirectEventHandler, Double, Int32, WithDefault } from "react-native/Libraries/Types/CodegenTypes";
4
4
  export type OnPageScrollEventData = Readonly<{
5
5
  position: Double;
@@ -20,6 +20,10 @@ export type OnCollapsibleStateChangedEventData = Readonly<{
20
20
  retainedPages: string;
21
21
  reason: string;
22
22
  }>;
23
+ export type OnNativeTabPressEventData = Readonly<{
24
+ position: Int32;
25
+ key: string;
26
+ }>;
23
27
  /**
24
28
  * Internal native props. Consumers should use CollapsiblePagerViewProps from
25
29
  * CollapsiblePagerView instead of mounting this host component directly.
@@ -30,14 +34,31 @@ export interface NativeProps extends ViewProps {
30
34
  initialPage?: Int32;
31
35
  offscreenPageLimit?: Int32;
32
36
  nestedScrollEnabled?: WithDefault<boolean, false>;
37
+ nativeSmoothHeaderScrollEnabled?: WithDefault<boolean, false>;
33
38
  headerHeight?: Int32;
34
39
  stickyHeaderHeight?: Int32;
35
40
  pageKeys?: string;
36
41
  retainedPages?: string;
42
+ nativeTabBarItems?: string;
43
+ nativeTabBarHeight?: Double;
44
+ nativeTabBarContentPaddingHorizontal?: Double;
45
+ nativeTabBarItemSpacing?: Double;
46
+ nativeTabBarFontSize?: Double;
47
+ nativeTabBarFontFamily?: string;
48
+ nativeTabBarBackgroundColor?: ColorValue;
49
+ nativeTabBarActiveTextColor?: ColorValue;
50
+ nativeTabBarInactiveTextColor?: ColorValue;
51
+ nativeTabBarIndicatorColor?: ColorValue;
52
+ nativeTabBarIndicatorHeight?: Double;
53
+ nativeTabBarIndicatorBottom?: Double;
54
+ nativeSubHeaderConfig?: string;
55
+ nativeSubHeaderSelectedBackgroundColor?: ColorValue;
37
56
  onPageScroll?: DirectEventHandler<OnPageScrollEventData>;
38
57
  onPageSelected?: DirectEventHandler<OnPageSelectedEventData>;
39
58
  onPageScrollStateChanged?: DirectEventHandler<OnPageScrollStateChangedEventData>;
40
59
  onCollapsibleStateChanged?: DirectEventHandler<OnCollapsibleStateChangedEventData>;
60
+ onNativeTabPress?: DirectEventHandler<OnNativeTabPressEventData>;
61
+ onNativeSubHeaderPress?: DirectEventHandler<OnNativeTabPressEventData>;
41
62
  }
42
63
  type CollapsiblePagerViewNativeType = HostComponent<NativeProps>;
43
64
  export interface NativeCommands {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-pager-view",
3
- "version": "3.0.118",
3
+ "version": "3.0.120",
4
4
  "description": "React Native wrapper for Android and iOS ViewPager",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
@@ -39,7 +39,7 @@
39
39
  "prepare": "rm -rf lib && bob build",
40
40
  "typecheck": "tsc -b",
41
41
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
42
- "test": "jest",
42
+ "test": "node --test src/__tests__/*.cjs",
43
43
  "release": "yarn prepare && npm whoami && npm publish --access public"
44
44
  },
45
45
  "keywords": [
@@ -67,6 +67,7 @@
67
67
  "typescript": "^5.9.2"
68
68
  },
69
69
  "peerDependencies": {
70
+ "@onekeyfe/react-native-native-logger": "3.0.120",
70
71
  "react": "*",
71
72
  "react-native": "*"
72
73
  },