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

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 (51) hide show
  1. package/lib/config.js +3 -1
  2. package/lib/platform/template/wx/index.js +3 -1
  3. package/lib/react/processScript.js +6 -4
  4. package/lib/runtime/components/react/context.ts +17 -0
  5. package/lib/runtime/components/react/dist/context.js +2 -0
  6. package/lib/runtime/components/react/dist/getInnerListeners.js +2 -2
  7. package/lib/runtime/components/react/dist/locale-provider.jsx +15 -0
  8. package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
  9. package/lib/runtime/components/react/dist/mpx-image.jsx +13 -9
  10. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +2 -1
  11. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +2 -2
  12. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +65 -61
  13. package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +23 -0
  14. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +93 -0
  15. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +40 -0
  16. package/lib/runtime/components/react/dist/mpx-portal.jsx +13 -0
  17. package/lib/runtime/components/react/dist/mpx-provider.jsx +31 -0
  18. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  19. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +9 -5
  20. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +13 -7
  21. package/lib/runtime/components/react/dist/mpx-swiper.jsx +384 -321
  22. package/lib/runtime/components/react/dist/mpx-view.jsx +16 -20
  23. package/lib/runtime/components/react/dist/mpx-web-view.jsx +129 -53
  24. package/lib/runtime/components/react/dist/pickerFaces.js +2 -7
  25. package/lib/runtime/components/react/dist/useAnimationHooks.js +30 -13
  26. package/lib/runtime/components/react/dist/utils.jsx +60 -2
  27. package/lib/runtime/components/react/getInnerListeners.ts +2 -2
  28. package/lib/runtime/components/react/locale-provider.tsx +83 -0
  29. package/lib/runtime/components/react/mpx-button.tsx +20 -57
  30. package/lib/runtime/components/react/mpx-image.tsx +41 -25
  31. package/lib/runtime/components/react/mpx-picker/time.tsx +2 -1
  32. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +3 -3
  33. package/lib/runtime/components/react/mpx-picker-view-column.tsx +70 -69
  34. package/lib/runtime/components/react/mpx-portal/portal-consumer.tsx +32 -0
  35. package/lib/runtime/components/react/mpx-portal/portal-host.tsx +127 -0
  36. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +64 -0
  37. package/lib/runtime/components/react/mpx-portal.tsx +30 -0
  38. package/lib/runtime/components/react/mpx-provider.tsx +51 -0
  39. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  40. package/lib/runtime/components/react/mpx-scroll-view.tsx +10 -8
  41. package/lib/runtime/components/react/mpx-swiper-item.tsx +13 -7
  42. package/lib/runtime/components/react/mpx-swiper.tsx +378 -325
  43. package/lib/runtime/components/react/mpx-view.tsx +19 -22
  44. package/lib/runtime/components/react/mpx-web-view.tsx +170 -62
  45. package/lib/runtime/components/react/pickerFaces.ts +2 -7
  46. package/lib/runtime/components/react/types/global.d.ts +7 -0
  47. package/lib/runtime/components/react/useAnimationHooks.ts +34 -14
  48. package/lib/runtime/components/react/utils.tsx +67 -2
  49. package/lib/template-compiler/compiler.js +1 -1
  50. package/lib/wxss/loader.js +15 -2
  51. package/package.json +1 -1
@@ -34,7 +34,7 @@
34
34
  * ✘ bindagreeprivacyauthorization
35
35
  * ✔ bindtap
36
36
  */
37
- import { createElement, useEffect, useRef, useState, ReactNode, forwardRef, useContext, JSX } from 'react'
37
+ import { createElement, useEffect, useRef, ReactNode, forwardRef, useContext, JSX } from 'react'
38
38
  import {
39
39
  View,
40
40
  StyleSheet,
@@ -45,10 +45,12 @@ import {
45
45
  NativeSyntheticEvent
46
46
  } from 'react-native'
47
47
  import { warn } from '@mpxjs/utils'
48
- import { getCurrentPage, splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils'
48
+ import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
49
+ import { getCurrentPage, splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject, useHover } from './utils'
49
50
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
50
51
  import useNodesRef, { HandlerRef } from './useNodesRef'
51
52
  import { RouteContext, FormContext } from './context'
53
+ import type { ExtendedViewStyle } from './types/common'
52
54
 
53
55
  export type Type = 'default' | 'primary' | 'warn'
54
56
 
@@ -68,7 +70,7 @@ export interface ButtonProps {
68
70
  disabled?: boolean
69
71
  loading?: boolean
70
72
  'hover-class'?: string
71
- 'hover-style'?: ViewStyle & TextStyle & Record<string, any>
73
+ 'hover-style'?: ExtendedViewStyle
72
74
  'hover-start-time'?: number
73
75
  'hover-stay-time'?: number
74
76
  'open-type'?: OpenType
@@ -83,8 +85,6 @@ export interface ButtonProps {
83
85
  children: ReactNode
84
86
  bindgetuserinfo?: (userInfo: any) => void
85
87
  bindtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
86
- bindtouchstart?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
87
- bindtouchend?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
88
88
  }
89
89
 
90
90
  const LOADING_IMAGE_URI =
@@ -216,15 +216,16 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
216
216
  style = {},
217
217
  children,
218
218
  bindgetuserinfo,
219
- bindtap,
220
- bindtouchstart,
221
- bindtouchend
219
+ bindtap
222
220
  } = props
223
221
 
224
222
  const pageId = useContext(RouteContext)
225
223
 
226
224
  const formContext = useContext(FormContext)
227
225
 
226
+ const enableHover = hoverClass !== 'none'
227
+ const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime, disabled })
228
+
228
229
  let submitFn: () => void | undefined
229
230
  let resetFn: () => void | undefined
230
231
 
@@ -233,27 +234,15 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
233
234
  resetFn = formContext.reset
234
235
  }
235
236
 
236
- const refs = useRef<{
237
- hoverStartTimer: ReturnType<typeof setTimeout> | undefined
238
- hoverStayTimer: ReturnType<typeof setTimeout> | undefined
239
- }>({
240
- hoverStartTimer: undefined,
241
- hoverStayTimer: undefined
242
- })
243
-
244
- const [isHover, setIsHover] = useState(false)
245
-
246
237
  const isMiniSize = size === 'mini'
247
238
 
248
- const applyHoverEffect = isHover && hoverClass !== 'none'
249
-
250
239
  const [color, hoverColor, plainColor, disabledColor] = TypeColorMap[type]
251
240
 
252
- const normalBackgroundColor = disabled ? disabledColor : applyHoverEffect || loading ? hoverColor : color
241
+ const normalBackgroundColor = disabled ? disabledColor : isHover || loading ? hoverColor : color
253
242
 
254
243
  const plainBorderColor = disabled
255
244
  ? 'rgba(0, 0, 0, .2)'
256
- : applyHoverEffect
245
+ : isHover
257
246
  ? `rgba(${plainColor},.6)`
258
247
  : `rgb(${plainColor})`
259
248
 
@@ -261,14 +250,14 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
261
250
 
262
251
  const plainTextColor = disabled
263
252
  ? 'rgba(0, 0, 0, .2)'
264
- : applyHoverEffect
253
+ : isHover
265
254
  ? `rgba(${plainColor}, .6)`
266
255
  : `rgb(${plainColor})`
267
256
 
268
257
  const normalTextColor =
269
258
  type === 'default'
270
- ? `rgba(0, 0, 0, ${disabled ? 0.3 : applyHoverEffect || loading ? 0.6 : 1})`
271
- : `rgba(255 ,255 ,255 , ${disabled || applyHoverEffect || loading ? 0.6 : 1})`
259
+ ? `rgba(0, 0, 0, ${disabled ? 0.3 : isHover || loading ? 0.6 : 1})`
260
+ : `rgba(255 ,255 ,255 , ${disabled || isHover || loading ? 0.6 : 1})`
272
261
 
273
262
  const viewStyle = {
274
263
  borderWidth: 1,
@@ -297,7 +286,7 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
297
286
  {},
298
287
  defaultStyle,
299
288
  style,
300
- applyHoverEffect ? hoverStyle : {}
289
+ isHover ? hoverStyle : {}
301
290
  )
302
291
 
303
292
  const {
@@ -366,34 +355,6 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
366
355
  }
367
356
  }
368
357
 
369
- const setStayTimer = () => {
370
- clearTimeout(refs.current.hoverStayTimer)
371
- refs.current.hoverStayTimer = setTimeout(() => {
372
- setIsHover(false)
373
- clearTimeout(refs.current.hoverStayTimer)
374
- }, hoverStayTime)
375
- }
376
-
377
- const setStartTimer = () => {
378
- clearTimeout(refs.current.hoverStartTimer)
379
- refs.current.hoverStartTimer = setTimeout(() => {
380
- setIsHover(true)
381
- clearTimeout(refs.current.hoverStartTimer)
382
- }, hoverStartTime)
383
- }
384
-
385
- const onTouchStart = (evt: NativeSyntheticEvent<TouchEvent>) => {
386
- bindtouchstart && bindtouchstart(evt)
387
- if (disabled) return
388
- setStartTimer()
389
- }
390
-
391
- const onTouchEnd = (evt: NativeSyntheticEvent<TouchEvent>) => {
392
- bindtouchend && bindtouchend(evt)
393
- if (disabled) return
394
- setStayTimer()
395
- }
396
-
397
358
  const handleFormTypeFn = () => {
398
359
  if (formType === 'submit') {
399
360
  submitFn && submitFn()
@@ -418,8 +379,6 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
418
379
  },
419
380
  layoutProps,
420
381
  {
421
- bindtouchstart: (bindtouchstart || !disabled) && onTouchStart,
422
- bindtouchend: (bindtouchend || !disabled) && onTouchEnd,
423
382
  bindtap: !disabled && onTap
424
383
  }
425
384
  ),
@@ -442,7 +401,7 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
442
401
  }
443
402
  )
444
403
 
445
- return createElement(View, innerProps, loading && createElement(Loading, { alone: !children }),
404
+ const baseButton = createElement(View, innerProps, loading && createElement(Loading, { alone: !children }),
446
405
  wrapChildren(
447
406
  props,
448
407
  {
@@ -453,6 +412,10 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
453
412
  }
454
413
  )
455
414
  )
415
+
416
+ return enableHover
417
+ ? createElement(GestureDetector, { gesture: gesture as PanGesture }, baseButton)
418
+ : baseButton
456
419
  })
457
420
 
458
421
  Button.displayName = 'MpxButton'
@@ -403,32 +403,48 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
403
403
  }
404
404
  )
405
405
 
406
- return createElement(View, innerProps,
407
- isSvg
408
- ? createElement(SvgCssUri, {
409
- uri: src,
410
- onLayout: onSvgLoad,
411
- onError: binderror && onSvgError,
412
- style: extendObject(
413
- { transformOrigin: 'top left' },
414
- modeStyle
415
- )
416
- })
417
- : loaded && renderImage({
418
- source: { uri: src },
419
- resizeMode: resizeMode,
420
- onLoad: bindload && onImageLoad,
421
- onError: binderror && onImageError,
422
- style: extendObject(
423
- {
424
- transformOrigin: 'top left',
425
- width: isCropMode ? imageWidth : '100%',
426
- height: isCropMode ? imageHeight : '100%'
427
- },
428
- isCropMode ? modeStyle : {}
429
- )
430
- }, enableFastImage)
406
+ const createBaseImage = (innerProps = {}) => {
407
+ return renderImage(
408
+ extendObject(
409
+ {
410
+ source: { uri: src },
411
+ resizeMode: resizeMode,
412
+ onLoad: bindload && onImageLoad,
413
+ onError: binderror && onImageError,
414
+ style: extendObject(
415
+ {
416
+ transformOrigin: 'top left',
417
+ width: isCropMode ? imageWidth : '100%',
418
+ height: isCropMode ? imageHeight : '100%'
419
+ },
420
+ isCropMode ? modeStyle : {}
421
+ )
422
+ },
423
+ innerProps
424
+ ),
425
+ enableFastImage
426
+ )
427
+ }
428
+
429
+ const SvgImage = createElement(
430
+ View,
431
+ innerProps,
432
+ createElement(SvgCssUri, {
433
+ uri: src,
434
+ onLayout: onSvgLoad,
435
+ onError: binderror && onSvgError,
436
+ style: extendObject(
437
+ { transformOrigin: 'top left' },
438
+ modeStyle
439
+ )
440
+ })
431
441
  )
442
+
443
+ const BaseImage = createBaseImage(innerProps)
444
+
445
+ const LayoutImage = createElement(View, innerProps, loaded && createBaseImage())
446
+
447
+ return isSvg ? SvgImage : isLayoutMode ? LayoutImage : BaseImage
432
448
  })
433
449
 
434
450
  Image.displayName = 'mpx-image'
@@ -1,5 +1,6 @@
1
1
  import { View, Text, Modal, TouchableWithoutFeedback } from 'react-native'
2
- import { PickerView, Portal } from '@ant-design/react-native'
2
+ import Portal from '../mpx-portal'
3
+ import { PickerView } from '@ant-design/react-native'
3
4
  import React, { forwardRef, useState, useRef, useEffect } from 'react'
4
5
  import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
5
6
  import { TimeProps } from './type'
@@ -9,7 +9,7 @@ interface PickerColumnItemProps {
9
9
  item: React.ReactElement
10
10
  index: number
11
11
  itemHeight: number
12
- itemWidth: number | '100%'
12
+ itemWidth?: number | '100%'
13
13
  textStyleFromParent: Record<string, any>
14
14
  textStyle: Record<string, any>
15
15
  hasVarDec: boolean
@@ -23,7 +23,7 @@ const _PickerViewColumnItem: React.FC<PickerColumnItemProps> = ({
23
23
  item,
24
24
  index,
25
25
  itemHeight,
26
- itemWidth,
26
+ itemWidth = '100%',
27
27
  textStyleFromParent,
28
28
  textStyle,
29
29
  hasVarDec,
@@ -44,8 +44,8 @@ const _PickerViewColumnItem: React.FC<PickerColumnItemProps> = ({
44
44
  return {
45
45
  opacity: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.opacity), Extrapolation.CLAMP),
46
46
  transform: [
47
- { rotateX: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.deg), Extrapolation.CLAMP) + 'deg' },
48
47
  { translateY: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.offsetY), Extrapolation.EXTEND) },
48
+ { rotateX: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.deg), Extrapolation.CLAMP) + 'deg' },
49
49
  { scale: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.scale), Extrapolation.EXTEND) }
50
50
  ]
51
51
  }
@@ -1,7 +1,7 @@
1
1
  import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react'
2
2
  import { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, SafeAreaView, ScrollView, StyleSheet, View } from 'react-native'
3
3
  import Reanimated, { AnimatedRef, useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated'
4
- import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid } from './utils'
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, useDebounceCallback, useStableCallback } from './utils'
5
5
  import useNodesRef, { HandlerRef } from './useNodesRef'
6
6
  import PickerOverlay from './pickerViewOverlay'
7
7
  import PickerMask from './pickerViewMask'
@@ -64,14 +64,12 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
64
64
  })
65
65
 
66
66
  const { height: pickerH, itemHeight } = wrapperStyle
67
- const [scrollViewWidth, setScrollViewWidth] = useState<number | '100%'>('100%')
68
- const [itemRawW, setItemRawW] = useState<number | '100%'>('100%')
69
67
  const [itemRawH, setItemRawH] = useState(itemHeight)
70
68
  const maxIndex = useMemo(() => columnData.length - 1, [columnData])
71
- const maxScrollViewWidth = useRef(-1)
72
69
  const prevScrollingInfo = useRef({ index: initialIndex, y: 0 })
73
70
  const touching = useRef(false)
74
71
  const scrolling = useRef(false)
72
+ const timerScrollTo = useRef<NodeJS.Timeout | null>(null)
75
73
  const activeIndex = useRef(initialIndex)
76
74
  const prevIndex = usePrevious(initialIndex)
77
75
  const prevMaxIndex = usePrevious(maxIndex)
@@ -88,11 +86,6 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
88
86
 
89
87
  // console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length, 'pickerH=', pickerH, 'itemRawH=', itemRawH, 'itemHeight=', itemHeight)
90
88
 
91
- // const initialOffset = useMemo(() => ({
92
- // x: 0,
93
- // y: itemRawH * initialIndex
94
- // }), [itemRawH])
95
-
96
89
  const paddingHeight = useMemo(
97
90
  () => Math.round((pickerH - itemHeight) / 2),
98
91
  [pickerH, itemHeight]
@@ -112,8 +105,41 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
112
105
  return Math.max(0, Math.min(calc, maxIndex))
113
106
  }, [itemRawH, maxIndex])
114
107
 
108
+ const getYofIndex = useCallback((index: number) => {
109
+ return index * itemRawH
110
+ }, [itemRawH])
111
+
112
+ const stableResetScrollPosition = useStableCallback((y: number) => {
113
+ // console.log('[mpx-picker-view-column], reset --->', 'columnIndex=', columnIndex, 'y=', y, touching.current, scrolling.current, itemRawH, 'snapToOffsets=', snapToOffsets)
114
+ if (touching.current || scrolling.current) {
115
+ return
116
+ }
117
+ // needReset.current = true
118
+ if (y % itemRawH !== 0) {
119
+ scrolling.current = true
120
+ const targetIndex = getIndex(y)
121
+ const targetY = getYofIndex(targetIndex)
122
+ scrollViewRef.current?.scrollTo({ x: 0, y: targetY, animated: false })
123
+ } else {
124
+ onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } })
125
+ }
126
+ })
127
+ const debounceResetScrollPosition = useDebounceCallback(stableResetScrollPosition, 10)
128
+
129
+ const clearTimerScrollTo = () => {
130
+ if (timerScrollTo.current) {
131
+ clearTimeout(timerScrollTo.current)
132
+ timerScrollTo.current = null
133
+ }
134
+ }
135
+
136
+ useEffect(() => {
137
+ return () => {
138
+ clearTimerScrollTo()
139
+ }
140
+ }, [])
141
+
115
142
  useEffect(() => {
116
- // console.log('[mpx-picker-view-column], useEffect000 --->', 'columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'prevIndex=', prevIndex, 'activeIndex=', activeIndex.current, 'maxIndex=', maxIndex, 'prevMaxIndex=', prevMaxIndex)
117
143
  if (
118
144
  !scrollViewRef.current ||
119
145
  !itemRawH ||
@@ -126,11 +152,11 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
126
152
  ) {
127
153
  return
128
154
  }
129
- // console.log('[mpx-picker-view-column], useEffect ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'y=', itemRawH * initialIndex, `${scrollViewRef.current?.scrollTo}`)
130
- setTimeout(() => {
155
+ clearTimerScrollTo()
156
+ timerScrollTo.current = setTimeout(() => {
131
157
  scrollViewRef.current?.scrollTo({
132
158
  x: 0,
133
- y: itemRawH * initialIndex,
159
+ y: getYofIndex(initialIndex),
134
160
  animated: false
135
161
  })
136
162
  }, isAndroid ? 200 : 0)
@@ -138,86 +164,64 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
138
164
  }, [itemRawH, initialIndex])
139
165
 
140
166
  const onContentSizeChange = (_w: number, h: number) => {
141
- const y = itemRawH * initialIndex
142
- // console.log('[mpx-picker-view-column], onContentSizeChange --->', 'columnIndex=', columnIndex, '_w=', _w, 'h=', h, 'y=', y, 'itemRawH=', itemRawH)
167
+ const y = getYofIndex(initialIndex)
143
168
  if (y <= h) {
144
- setTimeout(() => {
169
+ clearTimerScrollTo()
170
+ timerScrollTo.current = setTimeout(() => {
145
171
  scrollViewRef.current?.scrollTo({ x: 0, y, animated: false })
146
172
  }, 0)
147
173
  }
148
174
  }
149
175
 
150
- const onScrollViewLayout = (e: LayoutChangeEvent) => {
151
- if (isAndroid) {
152
- return
153
- }
154
- // RN iOS bug: https://github.com/facebook/react-native/issues/36135
155
- const { width } = e.nativeEvent.layout
156
- const widthInt = Math.ceil(width)
157
- // console.log('[mpx-picker-view-column], onScrollViewLayout --->', 'columnIndex=', columnIndex, 'width=', width, 'widthInt=', widthInt, 'scrollViewWidth=', scrollViewWidth)
158
- if (widthInt !== scrollViewWidth) {
159
- const maxW = maxScrollViewWidth.current
160
- if (maxW !== -1 && widthInt > maxW) {
161
- return
162
- }
163
- if (maxW === -1) {
164
- maxScrollViewWidth.current = Math.ceil(widthInt * 1.5)
165
- }
166
- setScrollViewWidth(widthInt)
167
- }
168
- if (itemRawW === '100%') {
169
- setItemRawW(widthInt)
170
- }
171
- }
172
-
173
176
  const onItemLayout = (e: LayoutChangeEvent) => {
174
177
  const { height: rawH } = e.nativeEvent.layout
175
- // console.log('[mpx-picker-view-column], onItemLayout --->', 'columnIndex=', columnIndex, 'width=', width)
176
- if (rawH && itemRawH !== rawH) {
177
- setItemRawH(rawH)
178
+ const roundedH = Math.round(rawH)
179
+ if (roundedH && roundedH !== itemRawH) {
180
+ setItemRawH(roundedH)
178
181
  }
179
182
  }
180
183
 
181
- const onTouchStart = () => {
184
+ const onScrollBeginDrag = () => {
185
+ isIOS && debounceResetScrollPosition.clear()
182
186
  touching.current = true
183
187
  prevScrollingInfo.current = {
184
188
  index: activeIndex.current,
185
- y: activeIndex.current * itemRawH
189
+ y: getYofIndex(activeIndex.current)
186
190
  }
187
191
  }
188
192
 
189
- const onTouchEnd = () => {
190
- touching.current = false
191
- }
192
-
193
- const onTouchCancel = () => {
193
+ const onScrollEndDrag = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
194
194
  touching.current = false
195
+ const { y } = e.nativeEvent.contentOffset
196
+ if (isIOS) {
197
+ if (y >= 0 && y <= snapToOffsets[maxIndex]) {
198
+ debounceResetScrollPosition(y)
199
+ }
200
+ }
195
201
  }
196
202
 
197
203
  const onMomentumScrollBegin = () => {
204
+ isIOS && debounceResetScrollPosition.clear()
198
205
  scrolling.current = true
199
206
  }
200
207
 
201
- const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
208
+ const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent> | { nativeEvent: { contentOffset: { y: number } } }) => {
202
209
  scrolling.current = false
203
- if (!itemRawH) {
204
- return
205
- }
206
210
  const { y: scrollY } = e.nativeEvent.contentOffset
207
- let calcIndex = Math.round(scrollY / itemRawH)
208
- activeIndex.current = calcIndex
209
- if (calcIndex !== initialIndex) {
210
- calcIndex = Math.max(0, Math.min(calcIndex, maxIndex)) || 0
211
+ // console.log('[mpx-picker-view-column], onMomentumScrollEnd --->', 'columnIndex=', columnIndex, scrollY, itemRawH)
212
+ if (isIOS && scrollY % itemRawH !== 0) {
213
+ return debounceResetScrollPosition(scrollY)
214
+ }
215
+ const calcIndex = getIndex(scrollY)
216
+ if (calcIndex !== activeIndex.current) {
217
+ activeIndex.current = calcIndex
211
218
  onSelectChange(calcIndex)
212
219
  }
213
220
  }
214
221
 
215
222
  const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
216
- if (isAndroid) {
217
- return
218
- }
219
- // 全局注册的震动触感 hook
220
- const pickerVibrate = global.__mpx.config.rnConfig.pickerVibrate
223
+ // 全局注册的振动触感 hook
224
+ const pickerVibrate = global.__mpx?.config?.rnConfig?.pickerVibrate
221
225
  if (typeof pickerVibrate !== 'function') {
222
226
  return
223
227
  }
@@ -229,7 +233,7 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
229
233
  if (currentId !== prevIndex) {
230
234
  prevScrollingInfo.current = {
231
235
  index: currentId,
232
- y: currentId * itemRawH
236
+ y: getYofIndex(currentId)
233
237
  }
234
238
  // vibrateShort({ type: 'selection' })
235
239
  pickerVibrate()
@@ -246,7 +250,6 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
246
250
  item={item}
247
251
  index={index}
248
252
  itemHeight={itemHeight}
249
- itemWidth={itemRawW}
250
253
  textStyleFromParent={textStyleFromParent}
251
254
  textStyle={textStyle}
252
255
  hasVarDec={hasVarDec}
@@ -271,14 +274,12 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
271
274
  showsHorizontalScrollIndicator={false}
272
275
  scrollEventThrottle={16}
273
276
  {...layoutProps}
274
- style={[{ width: scrollViewWidth }]}
277
+ style={[{ width: '100%' }]}
275
278
  decelerationRate="fast"
276
279
  snapToOffsets={snapToOffsets}
277
280
  onScroll={onScroll}
278
- onLayout={onScrollViewLayout}
279
- onTouchStart={onTouchStart}
280
- onTouchEnd={onTouchEnd}
281
- onTouchCancel={onTouchCancel}
281
+ onScrollBeginDrag={onScrollBeginDrag}
282
+ onScrollEndDrag={onScrollEndDrag}
282
283
  onMomentumScrollBegin={onMomentumScrollBegin}
283
284
  onMomentumScrollEnd={onMomentumScrollEnd}
284
285
  onContentSizeChange={onContentSizeChange}
@@ -0,0 +1,32 @@
1
+ import { useEffect, useRef, ReactNode } from 'react'
2
+ import { PortalContextValue } from '../context'
3
+ import { getFocusedNavigation } from '@mpxjs/utils'
4
+
5
+ export type PortalConsumerProps = {
6
+ manager: PortalContextValue
7
+ children?: ReactNode
8
+ }
9
+ const PortalConsumer = ({ manager, children } :PortalConsumerProps): JSX.Element | null => {
10
+ const keyRef = useRef<any>(null)
11
+ useEffect(() => {
12
+ const navigation = getFocusedNavigation()
13
+ const curPageId = navigation?.pageId
14
+ manager.update(keyRef.current, children, curPageId)
15
+ }, [children])
16
+ useEffect(() => {
17
+ if (!manager) {
18
+ throw new Error(
19
+ 'Looks like you forgot to wrap your root component with `Provider` component from `@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal`.\n\n'
20
+ )
21
+ }
22
+ const navigation = getFocusedNavigation()
23
+ const curPageId = navigation?.pageId
24
+ keyRef.current = manager.mount(children, undefined, curPageId)
25
+ return () => {
26
+ manager.unmount(keyRef.current)
27
+ }
28
+ }, [])
29
+ return null
30
+ }
31
+
32
+ export default PortalConsumer