@mpxjs/webpack-plugin 2.9.69-beta.0 → 2.9.69-beta.2

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 (50) hide show
  1. package/lib/index.js +17 -1
  2. package/lib/platform/style/wx/index.js +18 -18
  3. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  4. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  5. package/lib/resolver/AddEnvPlugin.js +1 -0
  6. package/lib/resolver/AddModePlugin.js +1 -0
  7. package/lib/runtime/components/react/context.ts +8 -0
  8. package/lib/runtime/components/react/dist/context.js +2 -0
  9. package/lib/runtime/components/react/dist/getInnerListeners.js +3 -4
  10. package/lib/runtime/components/react/dist/mpx-input.jsx +1 -1
  11. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +1 -1
  12. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +1 -1
  13. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +54 -52
  14. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +1 -1
  15. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
  16. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +21 -6
  17. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +25 -8
  18. package/lib/runtime/components/react/dist/mpx-swiper.jsx +150 -148
  19. package/lib/runtime/components/react/dist/mpx-view.jsx +9 -40
  20. package/lib/runtime/components/react/dist/mpx-web-view.jsx +50 -12
  21. package/lib/runtime/components/react/dist/pickerFaces.js +1 -1
  22. package/lib/runtime/components/react/dist/useAnimationHooks.js +1 -1
  23. package/lib/runtime/components/react/dist/utils.jsx +63 -4
  24. package/lib/runtime/components/react/getInnerListeners.ts +3 -5
  25. package/lib/runtime/components/react/mpx-input.tsx +1 -1
  26. package/lib/runtime/components/react/mpx-movable-view.tsx +1 -1
  27. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +88 -0
  28. package/lib/runtime/components/react/mpx-picker-view-column.tsx +177 -159
  29. package/lib/runtime/components/react/mpx-picker-view.tsx +35 -37
  30. package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
  31. package/lib/runtime/components/react/mpx-scroll-view.tsx +30 -13
  32. package/lib/runtime/components/react/mpx-swiper-item.tsx +38 -10
  33. package/lib/runtime/components/react/mpx-swiper.tsx +690 -0
  34. package/lib/runtime/components/react/mpx-view.tsx +11 -51
  35. package/lib/runtime/components/react/mpx-web-view.tsx +57 -13
  36. package/lib/runtime/components/react/pickerFaces.ts +15 -7
  37. package/lib/runtime/components/react/pickerVIewContext.ts +18 -0
  38. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  39. package/lib/runtime/components/react/{pickerOverlay.tsx → pickerViewOverlay.tsx} +5 -3
  40. package/lib/runtime/components/react/types/global.d.ts +3 -1
  41. package/lib/runtime/components/react/useAnimationHooks.ts +1 -1
  42. package/lib/runtime/components/react/utils.tsx +75 -5
  43. package/lib/style-compiler/index.js +3 -4
  44. package/lib/style-compiler/strip-conditional-loader.js +118 -0
  45. package/lib/template-compiler/compiler.js +9 -14
  46. package/lib/utils/pre-process-json.js +5 -9
  47. package/package.json +1 -1
  48. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  49. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  50. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
@@ -1,17 +1,18 @@
1
-
2
- import { View, Animated, SafeAreaView, NativeScrollEvent, NativeSyntheticEvent, LayoutChangeEvent, ScrollView } from 'react-native'
3
- import React, { forwardRef, useRef, useState, useMemo, useCallback, useEffect } from 'react'
4
- import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout, usePrevious } from './utils'
1
+ import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react'
2
+ import { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, SafeAreaView, ScrollView, StyleSheet, View } from 'react-native'
3
+ import Reanimated, { AnimatedRef, useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated'
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, useDebounceCallback, useStableCallback, isIOS } from './utils'
5
5
  import useNodesRef, { HandlerRef } from './useNodesRef'
6
- import { createFaces } from './pickerFaces'
7
- import PickerOverlay from './pickerOverlay'
6
+ import PickerOverlay from './pickerViewOverlay'
7
+ import PickerMask from './pickerViewMask'
8
+ import MpxPickerVIewColumnItem from './mpx-picker-view-column-item'
9
+ import { PickerViewColumnAnimationContext } from './pickerVIewContext'
8
10
 
9
11
  interface ColumnProps {
10
12
  children?: React.ReactNode
11
13
  columnData: React.ReactNode[]
14
+ columnStyle: Record<string, any>
12
15
  initialIndex: number
13
- onColumnItemRawHChange: Function
14
- getInnerLayout: Function
15
16
  onSelectChange: Function
16
17
  style: {
17
18
  [key: string]: any
@@ -22,25 +23,23 @@ interface ColumnProps {
22
23
  height: number
23
24
  itemHeight: number
24
25
  }
26
+ pickerMaskStyle: Record<string, any>
25
27
  pickerOverlayStyle: Record<string, any>
26
28
  columnIndex: number
27
29
  }
28
30
 
29
- // 默认的单个选项高度
30
- const DefaultPickerItemH = 36
31
- // 默认一屏可见选项个数
32
31
  const visibleCount = 5
33
32
 
34
33
  const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>, ColumnProps>((props: ColumnProps, ref) => {
35
34
  const {
36
35
  columnData,
37
36
  columnIndex,
37
+ columnStyle,
38
38
  initialIndex,
39
39
  onSelectChange,
40
- onColumnItemRawHChange,
41
- getInnerLayout,
42
40
  style,
43
41
  wrapperStyle,
42
+ pickerMaskStyle,
44
43
  pickerOverlayStyle,
45
44
  'enable-var': enableVar,
46
45
  'external-var-context': externalVarContext
@@ -54,27 +53,42 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
54
53
  setWidth,
55
54
  setHeight
56
55
  } = useTransformStyle(style, { enableVar, externalVarContext })
57
- const { textStyle } = splitStyle(normalStyle)
56
+ const { textStyle: textStyleFromParent = {} } = splitStyle(columnStyle)
57
+ const { textStyle = {} } = splitStyle(normalStyle)
58
58
  const { textProps } = splitProps(props)
59
- const scrollViewRef = useRef<ScrollView>(null)
59
+ const scrollViewRef = useAnimatedRef<Reanimated.ScrollView>()
60
+ const offsetYShared = useScrollViewOffset(scrollViewRef as AnimatedRef<Reanimated.ScrollView>)
60
61
 
61
- useNodesRef(props, ref, scrollViewRef, {
62
+ useNodesRef(props, ref, scrollViewRef as AnimatedRef<ScrollView>, {
62
63
  style: normalStyle
63
64
  })
64
65
 
65
- const { height: pickerH, itemHeight = DefaultPickerItemH } = wrapperStyle
66
- const [itemRawH, setItemRawH] = useState(0) // 单个选项真实渲染高度
66
+ const { height: pickerH, itemHeight } = wrapperStyle
67
+ const [itemRawH, setItemRawH] = useState(itemHeight)
67
68
  const maxIndex = useMemo(() => columnData.length - 1, [columnData])
69
+ const prevScrollingInfo = useRef({ index: initialIndex, y: 0 })
68
70
  const touching = useRef(false)
69
71
  const scrolling = useRef(false)
70
72
  const activeIndex = useRef(initialIndex)
71
73
  const prevIndex = usePrevious(initialIndex)
72
74
  const prevMaxIndex = usePrevious(maxIndex)
73
75
 
74
- const initialOffset = useMemo(() => ({
75
- x: 0,
76
- y: itemRawH * initialIndex
77
- }), [itemRawH])
76
+ const {
77
+ layoutProps
78
+ } = useLayout({
79
+ props,
80
+ hasSelfPercent,
81
+ setWidth,
82
+ setHeight,
83
+ nodeRef: scrollViewRef
84
+ })
85
+
86
+ // console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length, 'pickerH=', pickerH, 'itemRawH=', itemRawH, 'itemHeight=', itemHeight)
87
+
88
+ const paddingHeight = useMemo(
89
+ () => Math.round((pickerH - itemHeight) / 2),
90
+ [pickerH, itemHeight]
91
+ )
78
92
 
79
93
  const snapToOffsets = useMemo(
80
94
  () => columnData.map((_, i) => i * itemRawH),
@@ -82,12 +96,34 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
82
96
  )
83
97
 
84
98
  const contentContainerStyle = useMemo(() => {
85
- return [
86
- {
87
- paddingVertical: Math.round(pickerH - itemRawH) / 2
88
- }
89
- ]
90
- }, [pickerH, itemRawH])
99
+ return [{ paddingVertical: paddingHeight }]
100
+ }, [paddingHeight])
101
+
102
+ const getIndex = useCallback((y: number) => {
103
+ const calc = Math.round(y / itemRawH)
104
+ return Math.max(0, Math.min(calc, maxIndex))
105
+ }, [itemRawH, maxIndex])
106
+
107
+ const getYofIndex = useCallback((index: number) => {
108
+ return index * itemRawH
109
+ }, [itemRawH])
110
+
111
+ const stableResetScrollPosition = useStableCallback((y: number) => {
112
+ console.log('[mpx-picker-view-column], reset --->', 'columnIndex=', columnIndex, 'y=', y, touching.current, scrolling.current)
113
+ if (touching.current || scrolling.current) {
114
+ return
115
+ }
116
+ // needReset.current = true
117
+ if (y % itemRawH !== 0) {
118
+ scrolling.current = true
119
+ const targetIndex = getIndex(y)
120
+ const targetY = getYofIndex(targetIndex)
121
+ scrollViewRef.current?.scrollTo({ x: 0, y: targetY, animated: false })
122
+ } else {
123
+ onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } })
124
+ }
125
+ })
126
+ const debounceResetScrollPosition = useDebounceCallback(stableResetScrollPosition, 10)
91
127
 
92
128
  useEffect(() => {
93
129
  if (
@@ -102,188 +138,170 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
102
138
  ) {
103
139
  return
104
140
  }
105
-
141
+ setTimeout(() => {
142
+ scrollViewRef.current?.scrollTo({
143
+ x: 0,
144
+ y: getYofIndex(initialIndex),
145
+ animated: false
146
+ })
147
+ }, isAndroid ? 200 : 0)
106
148
  activeIndex.current = initialIndex
107
- scrollViewRef.current.scrollTo({
108
- x: 0,
109
- y: itemRawH * initialIndex,
110
- animated: false
111
- })
112
149
  }, [itemRawH, initialIndex])
113
150
 
114
- const onScrollViewLayout = () => {
115
- getInnerLayout && getInnerLayout(layoutRef)
116
- }
117
-
118
- const {
119
- layoutRef,
120
- layoutProps
121
- } = useLayout({
122
- props,
123
- hasSelfPercent,
124
- setWidth,
125
- setHeight,
126
- nodeRef: scrollViewRef,
127
- onLayout: onScrollViewLayout
128
- })
129
-
130
- const onContentSizeChange = (w: number, h: number) => {
131
- scrollViewRef.current?.scrollTo({
132
- x: 0,
133
- y: itemRawH * initialIndex,
134
- animated: false
135
- })
151
+ const onContentSizeChange = (_w: number, h: number) => {
152
+ const y = getYofIndex(initialIndex)
153
+ if (y <= h) {
154
+ setTimeout(() => {
155
+ scrollViewRef.current?.scrollTo({ x: 0, y, animated: false })
156
+ }, 0)
157
+ }
136
158
  }
137
159
 
138
160
  const onItemLayout = (e: LayoutChangeEvent) => {
139
161
  const { height: rawH } = e.nativeEvent.layout
140
162
  if (rawH && itemRawH !== rawH) {
141
163
  setItemRawH(rawH)
142
- onColumnItemRawHChange(rawH)
143
164
  }
144
165
  }
145
166
 
146
- const onTouchStart = () => {
167
+ const onScrollBeginDrag = () => {
168
+ isIOS && debounceResetScrollPosition.clear()
147
169
  touching.current = true
170
+ prevScrollingInfo.current = {
171
+ index: activeIndex.current,
172
+ y: getYofIndex(activeIndex.current)
173
+ }
148
174
  }
149
175
 
150
- const onTouchEnd = () => {
151
- touching.current = false
152
- }
153
-
154
- const onTouchCancel = () => {
176
+ const onScrollEndDrag = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
155
177
  touching.current = false
178
+ const { y } = e.nativeEvent.contentOffset
179
+ if (isIOS) {
180
+ if (y > 0 && y < snapToOffsets[maxIndex]) {
181
+ debounceResetScrollPosition(y)
182
+ }
183
+ }
156
184
  }
157
185
 
158
186
  const onMomentumScrollBegin = () => {
187
+ isIOS && debounceResetScrollPosition.clear()
159
188
  scrolling.current = true
160
189
  }
161
190
 
162
- const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
191
+ const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent> | { nativeEvent: { contentOffset: { y: number } } }) => {
163
192
  scrolling.current = false
164
- if (!itemRawH) {
165
- return
166
- }
167
193
  const { y: scrollY } = e.nativeEvent.contentOffset
168
- let calcIndex = Math.round(scrollY / itemRawH)
194
+ if (isIOS && scrollY % itemRawH !== 0) {
195
+ return debounceResetScrollPosition(scrollY)
196
+ }
197
+ const calcIndex = getIndex(scrollY)
169
198
  activeIndex.current = calcIndex
170
199
  if (calcIndex !== initialIndex) {
171
- calcIndex = Math.max(0, Math.min(calcIndex, maxIndex)) || 0
172
200
  onSelectChange(calcIndex)
173
201
  }
174
202
  }
175
203
 
176
- const offsetY = useRef(new Animated.Value(0)).current
177
-
178
- const onScroll = useMemo(
179
- () =>
180
- Animated.event([{ nativeEvent: { contentOffset: { y: offsetY } } }], {
181
- useNativeDriver: true
182
- }),
183
- [offsetY]
184
- )
185
-
186
- const faces = useMemo(() => createFaces(itemRawH, visibleCount), [itemRawH])
187
-
188
- const getTransform = useCallback(
189
- (index: number) => {
190
- const inputRange = faces.map((f) => itemRawH * (index + f.index))
191
- return {
192
- opacity: offsetY.interpolate({
193
- inputRange: inputRange,
194
- outputRange: faces.map((x) => x.opacity),
195
- extrapolate: 'clamp'
196
- }),
197
- rotateX: offsetY.interpolate({
198
- inputRange: inputRange,
199
- outputRange: faces.map((x) => `${x.deg}deg`),
200
- extrapolate: 'extend'
201
- }),
202
- translateY: offsetY.interpolate({
203
- inputRange: inputRange,
204
- outputRange: faces.map((x) => x.offsetY),
205
- extrapolate: 'extend'
206
- })
204
+ const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
205
+ const { y } = e.nativeEvent.contentOffset
206
+ if (isAndroid) {
207
+ return
208
+ }
209
+ // 全局注册的震动触感 hook
210
+ const pickerVibrate = global.__mpx.config.rnConfig.pickerVibrate
211
+ if (typeof pickerVibrate !== 'function') {
212
+ return
213
+ }
214
+ const { index: prevIndex, y: _y } = prevScrollingInfo.current
215
+ if (touching.current || scrolling.current) {
216
+ if (Math.abs(y - _y) >= itemRawH) {
217
+ const currentId = getIndex(y)
218
+ if (currentId !== prevIndex) {
219
+ prevScrollingInfo.current = {
220
+ index: currentId,
221
+ y: getYofIndex(currentId)
222
+ }
223
+ // vibrateShort({ type: 'selection' })
224
+ pickerVibrate()
225
+ }
207
226
  }
208
- },
209
- [offsetY, faces, itemRawH]
210
- )
227
+ }
228
+ }
211
229
 
212
230
  const renderInnerchild = () =>
213
- columnData.map((item: React.ReactNode, index: number) => {
214
- const InnerProps = index === 0 ? { onLayout: onItemLayout } : {}
215
- const strKey = `picker-column-${columnIndex}-${index}`
216
- const { opacity, rotateX, translateY } = getTransform(index)
231
+ columnData.map((item: React.ReactElement, index: number) => {
217
232
  return (
218
- <Animated.View
219
- key={strKey}
220
- {...InnerProps}
221
- style={[
222
- {
223
- height: itemHeight || DefaultPickerItemH,
224
- width: '100%',
225
- opacity,
226
- transform: [
227
- { translateY },
228
- { rotateX },
229
- { perspective: 1000 } // 适配 Android
230
- ]
231
- }
232
- ]}
233
- >
234
- {wrapChildren(
235
- { children: item },
236
- {
237
- hasVarDec,
238
- varContext: varContextRef.current,
239
- textStyle,
240
- textProps
241
- }
242
- )}
243
- </Animated.View>
233
+ <MpxPickerVIewColumnItem
234
+ key={index}
235
+ item={item}
236
+ index={index}
237
+ itemHeight={itemHeight}
238
+ textStyleFromParent={textStyleFromParent}
239
+ textStyle={textStyle}
240
+ hasVarDec={hasVarDec}
241
+ varContext={varContextRef.current}
242
+ textProps={textProps}
243
+ visibleCount={visibleCount}
244
+ onItemLayout={onItemLayout}
245
+ />
244
246
  )
245
247
  })
246
248
 
247
249
  const renderScollView = () => {
248
250
  return (
249
- <Animated.ScrollView
250
- ref={scrollViewRef}
251
- bounces={true}
252
- horizontal={false}
253
- pagingEnabled={false}
254
- nestedScrollEnabled={true}
255
- removeClippedSubviews={true}
256
- showsVerticalScrollIndicator={false}
257
- showsHorizontalScrollIndicator={false}
258
- {...layoutProps}
259
- scrollEventThrottle={16}
260
- contentContainerStyle={contentContainerStyle}
261
- contentOffset={initialOffset}
262
- snapToOffsets={snapToOffsets}
263
- onContentSizeChange={onContentSizeChange}
264
- onScroll={onScroll}
265
- onTouchStart={onTouchStart}
266
- onTouchEnd={onTouchEnd}
267
- onTouchCancel={onTouchCancel}
268
- onMomentumScrollBegin={onMomentumScrollBegin}
269
- onMomentumScrollEnd={onMomentumScrollEnd}
270
- >
271
- {renderInnerchild()}
272
- </Animated.ScrollView>
251
+ <PickerViewColumnAnimationContext.Provider value={offsetYShared}>
252
+ <Reanimated.ScrollView
253
+ ref={scrollViewRef}
254
+ bounces={true}
255
+ horizontal={false}
256
+ nestedScrollEnabled={true}
257
+ removeClippedSubviews={false}
258
+ showsVerticalScrollIndicator={false}
259
+ showsHorizontalScrollIndicator={false}
260
+ scrollEventThrottle={16}
261
+ {...layoutProps}
262
+ style={[{ width: '100%' }]}
263
+ decelerationRate="fast"
264
+ snapToOffsets={snapToOffsets}
265
+ onScroll={onScroll}
266
+ onScrollBeginDrag={onScrollBeginDrag}
267
+ onScrollEndDrag={onScrollEndDrag}
268
+ onMomentumScrollBegin={onMomentumScrollBegin}
269
+ onMomentumScrollEnd={onMomentumScrollEnd}
270
+ onContentSizeChange={onContentSizeChange}
271
+ contentContainerStyle={contentContainerStyle}
272
+ >
273
+ {renderInnerchild()}
274
+ </Reanimated.ScrollView>
275
+ </PickerViewColumnAnimationContext.Provider>
273
276
  )
274
277
  }
275
278
 
276
279
  const renderOverlay = () => (
277
- <PickerOverlay itemHeight={itemHeight} overlayItemStyle={pickerOverlayStyle} />
280
+ <PickerOverlay
281
+ itemHeight={itemHeight}
282
+ overlayItemStyle={pickerOverlayStyle}
283
+ />
284
+ )
285
+
286
+ const renderMask = () => (
287
+ <PickerMask
288
+ itemHeight={itemHeight}
289
+ maskContainerStyle={pickerMaskStyle}
290
+ />
278
291
  )
279
292
 
280
293
  return (
281
- <SafeAreaView style={[{ display: 'flex', flex: 1 }]}>
294
+ <SafeAreaView style={[styles.wrapper, normalStyle]}>
282
295
  {renderScollView()}
296
+ {renderMask()}
283
297
  {renderOverlay()}
284
298
  </SafeAreaView>
285
299
  )
286
300
  })
287
301
 
302
+ const styles = StyleSheet.create({
303
+ wrapper: { display: 'flex', flex: 1 }
304
+ })
305
+
288
306
  _PickerViewColumn.displayName = 'MpxPickerViewColumn'
289
307
  export default _PickerViewColumn
@@ -1,5 +1,5 @@
1
1
  import { View } from 'react-native'
2
- import React, { forwardRef, useState, useRef } from 'react'
2
+ import React, { forwardRef, useRef } from 'react'
3
3
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
4
4
  import useNodesRef, { HandlerRef } from './useNodesRef'
5
5
  import {
@@ -9,8 +9,6 @@ import {
9
9
  wrapChildren,
10
10
  parseInlineStyle,
11
11
  useTransformStyle,
12
- useDebounceCallback,
13
- useStableCallback,
14
12
  extendObject
15
13
  } from './utils'
16
14
  import type { AnyFunc } from './types/common'
@@ -21,21 +19,21 @@ import type { AnyFunc } from './types/common'
21
19
  * ✘ bindpickend
22
20
  * ✘ mask-class
23
21
  * ✔ indicator-style: 优先级indicator-style.height > pick-view-column中的子元素设置的height
22
+ * WebView Only:
24
23
  * ✘ indicator-class
25
- * mask-style
24
+ * mask-style
26
25
  * ✘ immediate-change
27
26
  */
28
27
 
29
28
  interface PickerViewProps {
30
29
  children: React.ReactNode
31
- // 初始的defaultValue数组中的数字依次表示 picker-view 内的 picker-view-column 选择的第几项(下标从 0 开始),
32
- // 数字大于 picker-view-column 可选项长度时,选择最后一项。
33
30
  value?: Array<number>
34
31
  bindchange?: AnyFunc
35
32
  style: {
36
33
  [key: string]: any
37
34
  }
38
35
  'indicator-style'?: string
36
+ 'mask-style'?: string
39
37
  'enable-var': boolean
40
38
  'external-var-context'?: Record<string, any>,
41
39
  'enable-offset': boolean
@@ -62,6 +60,8 @@ const styles: { [key: string]: Object } = {
62
60
  }
63
61
  }
64
62
 
63
+ const DefaultPickerItemH = 36
64
+
65
65
  const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProps>((props: PickerViewProps, ref) => {
66
66
  const {
67
67
  children,
@@ -71,16 +71,16 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
71
71
  'enable-var': enableVar,
72
72
  'external-var-context': externalVarContext
73
73
  } = props
74
-
75
- // indicatorStyle 需要转换为rn的style
76
- // 微信设置到pick-view上上设置的normalStyle如border等需要转换成RN的style然后进行透传
77
74
  const indicatorStyle = parseInlineStyle(props['indicator-style'])
75
+ const pickerMaskStyle = parseInlineStyle(props['mask-style'])
78
76
  const { height: indicatorH, ...pickerOverlayStyle } = indicatorStyle
79
- const [pickMaxH, setPickMaxH] = useState(0)
80
77
  const nodeRef = useRef(null)
81
78
  const cloneRef = useRef(null)
82
79
  const activeValueRef = useRef(value)
83
80
  activeValueRef.current = value.slice()
81
+ const snapActiveValueRef = useRef<number[] | null>(null)
82
+
83
+ console.log('[mpx-picker-view] value=', value, Date.now())
84
84
 
85
85
  const {
86
86
  normalStyle,
@@ -96,7 +96,6 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
96
96
  })
97
97
 
98
98
  const {
99
- // 存储layout布局信息
100
99
  layoutRef,
101
100
  layoutProps,
102
101
  layoutStyle
@@ -104,33 +103,34 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
104
103
  const { textProps } = splitProps(props)
105
104
  const { textStyle } = splitStyle(normalStyle)
106
105
 
107
- const onColumnItemRawHChange = (height: number) => {
108
- if (height > pickMaxH) {
109
- setPickMaxH(height)
110
- }
111
- }
112
-
113
- const bindchangeDebounce = useDebounceCallback(useStableCallback(bindchange), 300)
114
-
115
106
  const onSelectChange = (columnIndex: number, selectedIndex: number) => {
116
- bindchangeDebounce.clear()
117
107
  const activeValue = activeValueRef.current
118
108
  activeValue[columnIndex] = selectedIndex
109
+ console.log('[mpx-picker-view], onSelectChange ---> columnIndex=', columnIndex, 'selectedIndex=', selectedIndex, 'activeValue=', activeValue)
119
110
  const eventData = getCustomEvent(
120
111
  'change',
121
112
  {},
122
113
  { detail: { value: activeValue, source: 'change' }, layoutRef }
123
114
  )
124
- bindchangeDebounce(eventData)
115
+ bindchange?.(eventData)
116
+ snapActiveValueRef.current = activeValueRef.current
125
117
  }
126
118
 
127
- const onInitialChange = (value: number[]) => {
128
- const eventData = getCustomEvent(
129
- 'change',
130
- {},
131
- { detail: { value, source: 'change' }, layoutRef }
132
- )
133
- bindchange?.(eventData) // immediate
119
+ const hasDiff = (a: number[] = [], b: number[]) => {
120
+ return a.some((v, i) => v !== b[i])
121
+ }
122
+
123
+ const onInitialChange = (isInvalid: boolean, value: number[]) => {
124
+ if (isInvalid || !snapActiveValueRef.current || hasDiff(snapActiveValueRef.current, value)) {
125
+ console.log('[mpx-picker-view], onInitialChange ===> value=', value)
126
+ const eventData = getCustomEvent(
127
+ 'change',
128
+ {},
129
+ { detail: { value, source: 'change' }, layoutRef }
130
+ )
131
+ bindchange?.(eventData)
132
+ snapActiveValueRef.current = value.slice()
133
+ }
134
134
  }
135
135
 
136
136
  const innerProps = useInnerProps(
@@ -153,7 +153,6 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
153
153
  )
154
154
 
155
155
  const renderColumn = (child: React.ReactElement, index: number, columnData: React.ReactNode[], initialIndex: number) => {
156
- const extraProps = {}
157
156
  const childProps = child?.props || {}
158
157
  const wrappedProps = extendObject(
159
158
  {},
@@ -164,15 +163,15 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
164
163
  columnIndex: index,
165
164
  key: `pick-view-${index}`,
166
165
  wrapperStyle: {
167
- height: normalStyle?.height || 0,
168
- itemHeight: indicatorH || 0
166
+ height: normalStyle?.height || DefaultPickerItemH,
167
+ itemHeight: indicatorH || DefaultPickerItemH
169
168
  },
170
- onColumnItemRawHChange,
169
+ columnStyle: normalStyle,
171
170
  onSelectChange: onSelectChange.bind(null, index),
172
171
  initialIndex,
173
- pickerOverlayStyle
174
- },
175
- extraProps
172
+ pickerOverlayStyle,
173
+ pickerMaskStyle
174
+ }
176
175
  )
177
176
  const realElement = React.cloneElement(child, wrappedProps)
178
177
  return wrapChildren(
@@ -215,7 +214,7 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
215
214
  validValue.push(validIndex)
216
215
  renderColumns.push(renderColumn(item, index, columnData, validIndex))
217
216
  })
218
- isInvalid && onInitialChange(validValue)
217
+ onInitialChange(isInvalid, validValue)
219
218
  return renderColumns
220
219
  }
221
220
 
@@ -227,5 +226,4 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
227
226
  })
228
227
 
229
228
  _PickerView.displayName = 'MpxPickerView'
230
-
231
229
  export default _PickerView
@@ -3,10 +3,10 @@
3
3
  * ✔ nodes
4
4
  */
5
5
  import { View, ViewProps, ViewStyle } from 'react-native'
6
- import { useRef, forwardRef, JSX, useState } from 'react'
6
+ import { useRef, forwardRef, JSX, useState, createElement } from 'react'
7
7
  import useInnerProps from '../getInnerListeners'
8
8
  import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
9
- import { useTransformStyle, useLayout } from '../utils'
9
+ import { useTransformStyle, useLayout, extendObject } from '../utils'
10
10
  import { WebView, WebViewMessageEvent } from 'react-native-webview'
11
11
  import { generateHTML } from './html'
12
12
 
@@ -91,28 +91,22 @@ const _RichText = forwardRef<HandlerRef<View, _RichTextProps>, _RichTextProps>((
91
91
  layoutRef
92
92
  })
93
93
 
94
- const innerProps = useInnerProps(props, {
94
+ const innerProps = useInnerProps(props, extendObject({
95
95
  ref: nodeRef,
96
- style: { ...normalStyle, ...layoutStyle },
97
- ...layoutProps
98
- }, [], {
96
+ style: extendObject(normalStyle, layoutStyle)
97
+ }, layoutProps), [], {
99
98
  layoutRef
100
99
  })
101
100
 
102
101
  const html: string = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes)
103
102
 
104
- return (
105
- <View
106
- {...innerProps}
107
- >
108
- <WebView
109
- source={{ html: generateHTML(html) }}
110
- onMessage={(event: WebViewMessageEvent) => {
111
- setWebViewHeight(+event.nativeEvent.data)
112
- }}
113
- >
114
- </WebView>
115
- </View>
103
+ return createElement(View, innerProps,
104
+ createElement(WebView, {
105
+ source: { html: generateHTML(html) },
106
+ onMessage: (event: WebViewMessageEvent) => {
107
+ setWebViewHeight(+event.nativeEvent.data)
108
+ }
109
+ })
116
110
  )
117
111
  })
118
112