@onekeyfe/react-native-pager-view 3.0.114 → 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.
Files changed (29) hide show
  1. package/README.md +40 -0
  2. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +630 -0
  3. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +222 -0
  4. package/android/src/main/java/com/reactnativepagerview/NestedScrollableHost.kt +3 -1
  5. package/android/src/main/java/com/reactnativepagerview/PagerViewViewPackage.kt +1 -1
  6. package/android/src/main/java/com/reactnativepagerview/event/CollapsibleStateChangedEvent.kt +39 -0
  7. package/ios/RNCCollapsiblePagerViewComponentView.h +9 -0
  8. package/ios/RNCCollapsiblePagerViewComponentView.mm +991 -0
  9. package/ios/RNCPagerViewComponentView.mm +4 -2
  10. package/lib/module/CollapsiblePagerView.js +167 -0
  11. package/lib/module/CollapsiblePagerView.web.js +478 -0
  12. package/lib/module/CollapsiblePagerViewNativeComponent.ts +87 -0
  13. package/lib/module/PagerView.web.js +177 -0
  14. package/lib/module/index.js +2 -1
  15. package/lib/module/index.web.js +6 -0
  16. package/lib/module/usePagerView.js +1 -1
  17. package/lib/typescript/src/CollapsiblePagerView.d.ts +58 -0
  18. package/lib/typescript/src/CollapsiblePagerView.web.d.ts +105 -0
  19. package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +51 -0
  20. package/lib/typescript/src/PagerView.web.d.ts +55 -0
  21. package/lib/typescript/src/index.d.ts +1 -0
  22. package/lib/typescript/src/index.web.d.ts +5 -0
  23. package/package.json +5 -2
  24. package/src/CollapsiblePagerView.tsx +293 -0
  25. package/src/CollapsiblePagerView.web.tsx +710 -0
  26. package/src/CollapsiblePagerViewNativeComponent.ts +87 -0
  27. package/src/PagerView.web.tsx +280 -0
  28. package/src/index.tsx +1 -0
  29. package/src/index.web.tsx +12 -0
@@ -593,9 +593,11 @@ using namespace facebook::react;
593
593
 
594
594
  // The blocker gesture never actually does anything — it only serves as a gate
595
595
  - (void)blockerGestureFired:(UIPanGestureRecognizer *)recognizer {
596
- // Immediately cancel so it doesn't interfere with other gestures
596
+ // Reset through the public enabled API. UIGestureRecognizer.state is
597
+ // read-only for clients; only recognizer subclasses may assign it.
597
598
  if (recognizer.state == UIGestureRecognizerStateBegan) {
598
- recognizer.state = UIGestureRecognizerStateCancelled;
599
+ recognizer.enabled = NO;
600
+ recognizer.enabled = YES;
599
601
  }
600
602
  }
601
603
 
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+
3
+ import React from "react";
4
+ import { I18nManager, Platform, StyleSheet, View } from "react-native";
5
+ import CollapsiblePagerViewNativeComponent, { Commands as CollapsiblePagerViewNativeCommands } from "./CollapsiblePagerViewNativeComponent";
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ const pageIndex = value => {
8
+ const index = Math.trunc(value);
9
+ return Number.isFinite(index) ? index : null;
10
+ };
11
+ const clampedPageIndex = (value, pageCount) => Math.min(Math.max(0, pageIndex(value) ?? 0), Math.max(0, pageCount - 1));
12
+ const pageKey = (child, index) => {
13
+ if (/*#__PURE__*/React.isValidElement(child) && child.key != null) {
14
+ return String(child.key);
15
+ }
16
+ return `page-${index}`;
17
+ };
18
+
19
+ /**
20
+ * Pager variant whose vertical header coordination is performed by the native
21
+ * scrolling containers. React participates only at settled page boundaries to
22
+ * retain the selected/adjacent heavy page subtrees.
23
+ */
24
+ export class CollapsiblePagerView extends React.PureComponent {
25
+ state = {
26
+ selectedPage: clampedPageIndex(this.props.initialPage ?? 0, React.Children.toArray(this.props.children).length)
27
+ };
28
+ nativeRef = null;
29
+ lastMountSignature = null;
30
+ componentDidMount() {
31
+ this.notifyMountedPagesChanged();
32
+ }
33
+ componentDidUpdate() {
34
+ const pageCount = this.pages().length;
35
+ const selectedPage = clampedPageIndex(this.state.selectedPage, pageCount);
36
+ if (selectedPage !== this.state.selectedPage) {
37
+ this.setState({
38
+ selectedPage
39
+ });
40
+ return;
41
+ }
42
+ this.notifyMountedPagesChanged();
43
+ }
44
+ setPage = selectedPage => {
45
+ const position = pageIndex(selectedPage);
46
+ if (this.nativeRef && position !== null && position >= 0 && position < this.pages().length) {
47
+ CollapsiblePagerViewNativeCommands.setPage(this.nativeRef, position);
48
+ }
49
+ };
50
+ setPageWithoutAnimation = selectedPage => {
51
+ const position = pageIndex(selectedPage);
52
+ if (this.nativeRef && position !== null && position >= 0 && position < this.pages().length) {
53
+ CollapsiblePagerViewNativeCommands.setPageWithoutAnimation(this.nativeRef, position);
54
+ }
55
+ };
56
+ setScrollEnabled = scrollEnabled => {
57
+ if (this.nativeRef) {
58
+ CollapsiblePagerViewNativeCommands.setScrollEnabledImperatively(this.nativeRef, scrollEnabled);
59
+ }
60
+ };
61
+ pages() {
62
+ return React.Children.toArray(this.props.children);
63
+ }
64
+ retentionDistance() {
65
+ return Math.max(0, Math.floor(this.props.pageRetentionDistance ?? 1));
66
+ }
67
+ mountedPages(pageCount = this.pages().length) {
68
+ const distance = this.retentionDistance();
69
+ const selected = Math.min(Math.max(0, this.state.selectedPage), Math.max(0, pageCount - 1));
70
+ const mounted = [];
71
+ for (let index = 0; index < pageCount; index += 1) {
72
+ if (Math.abs(index - selected) <= distance) {
73
+ mounted.push(index);
74
+ }
75
+ }
76
+ return mounted;
77
+ }
78
+ notifyMountedPagesChanged = () => {
79
+ if (!this.props.onMountedPagesChanged) {
80
+ return;
81
+ }
82
+ const pages = this.pages();
83
+ const state = {
84
+ position: this.state.selectedPage,
85
+ mountedPages: this.mountedPages(pages.length),
86
+ pageKeys: pages.map(pageKey)
87
+ };
88
+ const signature = JSON.stringify(state);
89
+ if (signature === this.lastMountSignature) {
90
+ return;
91
+ }
92
+ this.lastMountSignature = signature;
93
+ this.props.onMountedPagesChanged(state);
94
+ };
95
+ onPageSelected = event => {
96
+ const position = clampedPageIndex(event.nativeEvent.position, this.pages().length);
97
+ if (position !== this.state.selectedPage) {
98
+ this.setState({
99
+ selectedPage: position
100
+ }, this.notifyMountedPagesChanged);
101
+ }
102
+ this.props.onPageSelected?.(event);
103
+ };
104
+ render() {
105
+ const {
106
+ children: _children,
107
+ header,
108
+ stickyHeader,
109
+ headerHeight,
110
+ stickyHeaderHeight,
111
+ pageRetentionDistance: _pageRetentionDistance,
112
+ onMountedPagesChanged: _onMountedPagesChanged,
113
+ onPageSelected: _onPageSelected,
114
+ layoutDirection,
115
+ offscreenPageLimit,
116
+ ...nativeProps
117
+ } = this.props;
118
+ const pages = this.pages();
119
+ const pageKeys = pages.map(pageKey);
120
+ const retained = new Set(this.mountedPages(pages.length));
121
+ const deducedLayoutDirection = !layoutDirection || layoutDirection === "locale" ? I18nManager.isRTL ? "rtl" : "ltr" : layoutDirection;
122
+ return /*#__PURE__*/_jsxs(CollapsiblePagerViewNativeComponent, {
123
+ ...nativeProps,
124
+ ref: ref => {
125
+ this.nativeRef = ref;
126
+ },
127
+ layoutDirection: deducedLayoutDirection,
128
+ offscreenPageLimit: Math.max(1, offscreenPageLimit ?? 1),
129
+ headerHeight: Math.max(0, Math.round(headerHeight)),
130
+ stickyHeaderHeight: Math.max(0, Math.round(stickyHeaderHeight)),
131
+ pageKeys: JSON.stringify(pageKeys),
132
+ retainedPages: JSON.stringify([...retained]),
133
+ onPageSelected: this.onPageSelected,
134
+ children: [/*#__PURE__*/_jsx(View, {
135
+ collapsable: false,
136
+ pointerEvents: "box-none",
137
+ style: [styles.slot, {
138
+ bottom: undefined,
139
+ height: Math.max(0, Math.round(headerHeight))
140
+ }],
141
+ children: header
142
+ }, "collapsible-header"), /*#__PURE__*/_jsx(View, {
143
+ collapsable: false,
144
+ pointerEvents: "box-none",
145
+ style: [styles.slot, {
146
+ top: Math.max(0, Math.round(headerHeight)),
147
+ bottom: undefined,
148
+ height: Math.max(0, Math.round(stickyHeaderHeight))
149
+ }],
150
+ children: stickyHeader
151
+ }, "sticky-header"), pages.map((page, index) => /*#__PURE__*/_jsx(View, {
152
+ collapsable: false,
153
+ style: [styles.slot,
154
+ // Android translates the expanded pager while consuming header scroll.
155
+ // Keep Yoga's page bounds aligned with that native viewport.
156
+ Platform.OS === "android" ? {
157
+ bottom: -Math.max(0, Math.round(headerHeight))
158
+ } : null],
159
+ children: retained.has(index) ? page : null
160
+ }, pageKeys[index]))]
161
+ });
162
+ }
163
+ }
164
+ const styles = {
165
+ slot: StyleSheet.absoluteFill
166
+ };
167
+ //# sourceMappingURL=CollapsiblePagerView.js.map
@@ -0,0 +1,478 @@
1
+ "use strict";
2
+
3
+ import React from "react";
4
+ import { I18nManager, StyleSheet, View } from "react-native";
5
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
+ const COLLAPSE_ANIMATION_NAME = "ok-collapsible-pager-collapse";
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";
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
+ };
20
+ const timelineStyle = element => element.style;
21
+ function ensureCollapseAnimation(document) {
22
+ if (document.getElementById(COLLAPSE_STYLE_ID)) return;
23
+ const style = document.createElement("style");
24
+ style.id = COLLAPSE_STYLE_ID;
25
+ style.textContent = `@keyframes ${COLLAPSE_ANIMATION_NAME}{from{transform:translateY(0)}to{transform:translateY(calc(-1 * var(--ok-collapsible-header-height)))}}`;
26
+ document.head.appendChild(style);
27
+ }
28
+ const pageKey = (child, index) => {
29
+ if (/*#__PURE__*/React.isValidElement(child) && child.key != null) return String(child.key);
30
+ return `page-${index}`;
31
+ };
32
+
33
+ /** Web counterpart of the native collapsible pager contract. */
34
+ export class CollapsiblePagerView extends React.PureComponent {
35
+ state = {
36
+ selectedPage: clampedPageIndex(this.props.initialPage ?? 0, React.Children.toArray(this.props.children).length),
37
+ animateTransition: true
38
+ };
39
+ root = null;
40
+ track = null;
41
+ touchStartX = null;
42
+ touchStartY = null;
43
+ horizontalTouch = false;
44
+ pageOffsets = new Map();
45
+ pageHosts = new Map();
46
+ sharedHeaderOffset = 0;
47
+ scrollEnabled = this.props.scrollEnabled ?? true;
48
+ lastMountSignature = null;
49
+ configureFrame = null;
50
+ transitionTimer = null;
51
+ pageScrollState = "idle";
52
+ configuredScrollElement = null;
53
+ timelineName = `--ok-collapsible-pager-${++collapsiblePagerWebInstance}`;
54
+ componentDidMount() {
55
+ if (this.root) ensureCollapseAnimation(this.root.ownerDocument);
56
+ this.scheduleScrollConfiguration();
57
+ this.notifyMountedPagesChanged();
58
+ this.emitDiagnostics("mounted");
59
+ }
60
+ componentDidUpdate(previousProps) {
61
+ if (previousProps.scrollEnabled !== this.props.scrollEnabled) {
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;
79
+ }
80
+ this.scheduleScrollConfiguration();
81
+ this.notifyMountedPagesChanged();
82
+ }
83
+ componentWillUnmount() {
84
+ this.savePageOffset(this.state.selectedPage);
85
+ if (this.configureFrame !== null) {
86
+ cancelAnimationFrame(this.configureFrame);
87
+ this.configureFrame = null;
88
+ }
89
+ if (this.transitionTimer !== null) {
90
+ clearTimeout(this.transitionTimer);
91
+ this.transitionTimer = null;
92
+ }
93
+ this.setTrack(null);
94
+ this.restoreConfiguredScrollElement();
95
+ }
96
+ setPage = selectedPage => {
97
+ this.selectPage(selectedPage, true);
98
+ };
99
+ setPageWithoutAnimation = selectedPage => {
100
+ this.selectPage(selectedPage, false);
101
+ };
102
+ setScrollEnabled = scrollEnabled => {
103
+ this.scrollEnabled = scrollEnabled;
104
+ };
105
+ pages() {
106
+ return React.Children.toArray(this.props.children);
107
+ }
108
+ retentionDistance() {
109
+ return Math.max(0, Math.floor(this.props.pageRetentionDistance ?? 1));
110
+ }
111
+ mountedPages(pageCount = this.pages().length, selected = this.state.selectedPage) {
112
+ const mounted = [];
113
+ const distance = this.retentionDistance();
114
+ for (let index = 0; index < pageCount; index += 1) {
115
+ if (Math.abs(index - selected) <= distance) mounted.push(index);
116
+ }
117
+ return mounted;
118
+ }
119
+ nativeEvent(nativeEvent) {
120
+ return {
121
+ nativeEvent
122
+ };
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
+ };
155
+ pageScrollElement(index) {
156
+ const pageHost = this.pageHosts.get(index);
157
+ return pageHost?.querySelector(".ok-native-list-viewport, [data-collapsible-pager-scroll]") ?? pageHost;
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
+ }
165
+ restoreConfiguredScrollElement() {
166
+ const configured = this.configuredScrollElement;
167
+ if (!configured) return;
168
+ configured.element.removeEventListener("scrollend", this.onVerticalScrollSettled);
169
+ const style = timelineStyle(configured.element);
170
+ style.paddingTop = configured.paddingTop;
171
+ style.boxSizing = configured.boxSizing;
172
+ style.scrollTimelineName = configured.scrollTimelineName;
173
+ style.scrollTimelineAxis = configured.scrollTimelineAxis;
174
+ style.setProperty(PAGER_HEADER_INSET, configured.pagerHeaderInset);
175
+ style.setProperty(PAGER_STICKY_INSET, configured.pagerStickyInset);
176
+ configured.element.removeAttribute("data-collapsible-pager-active");
177
+ this.notifyInsetsChanged(configured.element);
178
+ this.configuredScrollElement = null;
179
+ }
180
+ configureActiveScrollElement = () => {
181
+ this.configureFrame = null;
182
+ const element = this.pageScrollElement(this.state.selectedPage);
183
+ if (!element) return;
184
+ if (this.configuredScrollElement?.element !== element) {
185
+ this.restoreConfiguredScrollElement();
186
+ const style = timelineStyle(element);
187
+ const computedPaddingTop = element.ownerDocument.defaultView?.getComputedStyle(element).paddingTop || style.paddingTop || "0px";
188
+ this.configuredScrollElement = {
189
+ element,
190
+ paddingTop: style.paddingTop,
191
+ basePaddingTop: computedPaddingTop,
192
+ boxSizing: style.boxSizing,
193
+ scrollTimelineName: style.scrollTimelineName,
194
+ scrollTimelineAxis: style.scrollTimelineAxis,
195
+ pagerHeaderInset: style.getPropertyValue(PAGER_HEADER_INSET),
196
+ pagerStickyInset: style.getPropertyValue(PAGER_STICKY_INSET)
197
+ };
198
+ element.addEventListener("scrollend", this.onVerticalScrollSettled);
199
+ }
200
+ const style = timelineStyle(element);
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;
209
+ style.boxSizing = "border-box";
210
+ style.scrollTimelineName = this.timelineName;
211
+ style.scrollTimelineAxis = "block";
212
+ style.setProperty(PAGER_HEADER_INSET, headerInsetValue);
213
+ style.setProperty(PAGER_STICKY_INSET, stickyInsetValue);
214
+ element.setAttribute("data-collapsible-pager-active", "true");
215
+ if (insetsChanged) this.notifyInsetsChanged(element);
216
+ };
217
+ scheduleScrollConfiguration() {
218
+ if (this.configureFrame !== null) return;
219
+ if (typeof requestAnimationFrame === "function") {
220
+ this.configureFrame = requestAnimationFrame(this.configureActiveScrollElement);
221
+ } else {
222
+ this.configureActiveScrollElement();
223
+ }
224
+ }
225
+ onVerticalScrollSettled = () => {
226
+ this.savePageOffset(this.state.selectedPage);
227
+ this.emitDiagnostics("scroll-settled");
228
+ };
229
+ savePageOffset(index) {
230
+ const key = this.pages().map(pageKey)[index];
231
+ const scrollElement = this.pageScrollElement(index);
232
+ if (key && scrollElement) {
233
+ this.pageOffsets.set(key, scrollElement.scrollTop);
234
+ this.sharedHeaderOffset = Math.min(Math.max(scrollElement.scrollTop, 0), Math.max(0, this.props.headerHeight));
235
+ }
236
+ }
237
+ restorePageOffset(index) {
238
+ const key = this.pages().map(pageKey)[index];
239
+ const scrollElement = this.pageScrollElement(index);
240
+ if (!key || !scrollElement) return;
241
+ scrollElement.scrollTop = Math.max(this.pageOffsets.get(key) ?? this.sharedHeaderOffset, this.sharedHeaderOffset);
242
+ }
243
+ selectPage(selectedPage, animated) {
244
+ const pages = this.pages();
245
+ const position = pageIndex(selectedPage);
246
+ if (position === null || position < 0 || position >= pages.length || position === this.state.selectedPage) {
247
+ return;
248
+ }
249
+ this.savePageOffset(this.state.selectedPage);
250
+ if (animated) this.beginPageTransition();else this.finishPageTransition();
251
+ this.setState({
252
+ selectedPage: position,
253
+ animateTransition: animated
254
+ }, () => {
255
+ this.scheduleScrollConfiguration();
256
+ const restore = () => {
257
+ this.configureActiveScrollElement();
258
+ this.restorePageOffset(position);
259
+ };
260
+ if (typeof requestAnimationFrame === "function") {
261
+ requestAnimationFrame(restore);
262
+ } else {
263
+ setTimeout(restore, 0);
264
+ }
265
+ this.props.onPageSelected?.(this.nativeEvent({
266
+ position
267
+ }));
268
+ this.props.onPageScroll?.(this.nativeEvent({
269
+ position,
270
+ offset: 0
271
+ }));
272
+ this.notifyMountedPagesChanged();
273
+ this.emitDiagnostics("page-selected");
274
+ });
275
+ }
276
+ notifyMountedPagesChanged = () => {
277
+ if (!this.props.onMountedPagesChanged) return;
278
+ const pages = this.pages();
279
+ const state = {
280
+ position: this.state.selectedPage,
281
+ mountedPages: this.mountedPages(pages.length),
282
+ pageKeys: pages.map(pageKey)
283
+ };
284
+ const signature = JSON.stringify(state);
285
+ if (signature === this.lastMountSignature) return;
286
+ this.lastMountSignature = signature;
287
+ this.props.onMountedPagesChanged(state);
288
+ };
289
+ emitDiagnostics(reason) {
290
+ const pages = this.pages();
291
+ const retainedPages = this.mountedPages(pages.length);
292
+ this.props.onCollapsibleStateChanged?.(this.nativeEvent({
293
+ position: this.state.selectedPage,
294
+ headerOffset: Math.min(Math.max(this.pageScrollElement(this.state.selectedPage)?.scrollTop ?? 0, 0), Math.max(0, this.props.headerHeight)),
295
+ nativePageCount: pages.length,
296
+ attachedPageCount: retainedPages.length,
297
+ observedScrollableCount: retainedPages.reduce((count, index) => count + (this.pageScrollElement(index) ? 1 : 0), 0),
298
+ retainedPages: JSON.stringify(retainedPages),
299
+ reason
300
+ }));
301
+ }
302
+ onTouchStart = event => {
303
+ if (!this.scrollEnabled) return;
304
+ const touch = event.nativeEvent.touches[0];
305
+ if (!touch) return;
306
+ this.touchStartX = touch.pageX;
307
+ this.touchStartY = touch.pageY;
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
+ }
320
+ };
321
+ onTouchEnd = event => {
322
+ if (this.touchStartX == null || !this.scrollEnabled) return;
323
+ const touch = event.nativeEvent.changedTouches[0];
324
+ if (!touch) {
325
+ this.onTouchCancel();
326
+ return;
327
+ }
328
+ const delta = touch.pageX - this.touchStartX;
329
+ const verticalDelta = touch.pageY - (this.touchStartY ?? touch.pageY);
330
+ this.touchStartX = null;
331
+ this.touchStartY = null;
332
+ const rtl = this.props.layoutDirection === "rtl" || (!this.props.layoutDirection || this.props.layoutDirection === "locale") && I18nManager.isRTL;
333
+ const direction = Math.abs(delta) >= 40 && Math.abs(delta) > Math.abs(verticalDelta) ? delta < 0 ? 1 : -1 : 0;
334
+ const next = this.state.selectedPage + (rtl ? -direction : direction);
335
+ if (direction === 0 || next < 0 || next >= this.pages().length) {
336
+ const wasHorizontal = this.horizontalTouch;
337
+ this.horizontalTouch = false;
338
+ if (wasHorizontal) this.finishPageTransition();
339
+ return;
340
+ }
341
+ this.horizontalTouch = false;
342
+ this.selectPage(next, true);
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
+ };
351
+ render() {
352
+ const {
353
+ children: _children,
354
+ header,
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,
368
+ style,
369
+ ...viewProps
370
+ } = this.props;
371
+ const pages = this.pages();
372
+ const keys = pages.map(pageKey);
373
+ const retained = new Set(this.mountedPages(pages.length));
374
+ const pageWidth = pages.length > 0 ? `${100 / pages.length}%` : "100%";
375
+ const collapseAnimation = {
376
+ "--ok-collapsible-header-height": `${Math.max(0, this.props.headerHeight)}px`,
377
+ animationName: COLLAPSE_ANIMATION_NAME,
378
+ animationDuration: "auto",
379
+ animationFillMode: "both",
380
+ animationTimingFunction: "linear",
381
+ animationTimeline: this.timelineName,
382
+ animationRange: `0px ${Math.max(1, this.props.headerHeight)}px`
383
+ };
384
+ const trackStyle = [styles.track, {
385
+ width: `${Math.max(1, pages.length) * 100}%`,
386
+ transform: [{
387
+ translateX: `${-this.state.selectedPage * 100 / Math.max(1, pages.length)}%`
388
+ }],
389
+ transitionProperty: "transform",
390
+ transitionDuration: this.state.animateTransition ? "240ms" : "0ms"
391
+ }];
392
+ return /*#__PURE__*/_jsxs(View, {
393
+ ...viewProps,
394
+ ref: node => {
395
+ this.root = webElement(node);
396
+ },
397
+ style: [styles.root, {
398
+ timelineScope: this.timelineName
399
+ }, style],
400
+ children: [/*#__PURE__*/_jsx(View, {
401
+ style: [styles.header, {
402
+ height: Math.max(0, this.props.headerHeight)
403
+ }, collapseAnimation],
404
+ children: header
405
+ }), /*#__PURE__*/_jsx(View, {
406
+ style: [styles.sticky, {
407
+ top: Math.max(0, this.props.headerHeight),
408
+ height: Math.max(0, this.props.stickyHeaderHeight)
409
+ }, collapseAnimation],
410
+ children: stickyHeader
411
+ }), /*#__PURE__*/_jsx(View, {
412
+ ref: this.setTrack,
413
+ style: trackStyle,
414
+ onTouchStart: this.onTouchStart,
415
+ onTouchMove: this.onTouchMove,
416
+ onTouchEnd: this.onTouchEnd,
417
+ onTouchCancel: this.onTouchCancel,
418
+ children: pages.map((page, index) => /*#__PURE__*/_jsx(View, {
419
+ ref: node => {
420
+ const host = webElement(node);
421
+ if (host) {
422
+ host.inert = index !== this.state.selectedPage;
423
+ this.pageHosts.set(index, host);
424
+ } else {
425
+ this.pageHosts.delete(index);
426
+ }
427
+ },
428
+ style: [styles.page, {
429
+ width: pageWidth
430
+ }],
431
+ "aria-hidden": index !== this.state.selectedPage,
432
+ children: retained.has(index) ? page : null
433
+ }, keys[index]))
434
+ })]
435
+ });
436
+ }
437
+ }
438
+ const styles = StyleSheet.create({
439
+ root: {
440
+ flex: 1,
441
+ overflow: "hidden",
442
+ position: "relative"
443
+ },
444
+ header: {
445
+ position: "absolute",
446
+ left: 0,
447
+ right: 0,
448
+ top: 0,
449
+ zIndex: 3,
450
+ overflow: "hidden"
451
+ },
452
+ sticky: {
453
+ position: "absolute",
454
+ left: 0,
455
+ right: 0,
456
+ zIndex: 4,
457
+ overflow: "hidden"
458
+ },
459
+ track: {
460
+ position: "absolute",
461
+ inset: 0,
462
+ display: "flex",
463
+ flexDirection: "row",
464
+ alignItems: "stretch",
465
+ touchAction: "pan-y"
466
+ },
467
+ page: {
468
+ flexShrink: 0,
469
+ minWidth: 0,
470
+ minHeight: 0,
471
+ height: "100%",
472
+ display: "flex",
473
+ position: "relative",
474
+ overflowY: "auto",
475
+ overflowX: "hidden"
476
+ }
477
+ });
478
+ //# sourceMappingURL=CollapsiblePagerView.web.js.map