@mpxjs/webpack-plugin 2.9.59 → 2.9.62

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 (106) hide show
  1. package/lib/platform/style/wx/index.js +314 -254
  2. package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
  3. package/lib/platform/template/wx/component-config/checkbox.js +8 -0
  4. package/lib/platform/template/wx/component-config/cover-image.js +15 -0
  5. package/lib/platform/template/wx/component-config/cover-view.js +9 -0
  6. package/lib/platform/template/wx/component-config/form.js +13 -1
  7. package/lib/platform/template/wx/component-config/icon.js +8 -0
  8. package/lib/platform/template/wx/component-config/index.js +5 -1
  9. package/lib/platform/template/wx/component-config/label.js +15 -0
  10. package/lib/platform/template/wx/component-config/movable-area.js +18 -1
  11. package/lib/platform/template/wx/component-config/movable-view.js +18 -1
  12. package/lib/platform/template/wx/component-config/navigator.js +8 -0
  13. package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
  14. package/lib/platform/template/wx/component-config/picker-view.js +18 -2
  15. package/lib/platform/template/wx/component-config/picker.js +14 -1
  16. package/lib/platform/template/wx/component-config/radio-group.js +8 -0
  17. package/lib/platform/template/wx/component-config/radio.js +8 -0
  18. package/lib/platform/template/wx/component-config/root-portal.js +15 -0
  19. package/lib/platform/template/wx/component-config/switch.js +8 -0
  20. package/lib/platform/template/wx/component-config/unsupported.js +1 -3
  21. package/lib/react/processScript.js +2 -0
  22. package/lib/runtime/components/react/context.ts +38 -0
  23. package/lib/runtime/components/react/dist/context.js +7 -0
  24. package/lib/runtime/components/react/dist/getInnerListeners.js +22 -11
  25. package/lib/runtime/components/react/dist/mpx-button.jsx +67 -45
  26. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +81 -0
  27. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +152 -0
  28. package/lib/runtime/components/react/dist/mpx-form.jsx +59 -0
  29. package/lib/runtime/components/react/dist/mpx-icon.jsx +51 -0
  30. package/lib/runtime/components/react/dist/mpx-image/index.jsx +17 -22
  31. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +0 -1
  32. package/lib/runtime/components/react/dist/mpx-input.jsx +38 -16
  33. package/lib/runtime/components/react/dist/mpx-label.jsx +63 -0
  34. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +46 -0
  35. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
  36. package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
  37. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
  38. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
  39. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +139 -0
  40. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +90 -0
  41. package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
  42. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
  43. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
  44. package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
  45. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +15 -0
  46. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +68 -0
  47. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +79 -0
  48. package/lib/runtime/components/react/dist/mpx-radio.jsx +169 -0
  49. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +11 -0
  50. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +66 -50
  51. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +206 -147
  52. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +9 -7
  53. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +3 -3
  54. package/lib/runtime/components/react/dist/mpx-switch.jsx +76 -0
  55. package/lib/runtime/components/react/dist/mpx-text.jsx +7 -19
  56. package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
  57. package/lib/runtime/components/react/dist/mpx-view.jsx +326 -96
  58. package/lib/runtime/components/react/dist/mpx-web-view.jsx +9 -15
  59. package/lib/runtime/components/react/dist/types/common.js +1 -0
  60. package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
  61. package/lib/runtime/components/react/dist/utils.js +82 -14
  62. package/lib/runtime/components/react/getInnerListeners.ts +25 -13
  63. package/lib/runtime/components/react/mpx-button.tsx +87 -67
  64. package/lib/runtime/components/react/mpx-checkbox-group.tsx +147 -0
  65. package/lib/runtime/components/react/mpx-checkbox.tsx +245 -0
  66. package/lib/runtime/components/react/mpx-form.tsx +89 -0
  67. package/lib/runtime/components/react/mpx-icon.tsx +103 -0
  68. package/lib/runtime/components/react/mpx-image/index.tsx +20 -32
  69. package/lib/runtime/components/react/mpx-image/svg.tsx +2 -2
  70. package/lib/runtime/components/react/mpx-input.tsx +54 -26
  71. package/lib/runtime/components/react/mpx-label.tsx +115 -0
  72. package/lib/runtime/components/react/mpx-movable-area.tsx +67 -0
  73. package/lib/runtime/components/react/mpx-movable-view.tsx +425 -0
  74. package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
  75. package/lib/runtime/components/react/mpx-picker/date.tsx +83 -0
  76. package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
  77. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +153 -0
  78. package/lib/runtime/components/react/mpx-picker/region.tsx +104 -0
  79. package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
  80. package/lib/runtime/components/react/mpx-picker/selector.tsx +92 -0
  81. package/lib/runtime/components/react/mpx-picker/time.tsx +274 -0
  82. package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
  83. package/lib/runtime/components/react/mpx-picker-view-column.tsx +28 -0
  84. package/lib/runtime/components/react/mpx-picker-view.tsx +104 -0
  85. package/lib/runtime/components/react/mpx-radio-group.tsx +147 -0
  86. package/lib/runtime/components/react/mpx-radio.tsx +246 -0
  87. package/lib/runtime/components/react/mpx-root-portal.tsx +25 -0
  88. package/lib/runtime/components/react/mpx-scroll-view.tsx +82 -58
  89. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +203 -156
  90. package/lib/runtime/components/react/mpx-swiper/index.tsx +12 -13
  91. package/lib/runtime/components/react/mpx-swiper/type.ts +11 -4
  92. package/lib/runtime/components/react/mpx-swiper-item.tsx +5 -3
  93. package/lib/runtime/components/react/mpx-switch.tsx +127 -0
  94. package/lib/runtime/components/react/mpx-text.tsx +52 -68
  95. package/lib/runtime/components/react/mpx-textarea.tsx +2 -2
  96. package/lib/runtime/components/react/mpx-view.tsx +373 -140
  97. package/lib/runtime/components/react/mpx-web-view.tsx +24 -28
  98. package/lib/runtime/components/react/types/common.ts +12 -0
  99. package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
  100. package/lib/runtime/components/react/types/global.d.ts +4 -0
  101. package/lib/runtime/components/react/useNodesRef.ts +3 -8
  102. package/lib/runtime/components/react/utils.ts +93 -15
  103. package/lib/runtime/optionProcessor.js +19 -17
  104. package/lib/template-compiler/compiler.js +56 -41
  105. package/lib/template-compiler/gen-node-react.js +7 -7
  106. package/package.json +6 -3
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * swiper 实现
3
3
  */
4
- import { View, ScrollView, Dimensions, LayoutChangeEvent, NativeSyntheticEvent, NativeScrollEvent, NativeScrollPoint } from 'react-native'
5
- import React, { forwardRef, useState, useRef, useEffect, ReactNode } from 'react'
4
+ import { Animated, View, ScrollView, Dimensions, NativeSyntheticEvent, NativeScrollEvent, NativeScrollPoint, Platform } from 'react-native'
5
+ import { JSX, forwardRef, useState, useRef, useEffect, ReactNode } from 'react'
6
6
  import { CarouseProps, CarouseState } from './type'
7
7
  import { getCustomEvent } from '../getInnerListeners'
8
8
  import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
@@ -11,6 +11,9 @@ import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
11
11
  * 默认的Style类型
12
12
  */
13
13
  const styles: { [key: string]: Object } = {
14
+ slide: {
15
+ backgroundColor: 'transparent'
16
+ },
14
17
  container_x: {
15
18
  position: 'relative',
16
19
  },
@@ -41,23 +44,31 @@ const styles: { [key: string]: Object } = {
41
44
  }
42
45
 
43
46
 
44
- const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>((props , ref): React.JSX.Element => {
47
+ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>((props , ref): JSX.Element => {
45
48
  // 默认取水平方向的width
46
49
  const { width } = Dimensions.get('window')
47
- const defaultHeight = 150
50
+ const { styleObj } = props
51
+ const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children
52
+ const totalElements = Array.isArray(newChild) ? newChild.length : (newChild ? 1 : 0)
53
+ // const defaultHeight = (styleObj?.height || 150) - previousMargin - nextMargin
54
+ // const defaultWidth = (styleObj?.width || width || 375) - previousMargin - nextMargin
55
+ const defaultHeight = (styleObj?.height || 150)
56
+ const defaultWidth = (styleObj?.width || width || 375)
48
57
  const dir = props.horizontal === false ? 'y' : 'x'
49
58
  // state的offset默认值
50
- const defaultX = width * (props.circular ? props.current + 1 : props.current) || 0
51
- const defaultY = defaultHeight * (props.circular ? props.current + 1 : props.current) || 0
59
+ // const initIndex = props.circular ? props.current + 1: (props.current || 0)
60
+ // 记录真正的下标索引, 不包括循环前后加入的索引, 游标
61
+ const initIndex = props.current || 0
62
+ // 这里要排除超过元素个数的设置
63
+ const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0)
64
+ // const defaultX = (defaultWidth * initOffsetIndex + previousMargin) || 0
65
+ // const defaultY = (defaultHeight * initOffsetIndex + previousMargin) || 0
66
+ const defaultX = (defaultWidth * initOffsetIndex) || 0
67
+ const defaultY = (defaultHeight * initOffsetIndex) || 0
52
68
  // 内部存储上一次的offset值
53
- const newChild = Array.isArray(props.children) ? props.children.filter(child => child) : props.children
54
- // 默认设置为初次渲染
55
- const initRenderRef = useRef(true)
56
69
  const autoplayTimerRef = useRef<ReturnType <typeof setTimeout> | null>(null)
57
- let loopJumpTimerRef = useRef<ReturnType <typeof setTimeout> | null>(null)
58
70
  const { nodeRef: scrollViewRef } = useNodesRef<ScrollView, CarouseProps>(props, ref, {
59
71
  })
60
- const autoplayEndRef = useRef(false)
61
72
  // 存储layout布局信息
62
73
  const layoutRef = useRef({})
63
74
  // 内部存储上一次的偏移量
@@ -68,125 +79,169 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
68
79
  },
69
80
  isScrolling: false
70
81
  })
82
+ const isDragRef = useRef(false)
71
83
  const [state, setState] = useState({
72
84
  children: newChild,
73
- width: width || 375,
85
+ width: defaultWidth || 375,
74
86
  height: defaultHeight,
75
- index: 0,
76
- total: Array.isArray(newChild) ? newChild.length : ( newChild ? 1 : 0),
87
+ // 真正的游标索引, 从0开始
88
+ index: initIndex,
89
+ total: totalElements,
77
90
  offset: {
78
91
  x: dir === 'x' ? defaultX : 0,
79
92
  y: dir === 'y' ? defaultY: 0
80
93
  },
81
- loopJump: false,
82
94
  dir
83
95
  } as CarouseState);
84
96
 
97
+ /**
98
+ * @desc: 开启下一次自动轮播
99
+ */
100
+ function createAutoPlay () {
101
+ autoplayTimerRef.current && clearTimeout(autoplayTimerRef.current)
102
+ autoplayTimerRef.current = setTimeout(() => {
103
+ startAutoPlay()
104
+ }, props.interval || 500)
105
+ }
106
+
85
107
  useEffect(() => {
86
108
  // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
87
109
  if (props.autoplay) {
88
- startAutoPlay()
89
- } else {
90
- startSwiperLoop()
110
+ createAutoPlay()
91
111
  }
92
- }, [props.autoplay, props.current, state.index]);
112
+ }, [props.autoplay, props.current, state.index, state.width, state.height]);
93
113
 
94
114
  /**
95
- * 更新index,以视图的offset计算当前的索引
115
+ * @desc: 更新状态: indexoffset, 并响应索引变化的事件
116
+ * scrollViewOffset: 移动到的目标位置
96
117
  */
97
- function updateIndex (scrollViewOffset: NativeScrollPoint) {
98
- const diff = scrollViewOffset[dir] - internalsRef.current.offset[state.dir]
99
- if (!diff) return
100
-
101
- const step = dir === 'x' ? state.width : state.height
102
- let loopJump = false
103
- let newIndex = state.index + Math.round(diff / step)
104
- // 若是循环circular
105
- // 1. 当前索引-1, 初始化为最后一个索引, 且scrollView的偏移量设置为 每个元素的步长 * 一共多少个元素, 这里为什么不减一呢
106
- // 2. 当前索引>total, 初始化为第一个元素,且scrollView的偏移量设置为一个元素的步长
107
- if (props.circular) {
108
- if (state.index <= -1) {
109
- newIndex = state.total - 1
110
- scrollViewOffset[state.dir] = step * state.total
111
- loopJump = true
112
- } else if (newIndex >= state.total) {
113
- newIndex = 0
114
- scrollViewOffset[state.dir] = step
115
- loopJump = true
116
- }
117
- }
118
- // 存储当前的偏移量
119
- internalsRef.current.offset = scrollViewOffset
120
- // 这里需不需要区分是否loop,初始化????
118
+ function updateIndex (scrollViewOffset: NativeScrollPoint, useIndex = false) {
119
+ const { nextIndex, nextOffset } = getNextConfig(scrollViewOffset)
120
+ internalsRef.current.offset = nextOffset
121
121
  setState((preState) => {
122
122
  const newState = {
123
123
  ...preState,
124
- index: newIndex,
125
- offset: scrollViewOffset,
126
- loopJump
124
+ index: nextIndex,
125
+ // offset用来指示当前scrollView的偏移量
126
+ offset: nextOffset,
127
127
  }
128
128
  return newState
129
129
  })
130
130
  internalsRef.current.isScrolling = false
131
131
  // getCustomEvent
132
- const eventData = getCustomEvent('change', {}, { detail: {current: newIndex, source: 'touch' }, layoutRef: layoutRef })
132
+ const eventData = getCustomEvent('change', {}, { detail: {current: nextIndex, source: 'touch' }, layoutRef: layoutRef })
133
133
  props.bindchange && props.bindchange(eventData)
134
134
  // 更新完状态之后, 开启新的loop
135
135
  }
136
136
 
137
137
  /**
138
- * 用户手动点击播放
139
- * 触发scrollView的onScrollEnd事件 => 然后更新索引 => 通过useEffect事件 => startSwiperLoop => 主动更新scrollView到指定的位置
140
- * 若是circular, 到最后一个索引会更新为0,但是视觉要scrollView到下一个
141
- * 若是circular, 到第一个再往前索引会更新为total-1, 但是视觉是展示的最后一个
138
+ * @desc: 获取下一个位置的索引、scrollView的contentOffset、scrollTo到的offset
139
+ * @desc: 包括正循环、反向循环、不循环
140
+ * 其中循环模式为了实现无缝链接, 会将结合contentOffset, 和 scrollTo的offset, 先scrollTo一个位置的坐标, 然后通过updateIndex设置真正的index和内容的offset,视觉上是无缝
142
141
  */
143
- function startSwiperLoop () {
144
- loopJumpTimerRef.current = setTimeout(() => {
145
- let offset = { x: 0, y: 0, animated: false}
146
- if (state.index > 0){
147
- offset = props.horizontal ? { x: state.width * state.index, y: 0, animated: false } : { x: 0, y: state.height * state.index, animated: false }
148
- }
149
- if (props.circular) {
150
- offset = props.horizontal ? { x: state.width * (state.index + 1), y: 0, animated: false } : { x: 0, y: state.height * (state.index + 1), animated: false }
142
+ function getNextConfig (scrollViewOffset: NativeScrollPoint) {
143
+ const step = state.dir === 'x' ? state.width : state.height
144
+ let currentOffset = state.offset
145
+ let nextIndex = state.index + 1
146
+ let nextOffset = currentOffset
147
+ // autoMoveOffset scrollView 滚动到前后增加的位置
148
+ let autoMoveOffset = currentOffset
149
+ let isBack = false
150
+ let isAutoEnd = false
151
+ // 如果是循环反向的
152
+ if (scrollViewOffset?.[state.dir] < currentOffset[state.dir]) {
153
+ isBack = true
154
+ nextIndex = isBack ? nextIndex - 2 : nextIndex
155
+ }
156
+ if (!props.circular) {
157
+ // nextIndex = isBack ? nextIndex - 2 : nextIndex
158
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * nextIndex })
159
+ } else {
160
+ if (isBack) {
161
+ if (nextIndex < 0) {
162
+ // 反向: scollView 滚动到虚拟的位置
163
+ autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: 0 })
164
+ nextIndex = state.total - 1
165
+ // 反向: 数组最后一个index
166
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * state.total }),
167
+ isAutoEnd = true
168
+ } else {
169
+ // 反向非最后一个
170
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: ( nextIndex + 1 ) * step })
171
+ }
172
+ } else {
173
+ if (nextIndex > state.total - 1) {
174
+ autoMoveOffset = Object.assign({}, currentOffset, { [state.dir]: step * ( nextIndex + 1 )})
175
+ nextIndex = 0
176
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: step }),
177
+ isAutoEnd = true
178
+ } else {
179
+ // nextIndex = nextIndex,
180
+ nextOffset = Object.assign({}, currentOffset, { [state.dir]: (nextIndex + 1) * step })
181
+ }
151
182
  }
152
- scrollViewRef.current?.scrollTo(offset)
153
- internalsRef.current.offset = offset
154
- }, props.duration || 500)
183
+ }
184
+ return {
185
+ nextIndex,
186
+ nextOffset,
187
+ autoMoveOffset,
188
+ isAutoEnd
189
+ }
155
190
  }
156
191
 
157
192
  /**
158
- * 开启自动轮播
159
- * 每间隔interval scrollView的offset更改到下一个位置,通过onScrollEnd来获取contentOffset再计算要更新的索引index
193
+ * @desc: 开启自动轮播
160
194
  */
161
195
  function startAutoPlay () {
162
- // 已经开启过autopaly则不重新创建
163
- if (!Array.isArray(state.children) || !props.autoplay || internalsRef.current.isScrolling || autoplayEndRef.current) {
196
+ if (state.width && isNaN(+state.width)) {
197
+ createAutoPlay()
164
198
  return
165
199
  }
166
- autoplayTimerRef.current && clearTimeout(autoplayTimerRef.current)
167
- // 非循环自动播放的形式下 到最后一帧 结束自动播放
168
- if (!props.circular && state.index === state.total -1) {
169
- autoplayEndRef.current = true
200
+ if (!Array.isArray(state.children)) {
170
201
  return
171
202
  }
172
-
173
- // 开启自动播放
174
- autoplayTimerRef.current = setTimeout(() => {
175
- if (state.total < 2) return
176
- const nexStep = 1
177
- const toIndex = (props.circular ? 1 : 0) + nexStep + state.index
178
- let x = 0
179
- let y = 0
180
- if (state.dir === 'x') x = toIndex * state.width
181
- if (state.dir === 'y') y = toIndex * state.height
182
- // animated会影响切换的offset,先改为false
183
- scrollViewRef.current?.scrollTo({ x, y, animated: false })
184
-
185
- internalsRef.current.isScrolling = true
186
-
187
- autoplayEndRef.current = false
188
- updateIndex({ x, y })
189
- }, props.interval || 5000)
203
+ const step = state.dir === 'x' ? state.width : state.height
204
+ const { nextOffset, autoMoveOffset, isAutoEnd } = getNextConfig(state.offset)
205
+ // 这里可以scroll到下一个元素, 但是把scrollView的偏移量在设置为content,视觉效果就没了吧
206
+ // scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
207
+ if (Platform.OS === 'ios') {
208
+ if (!isAutoEnd) {
209
+ scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
210
+ } else {
211
+ if (state.dir === 'x') {
212
+ scrollViewRef.current?.scrollTo({ x: autoMoveOffset['x'], y: autoMoveOffset['x'], animated: true })
213
+ } else {
214
+ scrollViewRef.current?.scrollTo({ x: autoMoveOffset['y'], y: autoMoveOffset['y'], animated: true })
215
+ }
216
+ }
217
+ } else {
218
+ if (!isAutoEnd) {
219
+ scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
220
+ onScrollEnd({
221
+ nativeEvent: {
222
+ // @ts-ignore
223
+ x: +nextOffset['x'],
224
+ y: +nextOffset['y']
225
+ }
226
+ })
227
+ } else {
228
+ setTimeout(() => {
229
+ onScrollEnd({
230
+ nativeEvent: {
231
+ // @ts-ignore
232
+ x: 0,
233
+ y: 0
234
+ }
235
+ })
236
+ }, 10)
237
+ if (state.dir === 'x') {
238
+ scrollViewRef.current?.scrollTo({ x: step, y: step, animated: true })
239
+ // scrollViewRef.current?.scrollTo({ x: autoMoveOffset['x'], y: autoMoveOffset['x'], animated: true })
240
+ } else {
241
+ scrollViewRef.current?.scrollTo({ x: autoMoveOffset['y'], y: autoMoveOffset['y'], animated: true })
242
+ }
243
+ }
244
+ }
190
245
  }
191
246
 
192
247
  /**
@@ -195,11 +250,18 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
195
250
  function onScrollBegin () {
196
251
  internalsRef.current.isScrolling = true
197
252
  }
253
+
254
+ /**
255
+ * 当用户开始拖动结束
256
+ */
198
257
  function onScrollEnd (event: NativeSyntheticEvent<NativeScrollEvent>) {
258
+ // 这里安卓好像没有触发onScrollEnd, 调用scrollTo的时候
259
+ if (totalElements === 1) {
260
+ return
261
+ }
199
262
  internalsRef.current.isScrolling = false
200
-
201
263
  // 用户手动滑动更新索引后,如果开启了自动轮播等重新开始
202
- updateIndex(event.nativeEvent.contentOffset)
264
+ updateIndex(event.nativeEvent.contentOffset, true)
203
265
  }
204
266
 
205
267
  /**
@@ -208,59 +270,59 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
208
270
  function onScrollEndDrag (event: NativeSyntheticEvent<NativeScrollEvent>) {
209
271
  const { contentOffset } = event.nativeEvent
210
272
  const { index, total } = state
211
-
273
+ isDragRef.current = true
212
274
  const internalOffset = internalsRef.current.offset
213
275
  const previousOffset = props.horizontal ? internalOffset.x : internalOffset.y
214
- const newOffset = props.horizontal ? contentOffset.x : contentOffset.y
215
-
216
- if (previousOffset === newOffset && (index === 0 || index === total - 1)) {
276
+ const moveOffset = props.horizontal ? contentOffset.x : contentOffset.y
277
+ // const diff = moveOffset - previousOffset
278
+ /*
279
+ if (diff > 0 && state.index + 1 >= total) {
280
+ const { nextOffset } = getNextConfig(contentOffset)
281
+ // scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: false })
282
+ } else if ( diff < 0 && state.index -1 < 0) {
283
+ const { nextOffset } = getNextConfig(contentOffset)
284
+ // scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: false })
285
+ }
286
+ */
287
+ if (previousOffset === moveOffset && (index === 0 || index === total - 1)) {
217
288
  internalsRef.current.isScrolling = false
218
289
  }
219
290
  }
220
- /**
221
- * 垂直方向时,获取单个元素的布局,更新
222
- */
223
- function onItemLayout (event: LayoutChangeEvent) {
224
- if (!initRenderRef.current || state.dir === 'x') return
225
- const { width, height } = event.nativeEvent.layout
226
- if (state.total > 1) {
227
- internalsRef.current.offset[state.dir] = (state.dir === 'y' ? height * state.index : state.width * state.index)
228
- }
229
-
230
- if (!state.offset.x && !state.offset.y) {
231
- state.offset = internalsRef.current.offset
232
- }
233
291
 
234
- if (initRenderRef.current && state.total > 1) {
235
- scrollViewRef.current?.scrollTo({ ...internalsRef.current.offset, animated: false })
236
- initRenderRef.current = false
237
- }
238
- setState((preState) => {
239
- return {
240
- ...preState,
241
- height
242
- }
243
- })
244
- }
245
292
  /**
246
- * 水平方向时,获取单个元素的布局,更新
293
+ * @desc: 水平方向时,获取元素的布局,更新, 其中如果传递100%时需要依赖measure计算元算的宽高
247
294
  */
248
295
  function onWrapperLayout () {
249
296
  if (props.enableOffset) {
250
297
  // @ts-ignore
251
298
  scrollViewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
252
299
  layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
300
+ const isWDiff = state.width !== width
301
+ const isHDiff = state.height !== height
302
+ if (isWDiff || isHDiff) {
303
+ const changeState = {
304
+ width: isWDiff ? width : state.width,
305
+ height: isHDiff ? height : state.height
306
+ }
307
+ let correctOffset = Object.assign({}, state.offset, {
308
+ [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
309
+ })
310
+ state.offset = correctOffset
311
+ state.width = width
312
+ state.height = height
313
+ setState((preState) => {
314
+ return {
315
+ ...preState,
316
+ offset: correctOffset,
317
+ width: changeState.width,
318
+ height: changeState.height
319
+ }
320
+ })
321
+ scrollViewRef.current?.scrollTo({ x: correctOffset['x'], y: correctOffset['y'], animated: false })
322
+ }
253
323
  props.getInnerLayout && props.getInnerLayout(layoutRef)
254
324
  })
255
325
  }
256
- if (state.dir === 'y') return
257
- if (!state.offset.x && !state.offset.y) {
258
- state.offset = internalsRef.current.offset
259
- }
260
- if (!initRenderRef.current && state.total > 1) {
261
- scrollViewRef.current?.scrollTo({ ...state.offset, animated: false })
262
- initRenderRef.current = false
263
- }
264
326
  }
265
327
 
266
328
  function renderScrollView (pages: ReactNode) {
@@ -275,9 +337,11 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
275
337
  removeClippedSubviews: true,
276
338
  automaticallyAdjustContentInsets: false
277
339
  }
340
+ const layoutStyle = dir === 'x' ? { width: defaultWidth, height: defaultHeight } : { width: defaultWidth }
278
341
  return (
279
- <ScrollView
342
+ <Animated.ScrollView
280
343
  {...scrollElementProps}
344
+ style={[layoutStyle]}
281
345
  overScrollMode="always"
282
346
  contentOffset={state.offset}
283
347
  onScrollBeginDrag={onScrollBegin}
@@ -285,7 +349,7 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
285
349
  onScrollEndDrag={onScrollEndDrag}
286
350
  >
287
351
  {pages}
288
- </ScrollView>
352
+ </Animated.ScrollView>
289
353
  )
290
354
  }
291
355
 
@@ -328,10 +392,10 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
328
392
  </View>
329
393
  )
330
394
  }
331
-
395
+
332
396
  function renderPages () {
333
397
  const { width, height, total, children } = state
334
- const { circular, previousMargin, nextMargin, innerProps } = props
398
+ const { circular } = props
335
399
  const pageStyle = { width: width, height: height }
336
400
  if (total > 1 && Array.isArray(children)) {
337
401
  let arrElements: (Array<ReactNode>) = []
@@ -343,23 +407,8 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
343
407
  pages.push('0')
344
408
  }
345
409
  arrElements = pages.map((page, i) => {
346
- let pageStyle2 = { width: width, height: height }
347
- const extraStyle = {} as {
348
- left? : number;
349
- marginLeft?: number;
350
- paddingLeft?: number
351
- }
352
-
353
- if (previousMargin) {
354
- extraStyle.left = +previousMargin
355
- }
356
- if (nextMargin && state.index === i - 1) {
357
- const half = Math.floor(+nextMargin / 2)
358
- extraStyle.marginLeft = - half
359
- extraStyle.paddingLeft = half
360
- }
361
410
  return (
362
- <View style={[pageStyle2, extraStyle]} key={ 'page' + i} onLayout={onItemLayout}>
411
+ <View style={[pageStyle, styles.slide]} key={ 'page' + i}>
363
412
  {children[+page]}
364
413
  </View>
365
414
  )
@@ -374,22 +423,20 @@ const _Carouse = forwardRef<HandlerRef<ScrollView, CarouseProps>, CarouseProps>(
374
423
  }
375
424
  }
376
425
 
377
- const vStyle = {} as { height: number }
378
- if (dir === 'y') {
379
- vStyle.height = defaultHeight
380
- }
381
426
  const pages: Array<ReactNode> | ReactNode = renderPages()
382
427
  const strStyle: string = 'container_' + state.dir
383
428
  const eventProps = props.innerProps || {}
429
+ const layoutStyle = dir === 'x' ? { width: defaultWidth, height: defaultHeight } : { width: defaultWidth }
384
430
 
385
- return (
431
+ return (<View style={[layoutStyle]}>
386
432
  <View
387
- style={[styles[strStyle], vStyle]}
433
+ style={[styles[strStyle], layoutStyle]}
388
434
  {...eventProps}
389
435
  onLayout={onWrapperLayout}>
390
436
  {renderScrollView(pages)}
391
- {props.showsPagination && renderPagination()}
392
- </View>)
437
+ </View>
438
+ <View>{props.showsPagination && renderPagination()}</View>
439
+ </View>)
393
440
 
394
441
  })
395
442
 
@@ -1,5 +1,5 @@
1
- import { View, ScrollView } from 'react-native'
2
- import React, { forwardRef, useRef } from 'react'
1
+ import { ScrollView } from 'react-native'
2
+ import { JSX, MutableRefObject, forwardRef, useRef } from 'react'
3
3
  import { default as Carouse } from './carouse'
4
4
  import { SwiperProps } from './type'
5
5
  import useInnerProps from '../getInnerListeners'
@@ -15,11 +15,12 @@ import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
15
15
  * ✔ circular
16
16
  * ✔ vertical
17
17
  * ✘ display-multiple-items
18
- * previous-margin
19
- * next-margin
18
+ * previous-margin
19
+ * next-margin
20
+ * ✔ easing-function ="easeOutCubic"
20
21
  * ✘ snap-to-edge
21
22
  */
22
- const _SwiperWrapper = forwardRef<HandlerRef<ScrollView, SwiperProps>, SwiperProps>((props: SwiperProps, ref): React.JSX.Element => {
23
+ const _SwiperWrapper = forwardRef<HandlerRef<ScrollView, SwiperProps>, SwiperProps>((props: SwiperProps, ref): JSX.Element => {
23
24
  const { children } = props
24
25
  let innerLayout = useRef({})
25
26
  const swiperProp = {
@@ -32,11 +33,12 @@ const _SwiperWrapper = forwardRef<HandlerRef<ScrollView, SwiperProps>, SwiperPro
32
33
  dotColor: props['indicator-color'] || "rgba(0, 0, 0, .3)",
33
34
  activeDotColor: props['indicator-active-color'] || '#000000',
34
35
  horizontal: props.vertical !== undefined ? !props.vertical : true,
35
- style: props.style,
36
+ styleObj: props.style || {},
36
37
  previousMargin: props['previous-margin'] ? parseInt(props['previous-margin']) : 0,
37
38
  nextMargin: props['next-margin'] ? parseInt(props['next-margin']) : 0,
38
- enableOffset: props['enable-offset'] || false,
39
- bindchange: props.bindchange
39
+ enableOffset: props['enable-offset'] || true,
40
+ bindchange: props.bindchange,
41
+ easingFunction: props['easing-function'] || 'default'
40
42
  }
41
43
  const { nodeRef } = useNodesRef<ScrollView, SwiperProps>(props, ref, {
42
44
  })
@@ -49,16 +51,13 @@ const _SwiperWrapper = forwardRef<HandlerRef<ScrollView, SwiperProps>, SwiperPro
49
51
  'previous-margin',
50
52
  'next-margin'
51
53
  ], { layoutRef: innerLayout })
52
-
53
- const getInnerLayout = (layout: React.MutableRefObject<{}>) => {
54
+ const getInnerLayout = (layout: MutableRefObject<{}>) => {
54
55
  innerLayout.current = layout.current
55
56
  }
56
-
57
57
  return <Carouse
58
58
  getInnerLayout={getInnerLayout}
59
59
  innerProps={innerProps}
60
- {...swiperProp}
61
- {...innerProps}>
60
+ {...swiperProp}>
62
61
  {children}
63
62
  </Carouse>
64
63
 
@@ -1,5 +1,8 @@
1
1
  import { ReactNode } from 'react'
2
2
  import { NativeSyntheticEvent } from 'react-native'
3
+
4
+ export type EaseType = 'default' | 'linear' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic'
5
+
3
6
  export interface SwiperProps {
4
7
  children?: ReactNode;
5
8
  circular?: boolean;
@@ -11,8 +14,8 @@ export interface SwiperProps {
11
14
  'indicator-color'?: string;
12
15
  'indicator-active-color'?: string;
13
16
  vertical?: boolean;
14
- style?: string;
15
- easingFunction?: string;
17
+ style?: Object;
18
+ 'easing-function'?: EaseType;
16
19
  'previous-margin'?: string;
17
20
  'next-margin'?: string;
18
21
  'enable-offset'?: boolean;
@@ -30,14 +33,17 @@ export interface CarouseProps {
30
33
  dotColor?: string;
31
34
  activeDotColor?: string;
32
35
  horizontal?: boolean;
33
- style?: string;
34
- easingFunction?: string;
36
+ easingFunction?: EaseType;
35
37
  previousMargin?: number;
36
38
  nextMargin?: number;
37
39
  enableOffset?: boolean;
38
40
  bindchange?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void;
39
41
  getInnerLayout: Function,
40
42
  innerProps: Object;
43
+ styleObj: {
44
+ height?: number;
45
+ width?: number
46
+ };
41
47
  }
42
48
 
43
49
  export interface CarouseState {
@@ -55,6 +61,7 @@ export interface CarouseState {
55
61
  autoplayEnd: boolean;
56
62
  loopJump: boolean;
57
63
  dir: 'x' | 'y';
64
+ isScrollEnd: boolean
58
65
  }
59
66
 
60
67
  export interface ScrollElementProps {
@@ -1,16 +1,17 @@
1
1
  import { View } from 'react-native'
2
- import React, { forwardRef, useRef } from 'react'
2
+ import { ReactNode, forwardRef, useRef } from 'react'
3
3
  import useInnerProps from './getInnerListeners'
4
4
  import useNodesRef, { HandlerRef } from './useNodesRef' // 引入辅助函数
5
5
 
6
6
  interface SwiperItemProps {
7
7
  'item-id'?: string;
8
8
  'enable-offset'?: boolean;
9
- children?: React.ReactNode;
9
+ children?: ReactNode;
10
+ style?: Object;
10
11
  }
11
12
 
12
13
  const _SwiperItem = forwardRef<HandlerRef<View, SwiperItemProps>, SwiperItemProps>((props: SwiperItemProps, ref) => {
13
- const { children, 'enable-offset': enableOffset } = props
14
+ const { children, 'enable-offset': enableOffset, style } = props
14
15
  const layoutRef = useRef({})
15
16
  const { nodeRef } = useNodesRef(props, ref, {})
16
17
 
@@ -31,6 +32,7 @@ const _SwiperItem = forwardRef<HandlerRef<View, SwiperItemProps>, SwiperItemProp
31
32
  <View
32
33
  ref={nodeRef}
33
34
  data-itemId={props['item-id']}
35
+ style={[style]}
34
36
  {...innerProps}>
35
37
  {children}
36
38
  </View>