@mpxjs/webpack-plugin 2.9.70 → 2.9.71

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 (60) hide show
  1. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  2. package/lib/platform/template/wx/component-config/picker-view.js +1 -5
  3. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  4. package/lib/platform/template/wx/index.js +0 -4
  5. package/lib/runtime/components/react/context.ts +8 -0
  6. package/lib/runtime/components/react/dist/context.js +2 -0
  7. package/lib/runtime/components/react/dist/getInnerListeners.js +34 -31
  8. package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
  9. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +93 -58
  10. package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
  11. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +35 -0
  12. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +151 -127
  13. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +38 -34
  14. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
  15. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +11 -4
  16. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +31 -8
  17. package/lib/runtime/components/react/dist/mpx-swiper.jsx +670 -0
  18. package/lib/runtime/components/react/dist/mpx-view.jsx +15 -53
  19. package/lib/runtime/components/react/dist/pickerFaces.js +7 -6
  20. package/lib/runtime/components/react/dist/pickerVIewContext.js +14 -0
  21. package/lib/runtime/components/react/dist/pickerViewIndicator.jsx +23 -0
  22. package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
  23. package/lib/runtime/components/react/dist/useAnimationHooks.js +20 -2
  24. package/lib/runtime/components/react/dist/utils.jsx +74 -11
  25. package/lib/runtime/components/react/getInnerListeners.ts +43 -32
  26. package/lib/runtime/components/react/mpx-button.tsx +20 -57
  27. package/lib/runtime/components/react/mpx-movable-view.tsx +119 -74
  28. package/lib/runtime/components/react/mpx-navigator.tsx +1 -1
  29. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
  30. package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
  31. package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
  32. package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
  33. package/lib/runtime/components/react/mpx-scroll-view.tsx +21 -10
  34. package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
  35. package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
  36. package/lib/runtime/components/react/mpx-view.tsx +18 -65
  37. package/lib/runtime/components/react/pickerFaces.ts +10 -7
  38. package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
  39. package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
  40. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  41. package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
  42. package/lib/runtime/components/react/types/global.d.ts +10 -0
  43. package/lib/runtime/components/react/useAnimationHooks.ts +24 -3
  44. package/lib/runtime/components/react/utils.tsx +85 -12
  45. package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
  46. package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
  47. package/lib/template-compiler/compiler.js +61 -13
  48. package/lib/wxss/loader.js +15 -2
  49. package/package.json +3 -3
  50. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +0 -480
  51. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +0 -68
  52. package/lib/runtime/components/react/dist/mpx-swiper/type.js +0 -1
  53. package/lib/runtime/components/react/dist/pickerOverlay.jsx +0 -21
  54. package/lib/runtime/components/react/dist/types/common.js +0 -1
  55. package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
  56. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  57. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  58. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
  59. package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
  60. /package/lib/runtime/components/react/types/{common.ts → common.d.ts} +0 -0
@@ -1,68 +0,0 @@
1
- import { forwardRef, useRef } from 'react';
2
- import Carouse from './carouse';
3
- import useInnerProps from '../getInnerListeners';
4
- import useNodesRef from '../useNodesRef'; // 引入辅助函数
5
- /**
6
- * ✔ indicator-dots
7
- * ✔ indicator-color
8
- * ✔ indicator-active-color
9
- * ✔ autoplay
10
- * ✔ current
11
- * ✔ interval
12
- * ✔ duration
13
- * ✔ circular
14
- * ✔ vertical
15
- * ✘ display-multiple-items
16
- * ✘ previous-margin
17
- * ✘ next-margin
18
- * ✔ easing-function ="easeOutCubic"
19
- * ✘ snap-to-edge
20
- */
21
- const _SwiperWrapper = forwardRef((props, ref) => {
22
- const { children } = props;
23
- const innerLayout = useRef({});
24
- const swiperProp = {
25
- circular: props.circular || false,
26
- current: props.current || 0,
27
- autoplay: props.autoplay || false,
28
- duration: props.duration || 500,
29
- interval: props.interval || 5000,
30
- showsPagination: props['indicator-dots'],
31
- dotColor: props['indicator-color'] || 'rgba(0, 0, 0, .3)',
32
- activeDotColor: props['indicator-active-color'] || '#000000',
33
- horizontal: props.vertical !== undefined ? !props.vertical : true,
34
- previousMargin: props['previous-margin'] ? parseInt(props['previous-margin']) : 0,
35
- nextMargin: props['next-margin'] ? parseInt(props['next-margin']) : 0,
36
- enableOffset: props['enable-offset'] || true,
37
- enableVar: props['enable-var'] || false,
38
- parentFontSize: props['parent-font-size'],
39
- parentWidth: props['parent-width'],
40
- parentHeight: props['parent-height'],
41
- style: props.style || {},
42
- externalVarContext: props['external-var-context'],
43
- bindchange: props.bindchange,
44
- easingFunction: props['easing-function'] || 'default'
45
- };
46
- const nodeRef = useRef(null);
47
- useNodesRef(props, ref, nodeRef, {});
48
- const innerProps = useInnerProps(props, {
49
- ref: nodeRef
50
- }, [
51
- 'indicator-dots',
52
- 'indicator-color',
53
- 'indicator-active-color',
54
- 'previous-margin',
55
- 'vertical',
56
- 'previous-margin',
57
- 'next-margin',
58
- 'easing-function'
59
- ], { layoutRef: innerLayout });
60
- const getInnerLayout = (layout) => {
61
- innerLayout.current = layout.current;
62
- };
63
- return <Carouse getInnerLayout={getInnerLayout} innerProps={innerProps} {...innerProps} {...swiperProp}>
64
- {children}
65
- </Carouse>;
66
- });
67
- _SwiperWrapper.displayName = 'MpxSwiper';
68
- export default _SwiperWrapper;
@@ -1 +0,0 @@
1
- export {};
@@ -1,21 +0,0 @@
1
- import React from 'react';
2
- import { StyleSheet, View } from 'react-native';
3
- const Overlay = ({ itemHeight, overlayItemStyle, overlayContainerStyle }) => {
4
- return (<View style={[styles.overlayContainer, overlayContainerStyle]} pointerEvents={'none'}>
5
- <View style={[styles.selection, { height: itemHeight }, overlayItemStyle]}/>
6
- </View>);
7
- };
8
- const styles = StyleSheet.create({
9
- overlayContainer: {
10
- ...StyleSheet.absoluteFillObject,
11
- justifyContent: 'center',
12
- alignItems: 'center'
13
- },
14
- selection: {
15
- borderTopWidth: 1,
16
- borderBottomWidth: 1,
17
- borderColor: 'rgba(0, 0, 0, 0.05)',
18
- alignSelf: 'stretch'
19
- }
20
- });
21
- export default React.memo(Overlay);
@@ -1 +0,0 @@
1
- export {};
@@ -1,527 +0,0 @@
1
- /**
2
- * swiper 实现
3
- */
4
- import { Animated, View, ScrollView, Dimensions, NativeSyntheticEvent, NativeScrollEvent, NativeScrollPoint, Platform, LayoutChangeEvent } from 'react-native'
5
- import { JSX, forwardRef, useState, useRef, useEffect, ReactNode } from 'react'
6
- import { CarouseProps, CarouseState } from './type'
7
- import { getCustomEvent } from '../getInnerListeners'
8
- import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
9
- import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from '../utils'
10
-
11
- /**
12
- * 默认的Style类型
13
- */
14
- const styles: { [key: string]: Object } = {
15
- slide: {
16
- backgroundColor: 'transparent'
17
- },
18
- container_x: {
19
- position: 'relative'
20
- },
21
- container_y: {
22
- position: 'relative'
23
- },
24
- pagination_x: {
25
- position: 'absolute',
26
- bottom: 25,
27
- left: 0,
28
- right: 0,
29
- flexDirection: 'row',
30
- flex: 1,
31
- justifyContent: 'center',
32
- alignItems: 'center'
33
- },
34
-
35
- pagination_y: {
36
- position: 'absolute',
37
- right: 15,
38
- top: 0,
39
- bottom: 0,
40
- flexDirection: 'column',
41
- flex: 1,
42
- justifyContent: 'center',
43
- alignItems: 'center'
44
- }
45
- }
46
-
47
- const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, CarouseProps>((props, ref): JSX.Element => {
48
- // 默认取水平方向的width
49
- const { width } = Dimensions.get('window')
50
- const {
51
- style,
52
- previousMargin = 0,
53
- nextMargin = 0,
54
- enableVar,
55
- externalVarContext,
56
- parentFontSize,
57
- parentWidth,
58
- parentHeight
59
- } = props
60
- // 计算transform之类的
61
- const {
62
- normalStyle,
63
- hasVarDec,
64
- varContextRef,
65
- hasSelfPercent,
66
- setWidth,
67
- setHeight
68
- } = useTransformStyle(style, {
69
- enableVar,
70
- externalVarContext,
71
- parentFontSize,
72
- parentWidth,
73
- parentHeight
74
- })
75
- const { textStyle, innerStyle } = splitStyle(normalStyle)
76
- const { textProps } = splitProps(props)
77
- const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children
78
- const totalElements = Array.isArray(newChild) ? newChild.length : (newChild ? 1 : 0)
79
- const defaultHeight = (normalStyle?.height || 150)
80
- const defaultWidth = (normalStyle?.width || width || 375)
81
- const dir = props.horizontal === false ? 'y' : 'x'
82
- // state的offset默认值
83
- // const initIndex = props.circular ? props.current + 1: (props.current || 0)
84
- // 记录真正的下标索引, 不包括循环前后加入的索引, 游标
85
- const initIndex = props.current || 0
86
- // 这里要排除超过元素个数的设置
87
- const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0)
88
- const defaultX = (defaultWidth * initOffsetIndex) || 0
89
- const defaultY = (defaultHeight * initOffsetIndex) || 0
90
- // 主动scorllTo时是否要出发onScrollEnd
91
- const needTriggerScrollEnd = useRef(true)
92
- // 内部存储上一次的offset值
93
- const autoplayTimerRef = useRef<ReturnType <typeof setTimeout> | null>(null)
94
- const scrollViewRef = useRef<ScrollView & View>(null)
95
- useNodesRef<ScrollView & View, CarouseProps>(props, ref, scrollViewRef, {
96
- style: normalStyle
97
- })
98
- const {
99
- // 存储layout布局信息
100
- layoutRef,
101
- layoutProps,
102
- layoutStyle
103
- } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout: onWrapperLayout })
104
- // 内部存储上一次的偏移量
105
- const internalsRef = useRef({
106
- offset: {
107
- x: 0,
108
- y: 0
109
- },
110
- isScrolling: false
111
- })
112
- const isDragRef = useRef(false)
113
- const [state, setState] = useState({
114
- width: dir === 'x' && typeof defaultWidth === 'number' ? defaultWidth - previousMargin - nextMargin : defaultWidth,
115
- height: dir === 'y' && typeof defaultHeight === 'number' ? defaultHeight - previousMargin - nextMargin : defaultHeight,
116
- // 真正的游标索引, 从0开始
117
- index: initIndex,
118
- total: totalElements,
119
- offset: {
120
- x: 0,
121
- y: 0
122
- },
123
- dir
124
- } as CarouseState)
125
- /**
126
- * @desc: 开启下一次自动轮播
127
- */
128
- function createAutoPlay () {
129
- autoplayTimerRef.current && clearTimeout(autoplayTimerRef.current)
130
- autoplayTimerRef.current = setTimeout(() => {
131
- startAutoPlay()
132
- }, props.interval || 500)
133
- }
134
-
135
- useEffect(() => {
136
- // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
137
- if (props.autoplay) {
138
- createAutoPlay()
139
- }
140
- }, [props.autoplay, props.current, state.index, state.width, state.height])
141
-
142
- useEffect(() => {
143
- // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
144
- if (!props.autoplay && props.current !== undefined && props.current !== state.index) {
145
- const initIndex = props.current || 0
146
- // 这里要排除超过元素个数的设置
147
- const { nextIndex, nextOffset } = getMultiNextConfig(props.current)
148
- // 1. 安卓需要主动更新下内部状态, 2. IOS不能触发完wcrollTo之后立即updateState, 会造成滑动两次
149
- // 2. setTimeout 是fix 当再渲染过程中触发scrollTo失败的问题
150
- if (Platform.OS === 'ios') {
151
- needTriggerScrollEnd.current = false
152
- setTimeout(() => {
153
- scrollViewRef.current?.scrollTo({
154
- ...nextOffset,
155
- animated: true
156
- })
157
- }, 50)
158
- } else {
159
- updateState(nextIndex, nextOffset)
160
- }
161
- }
162
- }, [props.current, state.width, state.height])
163
-
164
- function getMultiNextConfig (target: number) {
165
- const step = state.dir === 'x' ? state.width : state.height
166
- const targetPos = step * props.current
167
- const targetOffset = {
168
- x: dir === 'x' ? targetPos : 0,
169
- y: dir === 'y' ? targetPos : 0
170
- }
171
- return {
172
- nextIndex: target,
173
- nextOffset: targetOffset
174
- }
175
- }
176
- /**
177
- * @desc: 更新状态: index和offset, 并响应索引变化的事件
178
- * scrollViewOffset: 移动到的目标位置
179
- */
180
- function updateIndex (scrollViewOffset: NativeScrollPoint, useIndex = false) {
181
- const { nextIndex, nextOffset } = getNextConfig(scrollViewOffset)
182
- updateState(nextIndex, nextOffset)
183
- // 更新完状态之后, 开启新的loop
184
- }
185
-
186
- /**
187
- * 更新索引状态
188
- */
189
- function updateState (index: number, offset: { x: number, y: number}) {
190
- internalsRef.current.offset = offset
191
- setState((preState) => {
192
- const newState = {
193
- ...preState,
194
- index: index,
195
- // offset用来指示当前scrollView的偏移量
196
- offset: offset
197
- }
198
- return newState
199
- })
200
- internalsRef.current.isScrolling = false
201
- // getCustomEvent
202
- const eventData = getCustomEvent('change', {}, { detail: { current: index, source: 'touch' }, layoutRef: layoutRef })
203
- props.bindchange && props.bindchange(eventData)
204
- }
205
-
206
- /**
207
- * @desc: 获取下一个位置的索引、scrollView的contentOffset、scrollTo到的offset
208
- * @desc: 包括正循环、反向循环、不循环
209
- * 其中循环模式为了实现无缝链接, 会将结合contentOffset, 和 scrollTo的offset,
210
- * 先scrollTo一个位置的坐标, 然后通过updateIndex设置真正的index和内容的offset,视觉上是无缝
211
- */
212
- function getNextConfig (scrollViewOffset: NativeScrollPoint) {
213
- const step = state.dir === 'x' ? state.width : state.height
214
- const currentOffset = state.offset
215
- let nextIndex = state.index + 1
216
- let nextOffset = currentOffset
217
- // autoMoveOffset scrollView 滚动到前后增加的位置
218
- let autoMoveOffset = currentOffset
219
- let isBack = false
220
- let isAutoEnd = false
221
- // 如果是循环反向的
222
- if (scrollViewOffset?.[state.dir] < currentOffset[state.dir]) {
223
- isBack = true
224
- nextIndex = isBack ? nextIndex - 2 : nextIndex
225
- }
226
- if (!props.circular) {
227
- nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * nextIndex })
228
- } else {
229
- if (isBack) {
230
- if (nextIndex < 0) {
231
- // 反向: scollView 滚动到虚拟的位置
232
- autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: 0 })
233
- nextIndex = state.total - 1
234
- // 反向: 数组最后一个index
235
- nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * state.total })
236
- isAutoEnd = true
237
- } else {
238
- // 反向非最后一个
239
- nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step })
240
- }
241
- } else {
242
- if (nextIndex > state.total - 1) {
243
- autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: step * (nextIndex + 1) })
244
- nextIndex = 0
245
- nextOffset = Object.assign({}, currentOffset, { [state.dir]: step })
246
- isAutoEnd = true
247
- } else {
248
- // nextIndex = nextIndex,
249
- nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step })
250
- }
251
- }
252
- }
253
- return {
254
- // 下一个要滚动到的实际元素的索引
255
- nextIndex,
256
- // 下一个要滚动到实际元素的offset
257
- nextOffset,
258
- // scrollTo一个位置的坐标, 虚拟元素的位置
259
- autoMoveOffset,
260
- isAutoEnd
261
- }
262
- }
263
-
264
- /**
265
- * @desc: 开启自动轮播
266
- */
267
- function startAutoPlay () {
268
- if (state.width && isNaN(+state.width)) {
269
- createAutoPlay()
270
- return
271
- }
272
- if (!Array.isArray(props.children)) {
273
- return
274
- }
275
- const step = state.dir === 'x' ? state.width : state.height
276
- const { nextOffset, autoMoveOffset, isAutoEnd } = getNextConfig(state.offset)
277
- // 这里可以scroll到下一个元素, 但是把scrollView的偏移量在设置为content,视觉效果就没了吧
278
- if (Platform.OS === 'ios') {
279
- if (!isAutoEnd) {
280
- scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true })
281
- } else {
282
- if (state.dir === 'x') {
283
- scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.x, animated: true })
284
- } else {
285
- scrollViewRef.current?.scrollTo({ x: autoMoveOffset.y, y: autoMoveOffset.y, animated: true })
286
- }
287
- }
288
- } else {
289
- if (!isAutoEnd) {
290
- scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true })
291
- onScrollEnd({
292
- nativeEvent: {
293
- contentOffset: {
294
- x: +nextOffset.x,
295
- y: +nextOffset.y
296
- }
297
- }
298
- } as NativeSyntheticEvent<NativeScrollEvent>)
299
- } else {
300
- // 安卓无法实现视觉的无缝连接, 只能回到真正的位置, 且安卓调用scrollTo不能触发onMomentumScrollEnd,还未找到为啥
301
- if (state.dir === 'x') {
302
- scrollViewRef.current?.scrollTo({ x: step, y: step, animated: true })
303
- } else {
304
- scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: step, animated: true })
305
- }
306
- updateState(0, nextOffset)
307
- }
308
- }
309
- }
310
-
311
- /**
312
- * 当用户开始拖动此视图时调用此函数, 更新当前在滚动态
313
- */
314
- function onScrollBegin () {
315
- internalsRef.current.isScrolling = true
316
- }
317
-
318
- /**
319
- * 当用户开始拖动结束
320
- * 注意: 当手动调用scrollTo的时候, 安卓不会触发onMomentumScrollEnd, IOS会触发onMomentumScrollEnd
321
- */
322
- function onScrollEnd (event: NativeSyntheticEvent<NativeScrollEvent>) {
323
- if (Platform.OS === 'ios' && !needTriggerScrollEnd.current) {
324
- const { nextIndex, nextOffset } = getMultiNextConfig(props.current)
325
- updateState(nextIndex, nextOffset)
326
- needTriggerScrollEnd.current = true
327
- return
328
- }
329
- if (totalElements === 1) {
330
- return
331
- }
332
- internalsRef.current.isScrolling = false
333
- // 用户手动滑动更新索引后,如果开启了自动轮播等重新开始
334
- updateIndex(event.nativeEvent.contentOffset, true)
335
- }
336
-
337
- /**
338
- * 当拖拽结束时,检测是否可滚动
339
- */
340
- function onScrollEndDrag (event: NativeSyntheticEvent<NativeScrollEvent>) {
341
- const { contentOffset } = event.nativeEvent
342
- const { index, total } = state
343
- isDragRef.current = true
344
- const internalOffset = internalsRef.current.offset
345
- const previousOffset = props.horizontal ? internalOffset.x : internalOffset.y
346
- const moveOffset = props.horizontal ? contentOffset.x : contentOffset.y
347
- if (previousOffset === moveOffset && (index === 0 || index === total - 1)) {
348
- internalsRef.current.isScrolling = false
349
- }
350
- }
351
-
352
- /**
353
- * @desc: 水平方向时,获取元素的布局,更新, 其中如果传递100%时需要依赖measure计算元算的宽高
354
- */
355
- function onWrapperLayout (e: LayoutChangeEvent) {
356
- scrollViewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
357
- layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
358
- const isWDiff = state.width !== width
359
- const isHDiff = state.height !== height
360
- if (isWDiff || isHDiff) {
361
- const changeState = {
362
- width: isWDiff ? width : state.width,
363
- height: isHDiff ? height : state.height
364
- }
365
- const attr = state.dir === 'x' ? 'width' : 'height'
366
- changeState[attr] = changeState[attr] - previousMargin - nextMargin
367
- const correctOffset = Object.assign({}, state.offset, {
368
- [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
369
- })
370
- state.width = changeState.width
371
- state.height = changeState.height
372
- // 这里setState之后,会再触发重新渲染, renderScrollView会再次触发onScrollEnd,
373
- setState((preState) => {
374
- return {
375
- ...preState,
376
- width: changeState.width,
377
- height: changeState.height
378
- }
379
- })
380
- }
381
- props.getInnerLayout && props.getInnerLayout(layoutRef)
382
- })
383
- }
384
-
385
- function getOffset (): Array<number> {
386
- const step = state.dir === 'x' ? state.width : state.height
387
- if (!step || Number.isNaN(+step)) return []
388
- const offsetArray = []
389
- for (let i = 0; i < totalElements; i++) {
390
- offsetArray.push(i * step)
391
- }
392
- return offsetArray
393
- }
394
-
395
- function renderScrollView (pages: ReactNode) {
396
- const offsetsArray = getOffset()
397
- const scrollElementProps = {
398
- ref: scrollViewRef,
399
- horizontal: props.horizontal,
400
- pagingEnabled: true,
401
- snapToOffsets: offsetsArray,
402
- decelerationRate: 0.99, // 'fast'
403
- showsHorizontalScrollIndicator: false,
404
- showsVerticalScrollIndicator: false,
405
- bounces: false,
406
- scrollsToTop: false,
407
- removeClippedSubviews: true,
408
- automaticallyAdjustContentInsets: false
409
- }
410
- const layoutStyle = dir === 'x' ? { width: defaultWidth, height: defaultHeight } : { width: defaultWidth }
411
- return (
412
- <Animated.ScrollView
413
- {...scrollElementProps}
414
- style={[layoutStyle]}
415
- overScrollMode="always"
416
- contentOffset={state.offset}
417
- onScrollBeginDrag={onScrollBegin}
418
- onMomentumScrollEnd={onScrollEnd}
419
- onScrollEndDrag={onScrollEndDrag}
420
- >
421
- {pages}
422
- </Animated.ScrollView>
423
- )
424
- }
425
-
426
- function renderPagination () {
427
- if (state.total <= 1) return null
428
- const dots: Array<ReactNode> = []
429
- const activeDotStyle = [{
430
- backgroundColor: props.activeDotColor || '#007aff',
431
- width: 8,
432
- height: 8,
433
- borderRadius: 4,
434
- marginLeft: 3,
435
- marginRight: 3,
436
- marginTop: 3,
437
- marginBottom: 3
438
- }]
439
- const dotStyle = [{
440
- backgroundColor: props.dotColor || 'rgba(0,0,0,.2)',
441
- width: 8,
442
- height: 8,
443
- borderRadius: 4,
444
- marginLeft: 3,
445
- marginRight: 3,
446
- marginTop: 3,
447
- marginBottom: 3
448
- }]
449
- for (let i = 0; i < state.total; i++) {
450
- if (i === state.index) {
451
- dots.push(<View style={activeDotStyle} key={i}></View>)
452
- } else {
453
- dots.push(<View style={dotStyle} key={i}></View>)
454
- }
455
- }
456
- return (
457
- <View
458
- pointerEvents="none"
459
- style={[styles['pagination_' + state.dir]]}
460
- >
461
- {dots}
462
- </View>
463
- )
464
- }
465
-
466
- function renderPages () {
467
- const { width, height } = state
468
- const { children } = props
469
- const { circular } = props
470
- const pageStyle = { width: width, height: height }
471
- // 设置了previousMargin或者nextMargin,
472
- // 1. 元素的宽度是减去这两个数目之和
473
- // 2. previousMargin设置marginLeft正值, nextmargin设置marginRight负值
474
- // 3. 第一个元素设置previousMargin 和 nextMargin, 最后一个元素
475
- if (totalElements > 1 && Array.isArray(children)) {
476
- let arrElements: (Array<ReactNode>) = []
477
- // pages = ["2", "0", "1", "2", "0"]
478
- const pages = Array.isArray(children) ? Object.keys(children) : []
479
- /* 无限循环的时候 */
480
- if (circular) {
481
- pages.unshift(totalElements - 1 + '')
482
- pages.push('0')
483
- }
484
- arrElements = pages.map((page, i) => {
485
- const extraStyle = {} as {
486
- [key: string]: any
487
- }
488
- if (i === 0 && dir === 'x' && typeof width === 'number') {
489
- previousMargin && (extraStyle.marginLeft = previousMargin)
490
- } else if (i === pages.length - 1 && typeof width === 'number') {
491
- nextMargin && (extraStyle.marginRight = nextMargin)
492
- }
493
- return (<View style={[pageStyle, styles.slide, extraStyle]} key={'page' + i}>
494
- {wrapChildren(
495
- {
496
- children: children[+page]
497
- },
498
- {
499
- hasVarDec,
500
- varContext: varContextRef.current,
501
- textStyle,
502
- textProps
503
- }
504
- )}
505
- </View>)
506
- })
507
- return arrElements
508
- } else {
509
- const realElement = (
510
- <View style={pageStyle} key={0}>
511
- {children}
512
- </View>
513
- )
514
- return realElement
515
- }
516
- }
517
-
518
- const pages: Array<ReactNode> | ReactNode = renderPages()
519
- return (<View style={[normalStyle, innerStyle, layoutStyle]} {...layoutProps}>
520
- {renderScrollView(pages)}
521
- {props.showsPagination && renderPagination()}
522
- </View>)
523
- })
524
-
525
- _Carouse.displayName = 'MpxCarouse'
526
-
527
- export default _Carouse