@mpxjs/webpack-plugin 2.9.67 → 2.9.69-beta.1

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 (150) hide show
  1. package/lib/index.js +30 -9
  2. package/lib/platform/json/wx/index.js +21 -8
  3. package/lib/platform/style/wx/index.js +51 -54
  4. package/lib/platform/template/wx/component-config/canvas.js +8 -0
  5. package/lib/platform/template/wx/component-config/fix-component-name.js +15 -12
  6. package/lib/platform/template/wx/component-config/index.js +1 -1
  7. package/lib/platform/template/wx/component-config/input.js +1 -1
  8. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  9. package/lib/platform/template/wx/component-config/rich-text.js +8 -0
  10. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  11. package/lib/platform/template/wx/component-config/swiper.js +1 -1
  12. package/lib/platform/template/wx/component-config/textarea.js +1 -1
  13. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  14. package/lib/react/processStyles.js +14 -4
  15. package/lib/react/processTemplate.js +3 -0
  16. package/lib/resolver/AddEnvPlugin.js +1 -0
  17. package/lib/resolver/AddModePlugin.js +9 -8
  18. package/lib/runtime/components/react/context.ts +14 -0
  19. package/lib/runtime/components/react/dist/context.js +4 -0
  20. package/lib/runtime/components/react/dist/event.config.js +24 -24
  21. package/lib/runtime/components/react/dist/getInnerListeners.js +183 -175
  22. package/lib/runtime/components/react/dist/mpx-button.jsx +77 -49
  23. package/lib/runtime/components/react/dist/mpx-canvas/Bus.js +60 -0
  24. package/lib/runtime/components/react/dist/mpx-canvas/CanvasGradient.js +15 -0
  25. package/lib/runtime/components/react/dist/mpx-canvas/CanvasRenderingContext2D.js +84 -0
  26. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +87 -0
  27. package/lib/runtime/components/react/dist/mpx-canvas/ImageData.js +15 -0
  28. package/lib/runtime/components/react/dist/mpx-canvas/constructorsRegistry.js +28 -0
  29. package/lib/runtime/components/react/dist/mpx-canvas/html.js +343 -0
  30. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +232 -0
  31. package/lib/runtime/components/react/dist/mpx-canvas/utils.jsx +89 -0
  32. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +13 -19
  33. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +29 -38
  34. package/lib/runtime/components/react/dist/mpx-form.jsx +16 -19
  35. package/lib/runtime/components/react/dist/mpx-icon.jsx +8 -16
  36. package/lib/runtime/components/react/dist/mpx-image.jsx +291 -0
  37. package/lib/runtime/components/react/dist/mpx-input.jsx +54 -27
  38. package/lib/runtime/components/react/dist/mpx-label.jsx +15 -22
  39. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +13 -16
  40. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +14 -14
  41. package/lib/runtime/components/react/dist/mpx-navigator.jsx +2 -4
  42. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +6 -2
  43. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +5 -3
  44. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +6 -2
  45. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +6 -2
  46. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +6 -2
  47. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +10 -15
  48. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +39 -0
  49. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +171 -88
  50. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +80 -121
  51. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +11 -19
  52. package/lib/runtime/components/react/dist/mpx-radio.jsx +27 -42
  53. package/lib/runtime/components/react/dist/mpx-rich-text/html.js +39 -0
  54. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +62 -0
  55. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +6 -4
  56. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +53 -42
  57. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +11 -0
  58. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +28 -9
  59. package/lib/runtime/components/react/dist/mpx-swiper.jsx +608 -0
  60. package/lib/runtime/components/react/dist/mpx-switch.jsx +20 -10
  61. package/lib/runtime/components/react/dist/mpx-text.jsx +11 -10
  62. package/lib/runtime/components/react/dist/mpx-textarea.jsx +8 -3
  63. package/lib/runtime/components/react/dist/mpx-view.jsx +67 -94
  64. package/lib/runtime/components/react/dist/mpx-web-view.jsx +152 -37
  65. package/lib/runtime/components/react/dist/pickerFaces.js +81 -0
  66. package/lib/runtime/components/react/dist/pickerVIewContext.js +9 -0
  67. package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
  68. package/lib/runtime/components/react/dist/pickerViewOverlay.jsx +23 -0
  69. package/lib/runtime/components/react/dist/useAnimationHooks.js +36 -10
  70. package/lib/runtime/components/react/dist/utils.jsx +129 -24
  71. package/lib/runtime/components/react/event.config.ts +25 -26
  72. package/lib/runtime/components/react/getInnerListeners.ts +238 -202
  73. package/lib/runtime/components/react/mpx-button.tsx +104 -57
  74. package/lib/runtime/components/react/mpx-canvas/Bus.ts +70 -0
  75. package/lib/runtime/components/react/mpx-canvas/CanvasGradient.ts +18 -0
  76. package/lib/runtime/components/react/mpx-canvas/CanvasRenderingContext2D.ts +87 -0
  77. package/lib/runtime/components/react/mpx-canvas/Image.ts +102 -0
  78. package/lib/runtime/components/react/mpx-canvas/ImageData.ts +23 -0
  79. package/lib/runtime/components/react/mpx-canvas/constructorsRegistry.ts +38 -0
  80. package/lib/runtime/components/react/mpx-canvas/html.ts +343 -0
  81. package/lib/runtime/components/react/mpx-canvas/index.tsx +296 -0
  82. package/lib/runtime/components/react/mpx-canvas/utils.tsx +150 -0
  83. package/lib/runtime/components/react/mpx-checkbox-group.tsx +28 -25
  84. package/lib/runtime/components/react/mpx-checkbox.tsx +48 -49
  85. package/lib/runtime/components/react/mpx-form.tsx +25 -28
  86. package/lib/runtime/components/react/mpx-icon.tsx +12 -17
  87. package/lib/runtime/components/react/mpx-image.tsx +436 -0
  88. package/lib/runtime/components/react/mpx-input.tsx +77 -57
  89. package/lib/runtime/components/react/mpx-label.tsx +26 -27
  90. package/lib/runtime/components/react/mpx-movable-area.tsx +18 -23
  91. package/lib/runtime/components/react/mpx-movable-view.tsx +22 -26
  92. package/lib/runtime/components/react/mpx-navigator.tsx +2 -8
  93. package/lib/runtime/components/react/mpx-picker/date.tsx +5 -2
  94. package/lib/runtime/components/react/mpx-picker/index.tsx +3 -2
  95. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +5 -2
  96. package/lib/runtime/components/react/mpx-picker/region.tsx +5 -2
  97. package/lib/runtime/components/react/mpx-picker/selector.tsx +5 -2
  98. package/lib/runtime/components/react/mpx-picker/time.tsx +10 -15
  99. package/lib/runtime/components/react/mpx-picker/type.ts +48 -43
  100. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +88 -0
  101. package/lib/runtime/components/react/mpx-picker-view-column.tsx +276 -112
  102. package/lib/runtime/components/react/mpx-picker-view.tsx +137 -129
  103. package/lib/runtime/components/react/mpx-radio-group.tsx +24 -27
  104. package/lib/runtime/components/react/mpx-radio.tsx +45 -54
  105. package/lib/runtime/components/react/mpx-rich-text/html.ts +40 -0
  106. package/lib/runtime/components/react/mpx-rich-text/index.tsx +115 -0
  107. package/lib/runtime/components/react/mpx-root-portal.tsx +3 -5
  108. package/lib/runtime/components/react/mpx-scroll-view.tsx +83 -73
  109. package/lib/runtime/components/react/mpx-simple-text.tsx +18 -0
  110. package/lib/runtime/components/react/mpx-swiper-item.tsx +41 -12
  111. package/lib/runtime/components/react/mpx-swiper.tsx +690 -0
  112. package/lib/runtime/components/react/mpx-switch.tsx +29 -23
  113. package/lib/runtime/components/react/mpx-text.tsx +14 -18
  114. package/lib/runtime/components/react/mpx-textarea.tsx +11 -10
  115. package/lib/runtime/components/react/mpx-view.tsx +93 -117
  116. package/lib/runtime/components/react/mpx-web-view.tsx +162 -56
  117. package/lib/runtime/components/react/pickerFaces.ts +112 -0
  118. package/lib/runtime/components/react/pickerVIewContext.ts +18 -0
  119. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  120. package/lib/runtime/components/react/pickerViewOverlay.tsx +34 -0
  121. package/lib/runtime/components/react/types/common.ts +2 -0
  122. package/lib/runtime/components/react/types/global.d.ts +7 -17
  123. package/lib/runtime/components/react/useAnimationHooks.ts +37 -12
  124. package/lib/runtime/components/react/utils.tsx +169 -29
  125. package/lib/runtime/components/web/getInnerListeners.js +6 -6
  126. package/lib/runtime/components/web/mpx-movable-view.vue +334 -344
  127. package/lib/runtime/components/web/mpx-picker-view-column.vue +75 -75
  128. package/lib/runtime/components/web/mpx-picker.vue +382 -385
  129. package/lib/runtime/components/web/mpx-web-view.vue +175 -161
  130. package/lib/runtime/optionProcessor.js +7 -38
  131. package/lib/runtime/utils.js +2 -0
  132. package/lib/style-compiler/index.js +3 -4
  133. package/lib/style-compiler/plugins/scope-id.js +30 -2
  134. package/lib/style-compiler/strip-conditional-loader.js +118 -0
  135. package/lib/template-compiler/bind-this.js +7 -2
  136. package/lib/template-compiler/compiler.js +66 -39
  137. package/lib/template-compiler/gen-node-react.js +3 -3
  138. package/package.json +6 -4
  139. package/LICENSE +0 -433
  140. package/lib/runtime/components/react/dist/mpx-image/index.jsx +0 -226
  141. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +0 -7
  142. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +0 -478
  143. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +0 -68
  144. package/lib/runtime/components/react/dist/mpx-swiper/type.js +0 -1
  145. package/lib/runtime/components/react/mpx-image/index.tsx +0 -345
  146. package/lib/runtime/components/react/mpx-image/svg.tsx +0 -22
  147. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -525
  148. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  149. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
  150. package/lib/runtime/components/web/event.js +0 -105
@@ -0,0 +1,690 @@
1
+ import { View, NativeSyntheticEvent, LayoutChangeEvent } from 'react-native'
2
+ import { GestureDetector, Gesture } from 'react-native-gesture-handler'
3
+ import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, runOnJS, runOnUI, useAnimatedReaction, cancelAnimation } from 'react-native-reanimated'
4
+
5
+ import React, { JSX, forwardRef, useRef, useEffect, ReactNode, ReactElement } from 'react'
6
+ import useInnerProps, { getCustomEvent } from './getInnerListeners'
7
+ import useNodesRef, { HandlerRef } from './useNodesRef' // 引入辅助函数
8
+ import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from './utils'
9
+ import { SwiperContext } from './context'
10
+ /**
11
+ * ✔ indicator-dots
12
+ * ✔ indicator-color
13
+ * ✔ indicator-active-color
14
+ * ✔ autoplay
15
+ * ✔ current
16
+ * ✔ interval
17
+ * ✔ duration
18
+ * ✔ circular
19
+ * ✔ vertical
20
+ * ✔ previous-margin
21
+ * ✔ next-margin
22
+ * ✔ easing-function ="easeOutCubic"
23
+ * ✘ display-multiple-items
24
+ * ✘ snap-to-edge
25
+ */
26
+ type EaseType = 'default' | 'linear' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic'
27
+ type StrTransType = 'translationX' | 'translationY'
28
+ type StrAbsoType = 'absoluteX' | 'absoluteY'
29
+ type StrVelocity = 'velocityX' | 'velocityY'
30
+ type EventDataType = {
31
+ translation: number
32
+ }
33
+
34
+ interface SwiperProps {
35
+ children?: ReactNode;
36
+ circular?: boolean;
37
+ current?: number;
38
+ interval?: number;
39
+ autoplay?: boolean;
40
+ // scrollView 只有安卓可以设
41
+ duration?: number;
42
+ // 滑动过程中元素是否scale变化
43
+ scale?: boolean;
44
+ 'indicator-dots'?: boolean;
45
+ 'indicator-color'?: string;
46
+ 'indicator-active-color'?: string;
47
+ vertical?: boolean;
48
+ style: {
49
+ [key: string]: any
50
+ };
51
+ 'easing-function'?: EaseType;
52
+ 'previous-margin'?: string;
53
+ 'next-margin'?: string;
54
+ 'enable-offset'?: boolean;
55
+ 'enable-var': boolean;
56
+ 'parent-font-size'?: number;
57
+ 'parent-width'?: number;
58
+ 'parent-height'?: number;
59
+ 'external-var-context'?: Record<string, any>;
60
+ bindchange?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void;
61
+ }
62
+
63
+ /**
64
+ * 默认的Style类型
65
+ */
66
+ const styles: { [key: string]: Object } = {
67
+ pagination_x: {
68
+ position: 'absolute',
69
+ bottom: 25,
70
+ left: 0,
71
+ right: 0,
72
+ flexDirection: 'row',
73
+ flex: 1,
74
+ justifyContent: 'center',
75
+ alignItems: 'center'
76
+ },
77
+ pagination_y: {
78
+ position: 'absolute',
79
+ right: 15,
80
+ top: 0,
81
+ bottom: 0,
82
+ flexDirection: 'column',
83
+ flex: 1,
84
+ justifyContent: 'center',
85
+ alignItems: 'center'
86
+ },
87
+ pagerWrapperx: {
88
+ position: 'absolute',
89
+ flexDirection: 'row',
90
+ justifyContent: 'center',
91
+ alignItems: 'center'
92
+ },
93
+ pagerWrappery: {
94
+ position: 'absolute',
95
+ flexDirection: 'column',
96
+ justifyContent: 'center',
97
+ alignItems: 'center'
98
+ },
99
+ swiper: {
100
+ overflow: 'scroll',
101
+ display: 'flex',
102
+ justifyContent: 'flex-start'
103
+ }
104
+ }
105
+
106
+ const dotCommonStyle = {
107
+ width: 8,
108
+ height: 8,
109
+ borderRadius: 4,
110
+ marginLeft: 3,
111
+ marginRight: 3,
112
+ marginTop: 3,
113
+ marginBottom: 3,
114
+ zIndex: 98
115
+ }
116
+ const activeDotStyle = {
117
+ zIndex: 99
118
+ }
119
+ const longPressRatio = 100
120
+
121
+ const easeMap = {
122
+ default: Easing.linear,
123
+ linear: Easing.linear,
124
+ easeInCubic: Easing.in(Easing.cubic),
125
+ easeOutCubic: Easing.out(Easing.cubic),
126
+ easeInOutCubic: Easing.inOut(Easing.cubic)
127
+ }
128
+
129
+ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((props: SwiperProps, ref): JSX.Element => {
130
+ const {
131
+ 'indicator-dots': showsPagination,
132
+ 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)',
133
+ 'indicator-active-color': activeDotColor = '#000000',
134
+ 'enable-var': enableVar = false,
135
+ 'parent-font-size': parentFontSize,
136
+ 'parent-width': parentWidth,
137
+ 'parent-height': parentHeight,
138
+ 'external-var-context': externalVarContext,
139
+ style = {}
140
+ } = props
141
+ const previousMargin = props['previous-margin'] ? parseInt(props['previous-margin']) : 0
142
+ const nextMargin = props['next-margin'] ? parseInt(props['next-margin']) : 0
143
+ const easeingFunc = props['easing-function'] || 'default'
144
+ const easeDuration = props.duration || 500
145
+ const horizontal = props.vertical !== undefined ? !props.vertical : true
146
+ // 默认前后补位的元素个数
147
+ const patchElementNum = props.circular ? (previousMargin ? 2 : 1) : 0
148
+ const nodeRef = useRef<View>(null)
149
+ useNodesRef<View, SwiperProps>(props, ref, nodeRef, {})
150
+
151
+ // 计算transfrom之类的
152
+ const {
153
+ normalStyle,
154
+ hasVarDec,
155
+ varContextRef,
156
+ hasSelfPercent,
157
+ setWidth,
158
+ setHeight
159
+ } = useTransformStyle(style, {
160
+ enableVar,
161
+ externalVarContext,
162
+ parentFontSize,
163
+ parentWidth,
164
+ parentHeight
165
+ })
166
+ const { textStyle } = splitStyle(normalStyle)
167
+ const { textProps } = splitProps(props)
168
+ const children = Array.isArray(props.children) ? props.children.filter(child => child) : (props.children ? [props.children] : [])
169
+ const initWidth = typeof normalStyle?.width === 'number' ? normalStyle.width - previousMargin - nextMargin : normalStyle.width
170
+ const initHeight = typeof normalStyle?.height === 'number' ? normalStyle.height - previousMargin - nextMargin : normalStyle.height
171
+ const dir = useSharedValue(horizontal === false ? 'y' : 'x')
172
+ const pstep = dir.value === 'x' ? initWidth : initHeight
173
+ const initStep: number = isNaN(pstep) ? 0 : pstep
174
+ // 每个元素的宽度 or 高度
175
+ const step = useSharedValue(initStep)
176
+ const totalElements = useSharedValue(children.length)
177
+ // 记录选中元素的索引值
178
+ const currentIndex = useSharedValue(0)
179
+ // 记录元素的偏移量
180
+ const offset = useSharedValue(0)
181
+ const strAbso = 'absolute' + dir.value.toUpperCase() as StrAbsoType
182
+ const arrPages: Array<ReactNode> | ReactNode = renderItems()
183
+ // 标识手指触摸和抬起, 起点在onBegin
184
+ const touchfinish = useSharedValue(true)
185
+ // 记录上一帧的绝对定位坐标
186
+ const preAbsolutePos = useSharedValue(0)
187
+ // 记录从onBegin 到 onTouchesUp 时移动的距离
188
+ const moveTranstion = useSharedValue(0)
189
+ // 记录从onBegin 到 onTouchesUp 的时间
190
+ const moveTime = useSharedValue(0)
191
+ const timerId = useRef(0 as number | ReturnType<typeof setTimeout>)
192
+ // 用户点击未移动状态下,记录用户上一次操作的transtion 的 direction
193
+ const customTrans = useSharedValue(0)
194
+ const intervalTimer = props.interval || 500
195
+ totalElements.value = children.length
196
+ const {
197
+ // 存储layout布局信息
198
+ layoutRef,
199
+ layoutProps,
200
+ layoutStyle
201
+ } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef, onLayout: onWrapperLayout })
202
+
203
+ const innerProps = useInnerProps(props, {
204
+ ref: nodeRef
205
+ }, [
206
+ 'style',
207
+ 'indicator-dots',
208
+ 'indicator-color',
209
+ 'indicator-active-color',
210
+ 'previous-margin',
211
+ 'vertical',
212
+ 'previous-margin',
213
+ 'next-margin',
214
+ 'easing-function',
215
+ 'autoplay',
216
+ 'circular',
217
+ 'interval',
218
+ 'easing-function'
219
+ ], { layoutRef: layoutRef })
220
+
221
+ function onWrapperLayout (e: LayoutChangeEvent) {
222
+ const { width, height } = e.nativeEvent.layout
223
+ const realWidth = dir.value === 'x' ? width - previousMargin - nextMargin : width
224
+ const realHeight = dir.value === 'y' ? height - previousMargin - nextMargin : height
225
+ step.value = dir.value === 'x' ? realWidth : realHeight
226
+ if (touchfinish.value) {
227
+ runOnUI(() => {
228
+ offset.value = getOffset(currentIndex.value)
229
+ })()
230
+ pauseLoop()
231
+ resumeLoop()
232
+ }
233
+ }
234
+
235
+ const dotAnimatedStyle = useAnimatedStyle(() => {
236
+ if (!step.value) return {}
237
+ const dotStep = dotCommonStyle.width + dotCommonStyle.marginRight + dotCommonStyle.marginLeft
238
+ if (dir.value === 'x') {
239
+ return { transform: [{ translateX: currentIndex.value * dotStep }] }
240
+ } else {
241
+ return { transform: [{ translateY: currentIndex.value * dotStep }] }
242
+ }
243
+ })
244
+
245
+ function renderPagination () {
246
+ if (totalElements.value <= 1) return null
247
+ const activeColor = activeDotColor || '#007aff'
248
+ const unActionColor = dotColor || 'rgba(0,0,0,.2)'
249
+ // 正常渲染所有dots
250
+ const dots: Array<ReactNode> = []
251
+ for (let i = 0; i < totalElements.value; i++) {
252
+ dots.push(<View style={[dotCommonStyle, { backgroundColor: unActionColor }]} key={i}></View>)
253
+ }
254
+ return (
255
+ <View pointerEvents="none" style = {styles['pagination_' + dir.value]}>
256
+ <View style = {[styles['pagerWrapper' + dir.value]]}>
257
+ <Animated.View style={[
258
+ dotCommonStyle,
259
+ activeDotStyle,
260
+ {
261
+ backgroundColor: activeColor,
262
+ position: 'absolute',
263
+ left: 0,
264
+ top: 0
265
+ },
266
+ dotAnimatedStyle
267
+ ]}
268
+ />
269
+ {dots}
270
+ </View>
271
+ </View>)
272
+ }
273
+
274
+ function renderItems () {
275
+ const itemAnimatedStyles = useAnimatedStyle(() => {
276
+ return dir.value === 'x' ? { width: step.value, height: '100%' } : { width: '100%', height: step.value }
277
+ })
278
+ let renderChild = children.slice()
279
+ if (props.circular && totalElements.value > 1) {
280
+ // 最前面加最后一个元素
281
+ const lastChild = React.cloneElement(children[totalElements.value - 1] as ReactElement)
282
+ // 最后面加第一个元素
283
+ const firstChild = React.cloneElement(children[0] as ReactElement)
284
+ if (previousMargin) {
285
+ const lastChild1 = React.cloneElement(children[totalElements.value - 2] as ReactElement)
286
+ const firstChild1 = React.cloneElement(children[1] as ReactElement)
287
+ renderChild = [lastChild1, lastChild].concat(renderChild).concat([firstChild, firstChild1])
288
+ } else {
289
+ renderChild = [lastChild].concat(renderChild).concat([firstChild])
290
+ }
291
+ }
292
+ const arrChilds = renderChild.map((child, index) => {
293
+ const extraStyle = {} as { [key: string]: any }
294
+ if (index === 0 && !props.circular) {
295
+ previousMargin && dir.value === 'x' && (extraStyle.marginLeft = previousMargin)
296
+ previousMargin && dir.value === 'y' && (extraStyle.marginTop = previousMargin)
297
+ }
298
+ if (index === totalElements.value - 1 && !props.circular) {
299
+ nextMargin && dir.value === 'x' && (extraStyle.marginRight = nextMargin)
300
+ nextMargin && dir.value === 'y' && (extraStyle.marginBottom = nextMargin)
301
+ }
302
+ const newChild = React.cloneElement(child, {
303
+ itemIndex: index,
304
+ customStyle: [itemAnimatedStyles, extraStyle],
305
+ key: 'page' + index
306
+ })
307
+ return newChild
308
+ })
309
+ const contextValue = {
310
+ offset,
311
+ step,
312
+ scale: props.scale
313
+ }
314
+ return (<SwiperContext.Provider value={contextValue}>{arrChilds}</SwiperContext.Provider>)
315
+ }
316
+
317
+ function createAutoPlay () {
318
+ let targetOffset = 0
319
+ let nextIndex = currentIndex.value
320
+ if (!props.circular) {
321
+ // 获取下一个位置的坐标, 循环到最后一个元素,直接停止, 取消定时器
322
+ if (currentIndex.value === totalElements.value - 1) {
323
+ pauseLoop()
324
+ return
325
+ }
326
+ nextIndex += 1
327
+ targetOffset = -nextIndex * step.value - previousMargin
328
+ offset.value = withTiming(targetOffset, {
329
+ duration: easeDuration,
330
+ easing: easeMap[easeingFunc]
331
+ }, () => {
332
+ currentIndex.value = nextIndex
333
+ runOnJS(loop)()
334
+ })
335
+ } else {
336
+ // 默认向右, 向下
337
+ if (nextIndex === totalElements.value - 1) {
338
+ nextIndex = 0
339
+ targetOffset = -(totalElements.value + patchElementNum) * step.value + previousMargin
340
+ // 执行动画到下一帧
341
+ offset.value = withTiming(targetOffset, {
342
+ duration: easeDuration
343
+ }, () => {
344
+ const initOffset = -step.value * patchElementNum + previousMargin
345
+ // 将开始位置设置为真正的位置
346
+ offset.value = initOffset
347
+ currentIndex.value = nextIndex
348
+ runOnJS(loop)()
349
+ })
350
+ } else {
351
+ nextIndex = currentIndex.value + 1
352
+ targetOffset = -(nextIndex + patchElementNum) * step.value + previousMargin
353
+ // 执行动画到下一帧
354
+ offset.value = withTiming(targetOffset, {
355
+ duration: easeDuration,
356
+ easing: easeMap[easeingFunc]
357
+ }, () => {
358
+ currentIndex.value = nextIndex
359
+ runOnJS(loop)()
360
+ })
361
+ }
362
+ }
363
+ }
364
+
365
+ function handleSwiperChange (current: number) {
366
+ if (props.current !== currentIndex.value) {
367
+ const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef })
368
+ props.bindchange && props.bindchange(eventData)
369
+ }
370
+ }
371
+
372
+ function getOffset (index?: number) {
373
+ 'worklet'
374
+ if (!step.value) return 0
375
+ let targetOffset = 0
376
+ if (props.circular && totalElements.value > 1) {
377
+ const targetIndex = (index || props.current || 0) + patchElementNum
378
+ targetOffset = -(step.value * targetIndex - previousMargin)
379
+ } else {
380
+ targetOffset = -(index || props?.current || 0) * step.value
381
+ }
382
+ return targetOffset
383
+ }
384
+
385
+ function loop () {
386
+ timerId.current = setTimeout(() => {
387
+ createAutoPlay()
388
+ }, intervalTimer)
389
+ }
390
+
391
+ function pauseLoop () {
392
+ timerId.current && clearTimeout(timerId.current)
393
+ }
394
+
395
+ function resumeLoop () {
396
+ if (props.autoplay) {
397
+ loop()
398
+ }
399
+ }
400
+
401
+ useAnimatedReaction(() => currentIndex.value, (newIndex, preIndex) => {
402
+ // 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
403
+ const isInit = !preIndex && newIndex === 0
404
+ if (!isInit && newIndex !== preIndex && props.bindchange) {
405
+ runOnJS(handleSwiperChange)(newIndex)
406
+ }
407
+ })
408
+ useEffect(() => {
409
+ if (!step.value) {
410
+ return
411
+ }
412
+ const targetOffset = getOffset()
413
+ if (props.current !== undefined && props.current !== currentIndex.value) {
414
+ offset.value = withTiming(targetOffset, {
415
+ duration: easeDuration,
416
+ easing: easeMap[easeingFunc]
417
+ }, () => {
418
+ currentIndex.value = props.current || 0
419
+ })
420
+ }
421
+ }, [props.current])
422
+
423
+ useEffect(() => {
424
+ if (!step.value) {
425
+ return
426
+ }
427
+ if (props.autoplay) {
428
+ resumeLoop()
429
+ } else {
430
+ pauseLoop()
431
+ }
432
+ return () => {
433
+ if (props.autoplay) {
434
+ pauseLoop()
435
+ }
436
+ }
437
+ }, [props.autoplay])
438
+
439
+ function getTargetPosition (eventData: EventDataType) {
440
+ 'worklet'
441
+ // 移动的距离
442
+ const { translation } = eventData
443
+ let resetOffsetPos = 0
444
+ let selectedIndex = currentIndex.value
445
+ // 是否临界点
446
+ let isCriticalItem = false
447
+ // 真实滚动到的偏移量坐标
448
+ let moveToTargetPos = 0
449
+ // 当前的位置
450
+ const currentOffset = offset.value - previousMargin
451
+ const computedIndex = Math.abs(currentOffset) / step.value
452
+ const moveToIndex = translation < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex)
453
+ // 实际应该定位的索引值
454
+ if (!props.circular) {
455
+ selectedIndex = moveToIndex
456
+ moveToTargetPos = selectedIndex * step.value
457
+ } else {
458
+ if (moveToIndex >= totalElements.value + patchElementNum) {
459
+ selectedIndex = moveToIndex - (totalElements.value + patchElementNum)
460
+ resetOffsetPos = (selectedIndex + patchElementNum) * step.value - previousMargin
461
+ moveToTargetPos = moveToIndex * step.value - previousMargin
462
+ isCriticalItem = true
463
+ } else if (moveToIndex <= patchElementNum - 1) {
464
+ selectedIndex = moveToIndex === 0 ? totalElements.value - patchElementNum : totalElements.value - 1
465
+ resetOffsetPos = (selectedIndex + patchElementNum) * step.value - previousMargin
466
+ moveToTargetPos = moveToIndex * step.value - previousMargin
467
+ isCriticalItem = true
468
+ } else {
469
+ selectedIndex = moveToIndex - patchElementNum
470
+ moveToTargetPos = moveToIndex * step.value - previousMargin
471
+ }
472
+ }
473
+ return {
474
+ selectedIndex,
475
+ isCriticalItem,
476
+ resetOffset: -resetOffsetPos,
477
+ targetOffset: -moveToTargetPos
478
+ }
479
+ }
480
+
481
+ function canMove (eventData: EventDataType) {
482
+ 'worklet'
483
+ const { translation } = eventData
484
+ const currentOffset = Math.abs(offset.value)
485
+ if (!props.circular) {
486
+ if (translation < 0) {
487
+ return currentOffset < step.value * (totalElements.value - 1)
488
+ } else {
489
+ return currentOffset > 0
490
+ }
491
+ } else {
492
+ return true
493
+ }
494
+ }
495
+
496
+ function handleEnd (eventData: EventDataType) {
497
+ 'worklet'
498
+ const { isCriticalItem, targetOffset, resetOffset, selectedIndex } = getTargetPosition(eventData)
499
+ if (isCriticalItem) {
500
+ offset.value = withTiming(targetOffset, {
501
+ duration: easeDuration,
502
+ easing: easeMap[easeingFunc]
503
+ }, () => {
504
+ if (touchfinish.value !== false) {
505
+ currentIndex.value = selectedIndex
506
+ offset.value = resetOffset
507
+ runOnJS(resumeLoop)()
508
+ }
509
+ })
510
+ } else {
511
+ offset.value = withTiming(targetOffset, {
512
+ duration: easeDuration,
513
+ easing: easeMap[easeingFunc]
514
+ }, () => {
515
+ if (touchfinish.value !== false) {
516
+ currentIndex.value = selectedIndex
517
+ runOnJS(resumeLoop)()
518
+ }
519
+ })
520
+ }
521
+ }
522
+
523
+ function handleBack (eventData: EventDataType) {
524
+ 'worklet'
525
+ const { translation } = eventData
526
+ // 向右滑动的back:trans < 0, 向左滑动的back: trans < 0
527
+ const currentOffset = Math.abs(offset.value)
528
+ const curIndex = currentOffset / step.value
529
+ const moveToIndex = (translation < 0 ? Math.floor(curIndex) : Math.ceil(curIndex)) - patchElementNum
530
+ const targetOffset = -(moveToIndex + patchElementNum) * step.value + (translation < 0 ? -previousMargin : previousMargin)
531
+ offset.value = withTiming(targetOffset, {
532
+ duration: easeDuration,
533
+ easing: easeMap[easeingFunc]
534
+ }, () => {
535
+ if (touchfinish.value !== false) {
536
+ currentIndex.value = moveToIndex
537
+ runOnJS(resumeLoop)()
538
+ }
539
+ })
540
+ }
541
+
542
+ function handleLongPress (eventData: EventDataType) {
543
+ 'worklet'
544
+ const { translation } = eventData
545
+ const currentOffset = Math.abs(offset.value) + (translation < 0 ? previousMargin : -previousMargin)
546
+ const half = currentOffset % step.value > step.value / 2
547
+ // 向右trans < 0, 向左trans > 0
548
+ const isExceedHalf = translation < 0 ? half : !half
549
+ if (+translation === 0) {
550
+ runOnJS(resumeLoop)()
551
+ } else if (isExceedHalf) {
552
+ handleEnd(eventData)
553
+ } else {
554
+ handleBack(eventData)
555
+ }
556
+ }
557
+
558
+ function reachBoundary (eventData: EventDataType) {
559
+ 'worklet'
560
+ // 移动的距离
561
+ const { translation } = eventData
562
+ const elementsLength = step.value * totalElements.value
563
+
564
+ let isBoundary = false
565
+ let resetOffset = 0
566
+ // Y轴向下滚动, transDistance > 0, 向上滚动 < 0 X轴向左滚动, transDistance > 0
567
+ const currentOffset = offset.value
568
+ const moveStep = Math.ceil(translation / elementsLength)
569
+ if (translation < 0) {
570
+ const posEnd = (totalElements.value + patchElementNum + 1) * step.value
571
+ const posReverseEnd = (patchElementNum - 1) * step.value
572
+ if (currentOffset < -posEnd + step.value) {
573
+ isBoundary = true
574
+ resetOffset = Math.abs(moveStep) === 0 ? patchElementNum * step.value + translation : moveStep * elementsLength
575
+ }
576
+ if (currentOffset > -posReverseEnd) {
577
+ isBoundary = true
578
+ resetOffset = moveStep * elementsLength
579
+ }
580
+ } else if (translation > 0) {
581
+ const posEnd = (patchElementNum - 1) * step.value
582
+ const posReverseEnd = (patchElementNum + totalElements.value) * step.value
583
+ if (currentOffset > -posEnd) {
584
+ isBoundary = true
585
+ resetOffset = moveStep * elementsLength + step.value + (moveStep === 1 ? translation : 0)
586
+ }
587
+ if (currentOffset < -posReverseEnd) {
588
+ isBoundary = true
589
+ resetOffset = moveStep * elementsLength + patchElementNum * step.value
590
+ }
591
+ }
592
+ return {
593
+ isBoundary,
594
+ resetOffset: -resetOffset
595
+ }
596
+ }
597
+
598
+ const gestureHandler = Gesture.Pan()
599
+ .onBegin((e) => {
600
+ 'worklet'
601
+ touchfinish.value = false
602
+ cancelAnimation(offset)
603
+ runOnJS(pauseLoop)()
604
+ preAbsolutePos.value = e[strAbso]
605
+ moveTranstion.value = e[strAbso]
606
+ moveTime.value = new Date().getTime()
607
+ })
608
+ .onTouchesMove((e) => {
609
+ 'worklet'
610
+ const touchEventData = e.changedTouches[0]
611
+ const moveDistance = touchEventData[strAbso] - preAbsolutePos.value
612
+ customTrans.value = moveDistance
613
+ const eventData = {
614
+ translation: moveDistance
615
+ }
616
+ // 处理用户一直拖拽到临界点的场景, 不会执行onEnd
617
+ if (!props.circular && !canMove(eventData)) {
618
+ return
619
+ }
620
+ const { isBoundary, resetOffset } = reachBoundary(eventData)
621
+ if (isBoundary && props.circular && !touchfinish.value) {
622
+ offset.value = resetOffset
623
+ } else {
624
+ offset.value = moveDistance + offset.value
625
+ }
626
+ preAbsolutePos.value = touchEventData[strAbso]
627
+ })
628
+ .onTouchesUp((e) => {
629
+ 'worklet'
630
+ const touchEventData = e.changedTouches[0]
631
+ const moveDistance = touchEventData[strAbso] - moveTranstion.value
632
+ touchfinish.value = true
633
+ const eventData = {
634
+ translation: moveDistance
635
+ }
636
+ // 用户手指按下起来, 需要计算正确的位置, 比如在滑动过程中突然按下然后起来,需要计算到正确的位置
637
+ if (!props.circular && !canMove(eventData)) {
638
+ return
639
+ }
640
+ if (!moveDistance) {
641
+ handleLongPress({ translation: customTrans.value })
642
+ } else {
643
+ const strVelocity = moveDistance / (new Date().getTime() - moveTime.value) * 1000
644
+ if (Math.abs(strVelocity) < longPressRatio) {
645
+ handleLongPress(eventData)
646
+ } else {
647
+ handleEnd(eventData)
648
+ }
649
+ }
650
+ })
651
+
652
+ const animatedStyles = useAnimatedStyle(() => {
653
+ if (dir.value === 'x') {
654
+ return { transform: [{ translateX: offset.value }], opacity: step.value > 0 ? 1 : 0 }
655
+ } else {
656
+ return { transform: [{ translateY: offset.value }], opacity: step.value > 0 ? 1 : 0 }
657
+ }
658
+ })
659
+
660
+ function renderSwiper () {
661
+ return (<View style={[normalStyle, layoutStyle, styles.swiper]} {...layoutProps} {...innerProps}>
662
+ <Animated.View style={[{
663
+ flexDirection: dir.value === 'x' ? 'row' : 'column',
664
+ width: '100%',
665
+ height: '100%'
666
+ }, animatedStyles]}>
667
+ {wrapChildren({
668
+ children: arrPages
669
+ }, {
670
+ hasVarDec,
671
+ varContext: varContextRef.current,
672
+ textStyle,
673
+ textProps
674
+ })}
675
+ </Animated.View>
676
+ {showsPagination && renderPagination()}
677
+ </View>)
678
+ }
679
+
680
+ if (totalElements.value === 1) {
681
+ return renderSwiper()
682
+ } else {
683
+ return (<GestureDetector gesture={gestureHandler}>
684
+ {renderSwiper()}
685
+ </GestureDetector>)
686
+ }
687
+ })
688
+ SwiperWrapper.displayName = 'MpxSwiperWrapper'
689
+
690
+ export default SwiperWrapper