@onekeyfe/react-native-pager-view 3.0.113 → 3.0.115

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.
@@ -5,7 +5,18 @@ import { I18nManager, StyleSheet, View } from "react-native";
5
5
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  const COLLAPSE_ANIMATION_NAME = "ok-collapsible-pager-collapse";
7
7
  const COLLAPSE_STYLE_ID = "ok-collapsible-pager-styles";
8
+ const PAGER_HEADER_INSET = "--ok-collapsible-pager-header-inset";
9
+ const PAGER_STICKY_INSET = "--ok-collapsible-pager-sticky-inset";
8
10
  let collapsiblePagerWebInstance = 0;
11
+ const pageIndex = value => {
12
+ const index = Math.trunc(value);
13
+ return Number.isFinite(index) ? index : null;
14
+ };
15
+ const clampedPageIndex = (value, pageCount) => Math.min(Math.max(0, pageIndex(value) ?? 0), Math.max(0, pageCount - 1));
16
+ const webElement = node => {
17
+ const element = node;
18
+ return element && typeof element.querySelector === "function" && typeof element.addEventListener === "function" ? element : null;
19
+ };
9
20
  const timelineStyle = element => element.style;
10
21
  function ensureCollapseAnimation(document) {
11
22
  if (document.getElementById(COLLAPSE_STYLE_ID)) return;
@@ -22,18 +33,22 @@ const pageKey = (child, index) => {
22
33
  /** Web counterpart of the native collapsible pager contract. */
23
34
  export class CollapsiblePagerView extends React.PureComponent {
24
35
  state = {
25
- selectedPage: Math.max(0, this.props.initialPage ?? 0),
36
+ selectedPage: clampedPageIndex(this.props.initialPage ?? 0, React.Children.toArray(this.props.children).length),
26
37
  animateTransition: true
27
38
  };
28
39
  root = null;
40
+ track = null;
29
41
  touchStartX = null;
30
42
  touchStartY = null;
43
+ horizontalTouch = false;
31
44
  pageOffsets = new Map();
32
45
  pageHosts = new Map();
33
46
  sharedHeaderOffset = 0;
34
47
  scrollEnabled = this.props.scrollEnabled ?? true;
35
48
  lastMountSignature = null;
36
49
  configureFrame = null;
50
+ transitionTimer = null;
51
+ pageScrollState = "idle";
37
52
  configuredScrollElement = null;
38
53
  timelineName = `--ok-collapsible-pager-${++collapsiblePagerWebInstance}`;
39
54
  componentDidMount() {
@@ -45,6 +60,22 @@ export class CollapsiblePagerView extends React.PureComponent {
45
60
  componentDidUpdate(previousProps) {
46
61
  if (previousProps.scrollEnabled !== this.props.scrollEnabled) {
47
62
  this.scrollEnabled = this.props.scrollEnabled ?? true;
63
+ if (!this.scrollEnabled) {
64
+ this.touchStartX = null;
65
+ this.touchStartY = null;
66
+ this.horizontalTouch = false;
67
+ this.finishPageTransition();
68
+ }
69
+ }
70
+ const pageCount = this.pages().length;
71
+ const selectedPage = clampedPageIndex(this.state.selectedPage, pageCount);
72
+ if (selectedPage !== this.state.selectedPage) {
73
+ this.finishPageTransition();
74
+ this.setState({
75
+ selectedPage,
76
+ animateTransition: false
77
+ });
78
+ return;
48
79
  }
49
80
  this.scheduleScrollConfiguration();
50
81
  this.notifyMountedPagesChanged();
@@ -55,6 +86,11 @@ export class CollapsiblePagerView extends React.PureComponent {
55
86
  cancelAnimationFrame(this.configureFrame);
56
87
  this.configureFrame = null;
57
88
  }
89
+ if (this.transitionTimer !== null) {
90
+ clearTimeout(this.transitionTimer);
91
+ this.transitionTimer = null;
92
+ }
93
+ this.setTrack(null);
58
94
  this.restoreConfiguredScrollElement();
59
95
  }
60
96
  setPage = selectedPage => {
@@ -85,10 +121,47 @@ export class CollapsiblePagerView extends React.PureComponent {
85
121
  nativeEvent
86
122
  };
87
123
  }
124
+ emitPageScrollState(pageScrollState) {
125
+ if (pageScrollState === this.pageScrollState) return;
126
+ this.pageScrollState = pageScrollState;
127
+ this.props.onPageScrollStateChanged?.(this.nativeEvent({
128
+ pageScrollState
129
+ }));
130
+ }
131
+ finishPageTransition = () => {
132
+ if (this.transitionTimer !== null) {
133
+ clearTimeout(this.transitionTimer);
134
+ this.transitionTimer = null;
135
+ }
136
+ this.emitPageScrollState("idle");
137
+ };
138
+ beginPageTransition() {
139
+ if (this.transitionTimer !== null) clearTimeout(this.transitionTimer);
140
+ this.emitPageScrollState("settling");
141
+ this.transitionTimer = setTimeout(this.finishPageTransition, 320);
142
+ }
143
+ onTrackTransitionEnd = event => {
144
+ if (event.target === this.track && event.propertyName === "transform") {
145
+ this.finishPageTransition();
146
+ }
147
+ };
148
+ setTrack = node => {
149
+ const track = webElement(node);
150
+ if (track === this.track) return;
151
+ this.track?.removeEventListener("transitionend", this.onTrackTransitionEnd);
152
+ this.track = track;
153
+ this.track?.addEventListener("transitionend", this.onTrackTransitionEnd);
154
+ };
88
155
  pageScrollElement(index) {
89
156
  const pageHost = this.pageHosts.get(index);
90
157
  return pageHost?.querySelector(".ok-native-list-viewport, [data-collapsible-pager-scroll]") ?? pageHost;
91
158
  }
159
+ notifyInsetsChanged(element) {
160
+ const EventConstructor = element.ownerDocument.defaultView?.Event;
161
+ if (EventConstructor) {
162
+ element.dispatchEvent(new EventConstructor("ok-collapsible-pager-insets-changed"));
163
+ }
164
+ }
92
165
  restoreConfiguredScrollElement() {
93
166
  const configured = this.configuredScrollElement;
94
167
  if (!configured) return;
@@ -98,7 +171,10 @@ export class CollapsiblePagerView extends React.PureComponent {
98
171
  style.boxSizing = configured.boxSizing;
99
172
  style.scrollTimelineName = configured.scrollTimelineName;
100
173
  style.scrollTimelineAxis = configured.scrollTimelineAxis;
174
+ style.setProperty(PAGER_HEADER_INSET, configured.pagerHeaderInset);
175
+ style.setProperty(PAGER_STICKY_INSET, configured.pagerStickyInset);
101
176
  configured.element.removeAttribute("data-collapsible-pager-active");
177
+ this.notifyInsetsChanged(configured.element);
102
178
  this.configuredScrollElement = null;
103
179
  }
104
180
  configureActiveScrollElement = () => {
@@ -108,21 +184,35 @@ export class CollapsiblePagerView extends React.PureComponent {
108
184
  if (this.configuredScrollElement?.element !== element) {
109
185
  this.restoreConfiguredScrollElement();
110
186
  const style = timelineStyle(element);
187
+ const computedPaddingTop = element.ownerDocument.defaultView?.getComputedStyle(element).paddingTop || style.paddingTop || "0px";
111
188
  this.configuredScrollElement = {
112
189
  element,
113
190
  paddingTop: style.paddingTop,
191
+ basePaddingTop: computedPaddingTop,
114
192
  boxSizing: style.boxSizing,
115
193
  scrollTimelineName: style.scrollTimelineName,
116
- scrollTimelineAxis: style.scrollTimelineAxis
194
+ scrollTimelineAxis: style.scrollTimelineAxis,
195
+ pagerHeaderInset: style.getPropertyValue(PAGER_HEADER_INSET),
196
+ pagerStickyInset: style.getPropertyValue(PAGER_STICKY_INSET)
117
197
  };
118
198
  element.addEventListener("scrollend", this.onVerticalScrollSettled);
119
199
  }
120
200
  const style = timelineStyle(element);
121
- style.paddingTop = `${Math.max(0, this.props.headerHeight + this.props.stickyHeaderHeight)}px`;
201
+ const headerInset = Math.max(0, this.props.headerHeight);
202
+ const stickyInset = Math.max(0, this.props.stickyHeaderHeight);
203
+ const basePaddingTop = this.configuredScrollElement?.basePaddingTop ?? "0px";
204
+ const paddingTop = `calc(${basePaddingTop} + ${headerInset + stickyInset}px)`;
205
+ const headerInsetValue = `${headerInset}px`;
206
+ const stickyInsetValue = `${stickyInset}px`;
207
+ const insetsChanged = style.paddingTop !== paddingTop || style.getPropertyValue(PAGER_HEADER_INSET) !== headerInsetValue || style.getPropertyValue(PAGER_STICKY_INSET) !== stickyInsetValue;
208
+ style.paddingTop = paddingTop;
122
209
  style.boxSizing = "border-box";
123
210
  style.scrollTimelineName = this.timelineName;
124
211
  style.scrollTimelineAxis = "block";
212
+ style.setProperty(PAGER_HEADER_INSET, headerInsetValue);
213
+ style.setProperty(PAGER_STICKY_INSET, stickyInsetValue);
125
214
  element.setAttribute("data-collapsible-pager-active", "true");
215
+ if (insetsChanged) this.notifyInsetsChanged(element);
126
216
  };
127
217
  scheduleScrollConfiguration() {
128
218
  if (this.configureFrame !== null) return;
@@ -152,21 +242,20 @@ export class CollapsiblePagerView extends React.PureComponent {
152
242
  }
153
243
  selectPage(selectedPage, animated) {
154
244
  const pages = this.pages();
155
- if (selectedPage < 0 || selectedPage >= pages.length || selectedPage === this.state.selectedPage) {
245
+ const position = pageIndex(selectedPage);
246
+ if (position === null || position < 0 || position >= pages.length || position === this.state.selectedPage) {
156
247
  return;
157
248
  }
158
249
  this.savePageOffset(this.state.selectedPage);
159
- this.props.onPageScrollStateChanged?.(this.nativeEvent({
160
- pageScrollState: animated ? "settling" : "idle"
161
- }));
250
+ if (animated) this.beginPageTransition();else this.finishPageTransition();
162
251
  this.setState({
163
- selectedPage,
252
+ selectedPage: position,
164
253
  animateTransition: animated
165
254
  }, () => {
166
255
  this.scheduleScrollConfiguration();
167
256
  const restore = () => {
168
257
  this.configureActiveScrollElement();
169
- this.restorePageOffset(selectedPage);
258
+ this.restorePageOffset(position);
170
259
  };
171
260
  if (typeof requestAnimationFrame === "function") {
172
261
  requestAnimationFrame(restore);
@@ -174,17 +263,12 @@ export class CollapsiblePagerView extends React.PureComponent {
174
263
  setTimeout(restore, 0);
175
264
  }
176
265
  this.props.onPageSelected?.(this.nativeEvent({
177
- position: selectedPage
266
+ position
178
267
  }));
179
268
  this.props.onPageScroll?.(this.nativeEvent({
180
- position: selectedPage,
269
+ position,
181
270
  offset: 0
182
271
  }));
183
- if (animated) {
184
- this.props.onPageScrollStateChanged?.(this.nativeEvent({
185
- pageScrollState: "idle"
186
- }));
187
- }
188
272
  this.notifyMountedPagesChanged();
189
273
  this.emitDiagnostics("page-selected");
190
274
  });
@@ -221,36 +305,68 @@ export class CollapsiblePagerView extends React.PureComponent {
221
305
  if (!touch) return;
222
306
  this.touchStartX = touch.pageX;
223
307
  this.touchStartY = touch.pageY;
224
- this.props.onPageScrollStateChanged?.(this.nativeEvent({
225
- pageScrollState: "dragging"
226
- }));
308
+ this.horizontalTouch = false;
309
+ };
310
+ onTouchMove = event => {
311
+ if (this.touchStartX == null || !this.scrollEnabled || this.horizontalTouch) return;
312
+ const touch = event.nativeEvent.touches[0];
313
+ if (!touch) return;
314
+ const deltaX = touch.pageX - this.touchStartX;
315
+ const deltaY = touch.pageY - (this.touchStartY ?? touch.pageY);
316
+ if (Math.abs(deltaX) >= 8 && Math.abs(deltaX) > Math.abs(deltaY)) {
317
+ this.horizontalTouch = true;
318
+ this.emitPageScrollState("dragging");
319
+ }
227
320
  };
228
321
  onTouchEnd = event => {
229
322
  if (this.touchStartX == null || !this.scrollEnabled) return;
230
323
  const touch = event.nativeEvent.changedTouches[0];
231
- if (!touch) return;
324
+ if (!touch) {
325
+ this.onTouchCancel();
326
+ return;
327
+ }
232
328
  const delta = touch.pageX - this.touchStartX;
233
329
  const verticalDelta = touch.pageY - (this.touchStartY ?? touch.pageY);
234
330
  this.touchStartX = null;
235
331
  this.touchStartY = null;
236
- const rtl = this.props.layoutDirection === "rtl" || !this.props.layoutDirection && I18nManager.isRTL;
332
+ const rtl = this.props.layoutDirection === "rtl" || (!this.props.layoutDirection || this.props.layoutDirection === "locale") && I18nManager.isRTL;
237
333
  const direction = Math.abs(delta) >= 40 && Math.abs(delta) > Math.abs(verticalDelta) ? delta < 0 ? 1 : -1 : 0;
238
334
  const next = this.state.selectedPage + (rtl ? -direction : direction);
239
335
  if (direction === 0 || next < 0 || next >= this.pages().length) {
240
- this.props.onPageScrollStateChanged?.(this.nativeEvent({
241
- pageScrollState: "idle"
242
- }));
336
+ const wasHorizontal = this.horizontalTouch;
337
+ this.horizontalTouch = false;
338
+ if (wasHorizontal) this.finishPageTransition();
243
339
  return;
244
340
  }
341
+ this.horizontalTouch = false;
245
342
  this.selectPage(next, true);
246
343
  };
344
+ onTouchCancel = () => {
345
+ const wasHorizontal = this.horizontalTouch;
346
+ this.touchStartX = null;
347
+ this.touchStartY = null;
348
+ this.horizontalTouch = false;
349
+ if (wasHorizontal) this.finishPageTransition();
350
+ };
247
351
  render() {
248
352
  const {
353
+ children: _children,
249
354
  header,
250
355
  stickyHeader,
356
+ headerHeight: _headerHeight,
357
+ stickyHeaderHeight: _stickyHeaderHeight,
358
+ pageRetentionDistance: _pageRetentionDistance,
359
+ layoutDirection: _layoutDirection,
360
+ scrollEnabled: _scrollEnabled,
361
+ initialPage: _initialPage,
362
+ offscreenPageLimit: _offscreenPageLimit,
363
+ onPageScroll: _onPageScroll,
364
+ onPageSelected: _onPageSelected,
365
+ onPageScrollStateChanged: _onPageScrollStateChanged,
366
+ onCollapsibleStateChanged: _onCollapsibleStateChanged,
367
+ onMountedPagesChanged: _onMountedPagesChanged,
251
368
  style,
252
- testID,
253
- accessibilityLabel
369
+ ...viewProps
254
370
  } = this.props;
255
371
  const pages = this.pages();
256
372
  const keys = pages.map(pageKey);
@@ -274,14 +390,13 @@ export class CollapsiblePagerView extends React.PureComponent {
274
390
  transitionDuration: this.state.animateTransition ? "240ms" : "0ms"
275
391
  }];
276
392
  return /*#__PURE__*/_jsxs(View, {
393
+ ...viewProps,
277
394
  ref: node => {
278
- this.root = node;
395
+ this.root = webElement(node);
279
396
  },
280
397
  style: [styles.root, {
281
398
  timelineScope: this.timelineName
282
399
  }, style],
283
- testID: testID,
284
- accessibilityLabel: accessibilityLabel,
285
400
  children: [/*#__PURE__*/_jsx(View, {
286
401
  style: [styles.header, {
287
402
  height: Math.max(0, this.props.headerHeight)
@@ -294,17 +409,16 @@ export class CollapsiblePagerView extends React.PureComponent {
294
409
  }, collapseAnimation],
295
410
  children: stickyHeader
296
411
  }), /*#__PURE__*/_jsx(View, {
412
+ ref: this.setTrack,
297
413
  style: trackStyle,
298
414
  onTouchStart: this.onTouchStart,
415
+ onTouchMove: this.onTouchMove,
299
416
  onTouchEnd: this.onTouchEnd,
300
- onTouchCancel: () => {
301
- this.touchStartX = null;
302
- this.touchStartY = null;
303
- },
417
+ onTouchCancel: this.onTouchCancel,
304
418
  children: pages.map((page, index) => /*#__PURE__*/_jsx(View, {
305
419
  ref: node => {
306
- if (node) {
307
- const host = node;
420
+ const host = webElement(node);
421
+ if (host) {
308
422
  host.inert = index !== this.state.selectedPage;
309
423
  this.pageHosts.set(index, host);
310
424
  } else {
@@ -45,6 +45,8 @@ export interface NativeProps extends ViewProps {
45
45
  layoutDirection?: WithDefault<"ltr" | "rtl", "ltr">;
46
46
  initialPage?: Int32;
47
47
  offscreenPageLimit?: Int32;
48
+ // OneKey patch: Preserve nested pager gesture coordination for collapsible pages.
49
+ nestedScrollEnabled?: WithDefault<boolean, false>;
48
50
  headerHeight?: Int32;
49
51
  stickyHeaderHeight?: Int32;
50
52
  pageKeys?: string;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
- import { PagerView } from "./PagerView";
3
+ import { PagerView } from './PagerView';
4
4
  export default PagerView;
5
5
  export * from "./usePagerView.js";
6
- export * from "./CollapsiblePagerView";
6
+ export * from './CollapsiblePagerView';
7
7
  //# sourceMappingURL=index.js.map
@@ -52,14 +52,18 @@ type State = {
52
52
  export declare class CollapsiblePagerView extends React.PureComponent<CollapsiblePagerViewProps, State> {
53
53
  state: State;
54
54
  private root;
55
+ private track;
55
56
  private touchStartX;
56
57
  private touchStartY;
58
+ private horizontalTouch;
57
59
  private pageOffsets;
58
60
  private pageHosts;
59
61
  private sharedHeaderOffset;
60
62
  private scrollEnabled;
61
63
  private lastMountSignature;
62
64
  private configureFrame;
65
+ private transitionTimer;
66
+ private pageScrollState;
63
67
  private configuredScrollElement;
64
68
  private readonly timelineName;
65
69
  componentDidMount(): void;
@@ -72,7 +76,13 @@ export declare class CollapsiblePagerView extends React.PureComponent<Collapsibl
72
76
  private retentionDistance;
73
77
  private mountedPages;
74
78
  private nativeEvent;
79
+ private emitPageScrollState;
80
+ private finishPageTransition;
81
+ private beginPageTransition;
82
+ private onTrackTransitionEnd;
83
+ private setTrack;
75
84
  private pageScrollElement;
85
+ private notifyInsetsChanged;
76
86
  private restoreConfiguredScrollElement;
77
87
  private configureActiveScrollElement;
78
88
  private scheduleScrollConfiguration;
@@ -83,7 +93,9 @@ export declare class CollapsiblePagerView extends React.PureComponent<Collapsibl
83
93
  private notifyMountedPagesChanged;
84
94
  private emitDiagnostics;
85
95
  private onTouchStart;
96
+ private onTouchMove;
86
97
  private onTouchEnd;
98
+ private onTouchCancel;
87
99
  render(): import("react/jsx-runtime").JSX.Element;
88
100
  }
89
101
  export type CollapsiblePagerViewOnPageScrollEvent = ReactNative.NativeSyntheticEvent<OnPageScrollEventData>;
@@ -29,6 +29,7 @@ export interface NativeProps extends ViewProps {
29
29
  layoutDirection?: WithDefault<"ltr" | "rtl", "ltr">;
30
30
  initialPage?: Int32;
31
31
  offscreenPageLimit?: Int32;
32
+ nestedScrollEnabled?: WithDefault<boolean, false>;
32
33
  headerHeight?: Int32;
33
34
  stickyHeaderHeight?: Int32;
34
35
  pageKeys?: string;
@@ -1,9 +1,9 @@
1
- import type * as ReactNative from "react-native";
2
- import { PagerView } from "./PagerView";
1
+ import type * as ReactNative from 'react-native';
2
+ import { PagerView } from './PagerView';
3
3
  export default PagerView;
4
- export * from "./usePagerView";
5
- export * from "./CollapsiblePagerView";
6
- import type { OnPageScrollEventData as PagerViewOnPageScrollEventData, OnPageSelectedEventData as PagerViewOnPageSelectedEventData, OnPageScrollStateChangedEventData as PageScrollStateChangedNativeEventData, NativeProps } from "./PagerViewNativeComponent";
4
+ export * from './usePagerView';
5
+ export * from './CollapsiblePagerView';
6
+ import type { OnPageScrollEventData as PagerViewOnPageScrollEventData, OnPageSelectedEventData as PagerViewOnPageSelectedEventData, OnPageScrollStateChangedEventData as PageScrollStateChangedNativeEventData, NativeProps } from './PagerViewNativeComponent';
7
7
  export type { PagerViewOnPageScrollEventData, PagerViewOnPageSelectedEventData, PageScrollStateChangedNativeEventData, NativeProps as PagerViewProps, };
8
8
  export type PagerViewOnPageScrollEvent = ReactNative.NativeSyntheticEvent<PagerViewOnPageScrollEventData>;
9
9
  export type PagerViewOnPageSelectedEvent = ReactNative.NativeSyntheticEvent<PagerViewOnPageSelectedEventData>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-pager-view",
3
- "version": "3.0.113",
3
+ "version": "3.0.115",
4
4
  "description": "React Native wrapper for Android and iOS ViewPager",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
@@ -55,6 +55,17 @@ type State = {
55
55
  selectedPage: number;
56
56
  };
57
57
 
58
+ const pageIndex = (value: number) => {
59
+ const index = Math.trunc(value);
60
+ return Number.isFinite(index) ? index : null;
61
+ };
62
+
63
+ const clampedPageIndex = (value: number, pageCount: number) =>
64
+ Math.min(
65
+ Math.max(0, pageIndex(value) ?? 0),
66
+ Math.max(0, pageCount - 1)
67
+ );
68
+
58
69
  const pageKey = (child: React.ReactNode, index: number) => {
59
70
  if (React.isValidElement(child) && child.key != null) {
60
71
  return String(child.key);
@@ -72,7 +83,10 @@ export class CollapsiblePagerView extends React.PureComponent<
72
83
  State
73
84
  > {
74
85
  state: State = {
75
- selectedPage: Math.max(0, this.props.initialPage ?? 0),
86
+ selectedPage: clampedPageIndex(
87
+ this.props.initialPage ?? 0,
88
+ React.Children.toArray(this.props.children).length
89
+ ),
76
90
  };
77
91
 
78
92
  private nativeRef: React.ElementRef<
@@ -86,20 +100,38 @@ export class CollapsiblePagerView extends React.PureComponent<
86
100
  }
87
101
 
88
102
  componentDidUpdate() {
103
+ const pageCount = this.pages().length;
104
+ const selectedPage = clampedPageIndex(this.state.selectedPage, pageCount);
105
+ if (selectedPage !== this.state.selectedPage) {
106
+ this.setState({ selectedPage });
107
+ return;
108
+ }
89
109
  this.notifyMountedPagesChanged();
90
110
  }
91
111
 
92
112
  public setPage = (selectedPage: number) => {
93
- if (this.nativeRef) {
94
- CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, selectedPage);
113
+ const position = pageIndex(selectedPage);
114
+ if (
115
+ this.nativeRef &&
116
+ position !== null &&
117
+ position >= 0 &&
118
+ position < this.pages().length
119
+ ) {
120
+ CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, position);
95
121
  }
96
122
  };
97
123
 
98
124
  public setPageWithoutAnimation = (selectedPage: number) => {
99
- if (this.nativeRef) {
125
+ const position = pageIndex(selectedPage);
126
+ if (
127
+ this.nativeRef &&
128
+ position !== null &&
129
+ position >= 0 &&
130
+ position < this.pages().length
131
+ ) {
100
132
  CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(
101
133
  this.nativeRef,
102
- selectedPage
134
+ position
103
135
  );
104
136
  }
105
137
  };
@@ -157,7 +189,10 @@ export class CollapsiblePagerView extends React.PureComponent<
157
189
  private onPageSelected = (
158
190
  event: ReactNative.NativeSyntheticEvent<OnPageSelectedEventData>
159
191
  ) => {
160
- const position = Math.max(0, Math.trunc(event.nativeEvent.position));
192
+ const position = clampedPageIndex(
193
+ event.nativeEvent.position,
194
+ this.pages().length
195
+ );
161
196
  if (position !== this.state.selectedPage) {
162
197
  this.setState({ selectedPage: position }, this.notifyMountedPagesChanged);
163
198
  }