@onekeyfe/react-native-pager-view 3.0.114 → 3.0.116

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
@@ -0,0 +1,222 @@
1
+ package com.reactnativepagerview
2
+
3
+ import android.view.View
4
+ import android.view.ViewGroup
5
+ import androidx.viewpager2.widget.ViewPager2
6
+ import com.facebook.react.bridge.ReadableArray
7
+ import com.facebook.react.common.MapBuilder
8
+ import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.uimanager.PixelUtil
10
+ import com.facebook.react.uimanager.ThemedReactContext
11
+ import com.facebook.react.uimanager.UIManagerHelper
12
+ import com.facebook.react.uimanager.ViewGroupManager
13
+ import com.facebook.react.uimanager.ViewManagerDelegate
14
+ import com.facebook.react.uimanager.annotations.ReactProp
15
+ import com.facebook.react.viewmanagers.RNCCollapsiblePagerViewManagerDelegate
16
+ import com.facebook.react.viewmanagers.RNCCollapsiblePagerViewManagerInterface
17
+ import com.reactnativepagerview.event.CollapsibleStateChangedEvent
18
+ import com.reactnativepagerview.event.PageScrollEvent
19
+ import com.reactnativepagerview.event.PageScrollStateChangedEvent
20
+ import com.reactnativepagerview.event.PageSelectedEvent
21
+ import org.json.JSONArray
22
+ import kotlin.math.roundToInt
23
+
24
+ @ReactModule(name = CollapsiblePagerViewManager.NAME)
25
+ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
26
+ RNCCollapsiblePagerViewManagerInterface<CollapsiblePagerHost> {
27
+
28
+ private val delegate: ViewManagerDelegate<CollapsiblePagerHost> =
29
+ RNCCollapsiblePagerViewManagerDelegate(this)
30
+
31
+ override fun getDelegate() = delegate
32
+
33
+ override fun getName() = NAME
34
+
35
+ override fun createViewInstance(reactContext: ThemedReactContext): CollapsiblePagerHost {
36
+ val host = CollapsiblePagerHost(reactContext)
37
+ host.id = View.generateViewId()
38
+ host.layoutParams = ViewGroup.LayoutParams(
39
+ ViewGroup.LayoutParams.MATCH_PARENT,
40
+ ViewGroup.LayoutParams.MATCH_PARENT,
41
+ )
42
+ host.pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
43
+ override fun onPageScrolled(position: Int, offset: Float, offsetPixels: Int) {
44
+ dispatch(reactContext, host, PageScrollEvent(host.id, position, offset))
45
+ }
46
+
47
+ override fun onPageSelected(position: Int) {
48
+ host.selectPage(position)
49
+ dispatch(reactContext, host, PageSelectedEvent(host.id, position))
50
+ dispatchDiagnostics(reactContext, host, "page-selected")
51
+ }
52
+
53
+ override fun onPageScrollStateChanged(state: Int) {
54
+ val value = when (state) {
55
+ ViewPager2.SCROLL_STATE_IDLE -> "idle"
56
+ ViewPager2.SCROLL_STATE_DRAGGING -> "dragging"
57
+ ViewPager2.SCROLL_STATE_SETTLING -> "settling"
58
+ else -> return
59
+ }
60
+ dispatch(reactContext, host, PageScrollStateChangedEvent(host.id, value))
61
+ if (state == ViewPager2.SCROLL_STATE_IDLE) {
62
+ dispatchDiagnostics(reactContext, host, "pager-idle")
63
+ }
64
+ }
65
+ })
66
+ host.onHeaderOffsetChanged = {
67
+ if (!host.pager.isFakeDragging && host.pager.scrollState == ViewPager2.SCROLL_STATE_IDLE) {
68
+ dispatchDiagnostics(reactContext, host, "vertical-idle")
69
+ }
70
+ }
71
+ host.post {
72
+ dispatch(reactContext, host, PageSelectedEvent(host.id, host.pager.currentItem))
73
+ dispatchDiagnostics(reactContext, host, "mounted")
74
+ }
75
+ return host
76
+ }
77
+
78
+ private fun dispatch(reactContext: ThemedReactContext, host: CollapsiblePagerHost, event: com.facebook.react.uimanager.events.Event<*>) {
79
+ UIManagerHelper.getEventDispatcherForReactTag(reactContext, host.id)?.dispatchEvent(event)
80
+ }
81
+
82
+ private fun dispatchDiagnostics(
83
+ reactContext: ThemedReactContext,
84
+ host: CollapsiblePagerHost,
85
+ reason: String,
86
+ ) {
87
+ dispatch(
88
+ reactContext,
89
+ host,
90
+ CollapsibleStateChangedEvent(
91
+ host.id,
92
+ host.selectedPage,
93
+ PixelUtil.toDIPFromPixel(host.headerOffsetPx.toFloat()).toDouble(),
94
+ host.adapter.itemCount,
95
+ host.attachedPageCount(),
96
+ host.observedScrollableCount(),
97
+ host.retainedPages,
98
+ reason,
99
+ ),
100
+ )
101
+ }
102
+
103
+ override fun addView(parent: CollapsiblePagerHost, child: View, index: Int) =
104
+ parent.addReactChild(child, index)
105
+
106
+ override fun getChildCount(parent: CollapsiblePagerHost) = parent.reactChildCount()
107
+
108
+ override fun getChildAt(parent: CollapsiblePagerHost, index: Int) = parent.reactChildAt(index)
109
+
110
+ override fun removeView(parent: CollapsiblePagerHost, view: View) = parent.removeReactChild(view)
111
+
112
+ override fun removeViewAt(parent: CollapsiblePagerHost, index: Int) =
113
+ parent.removeReactChild(parent.reactChildAt(index))
114
+
115
+ override fun removeAllViews(parent: CollapsiblePagerHost) = parent.removeAllReactChildren()
116
+
117
+ override fun needsCustomLayoutForChildren() = true
118
+
119
+ @ReactProp(name = "scrollEnabled", defaultBoolean = true)
120
+ override fun setScrollEnabled(view: CollapsiblePagerHost?, value: Boolean) {
121
+ view?.pager?.isUserInputEnabled = value
122
+ }
123
+
124
+ @ReactProp(name = "layoutDirection")
125
+ override fun setLayoutDirection(view: CollapsiblePagerHost?, value: String?) {
126
+ view?.pager?.layoutDirection = if (value == "rtl") {
127
+ View.LAYOUT_DIRECTION_RTL
128
+ } else {
129
+ View.LAYOUT_DIRECTION_LTR
130
+ }
131
+ }
132
+
133
+ @ReactProp(name = "initialPage", defaultInt = 0)
134
+ override fun setInitialPage(view: CollapsiblePagerHost?, value: Int) {
135
+ view ?: return
136
+ view.pendingInitialPage = value
137
+ view.applyPendingInitialPage()
138
+ }
139
+
140
+ @ReactProp(name = "offscreenPageLimit", defaultInt = ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT)
141
+ override fun setOffscreenPageLimit(view: CollapsiblePagerHost?, value: Int) {
142
+ view?.pager?.offscreenPageLimit = if (value == ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT) {
143
+ value
144
+ } else {
145
+ value.coerceAtLeast(1)
146
+ }
147
+ }
148
+
149
+ @ReactProp(name = "nestedScrollEnabled", defaultBoolean = false)
150
+ override fun setNestedScrollEnabled(view: CollapsiblePagerHost?, value: Boolean) {
151
+ // OneKey patch: CollapsiblePagerHost always coordinates nested pagers on Android.
152
+ }
153
+
154
+ // OneKey patch: round Yoga header dimensions to the nearest physical pixel.
155
+ @ReactProp(name = "headerHeight", defaultInt = 0)
156
+ override fun setHeaderHeight(view: CollapsiblePagerHost?, value: Int) {
157
+ view?.headerHeightPx = PixelUtil.toPixelFromDIP(value.toDouble()).roundToInt()
158
+ }
159
+
160
+ @ReactProp(name = "stickyHeaderHeight", defaultInt = 0)
161
+ override fun setStickyHeaderHeight(view: CollapsiblePagerHost?, value: Int) {
162
+ view?.stickyHeaderHeightPx = PixelUtil.toPixelFromDIP(value.toDouble()).roundToInt()
163
+ }
164
+
165
+ @ReactProp(name = "pageKeys")
166
+ override fun setPageKeys(view: CollapsiblePagerHost?, value: String?) {
167
+ view ?: return
168
+ view.pageKeys = parseStringArray(value)
169
+ }
170
+
171
+ @ReactProp(name = "retainedPages")
172
+ override fun setRetainedPages(view: CollapsiblePagerHost?, value: String?) {
173
+ view?.retainedPages = value ?: "[]"
174
+ }
175
+
176
+ private fun parseStringArray(value: String?): List<String> {
177
+ if (value.isNullOrEmpty()) return emptyList()
178
+ return runCatching {
179
+ val json = JSONArray(value)
180
+ List(json.length()) { index -> json.optString(index, "page-$index") }
181
+ }.getOrDefault(emptyList())
182
+ }
183
+
184
+ override fun receiveCommand(root: CollapsiblePagerHost, commandId: String, args: ReadableArray?) {
185
+ delegate.receiveCommand(root, commandId, args)
186
+ }
187
+
188
+ override fun setPage(view: CollapsiblePagerHost?, selectedPage: Int) {
189
+ if (view != null && selectedPage in 0 until view.adapter.itemCount) {
190
+ view.pager.setCurrentItem(selectedPage, true)
191
+ }
192
+ }
193
+
194
+ override fun setPageWithoutAnimation(view: CollapsiblePagerHost?, selectedPage: Int) {
195
+ if (view != null && selectedPage in 0 until view.adapter.itemCount) {
196
+ view.pager.setCurrentItem(selectedPage, false)
197
+ }
198
+ }
199
+
200
+ override fun setScrollEnabledImperatively(view: CollapsiblePagerHost?, scrollEnabled: Boolean) {
201
+ view?.pager?.isUserInputEnabled = scrollEnabled
202
+ }
203
+
204
+ override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Map<String, String>> =
205
+ MapBuilder.builder<String, Map<String, String>>()
206
+ .put(PageScrollEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPageScroll"))
207
+ .put(PageSelectedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPageSelected"))
208
+ .put(
209
+ PageScrollStateChangedEvent.EVENT_NAME,
210
+ MapBuilder.of("registrationName", "onPageScrollStateChanged"),
211
+ )
212
+ .put(
213
+ CollapsibleStateChangedEvent.EVENT_NAME,
214
+ MapBuilder.of("registrationName", "onCollapsibleStateChanged"),
215
+ )
216
+ .build()
217
+ .toMutableMap()
218
+
219
+ companion object {
220
+ const val NAME = "RNCCollapsiblePagerView"
221
+ }
222
+ }
@@ -21,7 +21,9 @@ import kotlin.math.sign
21
21
  * Supports multiple levels of nested PagerViews by re-asserting
22
22
  * requestDisallowInterceptTouchEvent after child dispatch.
23
23
  */
24
- class NestedScrollableHost : FrameLayout {
24
+ // OneKey patch: Let the collapsible pager reuse same-direction nested pager coordination.
25
+ // Original: class NestedScrollableHost : FrameLayout {
26
+ open class NestedScrollableHost : FrameLayout {
25
27
  constructor(context: Context) : super(context)
26
28
  constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
27
29
  public var initialIndex: Int? = null
@@ -12,6 +12,6 @@ class PagerViewPackage : ReactPackage {
12
12
  }
13
13
 
14
14
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
- return listOf(PagerViewViewManager())
15
+ return listOf(PagerViewViewManager(), CollapsiblePagerViewManager())
16
16
  }
17
17
  }
@@ -0,0 +1,39 @@
1
+ package com.reactnativepagerview.event
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+ import com.facebook.react.uimanager.events.RCTEventEmitter
7
+
8
+ class CollapsibleStateChangedEvent(
9
+ viewTag: Int,
10
+ private val position: Int,
11
+ private val headerOffset: Double,
12
+ private val nativePageCount: Int,
13
+ private val attachedPageCount: Int,
14
+ private val observedScrollableCount: Int,
15
+ private val retainedPages: String,
16
+ private val reason: String,
17
+ ) : Event<CollapsibleStateChangedEvent>(viewTag) {
18
+ override fun getEventName() = EVENT_NAME
19
+
20
+ override fun canCoalesce() = false
21
+
22
+ override fun dispatch(rctEventEmitter: RCTEventEmitter) {
23
+ rctEventEmitter.receiveEvent(viewTag, eventName, serializeEventData())
24
+ }
25
+
26
+ private fun serializeEventData(): WritableMap = Arguments.createMap().apply {
27
+ putInt("position", position)
28
+ putDouble("headerOffset", headerOffset)
29
+ putInt("nativePageCount", nativePageCount)
30
+ putInt("attachedPageCount", attachedPageCount)
31
+ putInt("observedScrollableCount", observedScrollableCount)
32
+ putString("retainedPages", retainedPages)
33
+ putString("reason", reason)
34
+ }
35
+
36
+ companion object {
37
+ const val EVENT_NAME = "topCollapsibleStateChanged"
38
+ }
39
+ }
@@ -0,0 +1,9 @@
1
+ #import <React/RCTViewComponentView.h>
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ @interface RNCCollapsiblePagerViewComponentView : RCTViewComponentView
6
+
7
+ @end
8
+
9
+ NS_ASSUME_NONNULL_END