@mpxjs/webpack-plugin 2.10.5 → 2.10.6

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 (62) hide show
  1. package/lib/index.js +10 -1
  2. package/lib/json-compiler/helper.js +1 -4
  3. package/lib/platform/template/wx/index.js +21 -1
  4. package/lib/resolver/PackageEntryPlugin.js +3 -1
  5. package/lib/runtime/components/react/dist/mpx-button.jsx +7 -2
  6. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +2 -4
  7. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +20 -17
  8. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +7 -2
  9. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +7 -2
  10. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +7 -2
  11. package/lib/runtime/components/react/dist/mpx-image.jsx +9 -2
  12. package/lib/runtime/components/react/dist/mpx-input.jsx +7 -2
  13. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +1 -1
  14. package/lib/runtime/components/react/dist/mpx-label.jsx +7 -2
  15. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +7 -2
  16. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +76 -42
  17. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -13
  18. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +8 -7
  19. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +26 -8
  20. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +9 -2
  21. package/lib/runtime/components/react/dist/mpx-radio.jsx +7 -2
  22. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +7 -2
  23. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +13 -4
  24. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +11 -9
  25. package/lib/runtime/components/react/dist/mpx-swiper.jsx +82 -36
  26. package/lib/runtime/components/react/dist/mpx-switch.jsx +7 -2
  27. package/lib/runtime/components/react/dist/mpx-text.jsx +7 -2
  28. package/lib/runtime/components/react/dist/mpx-video.jsx +7 -2
  29. package/lib/runtime/components/react/dist/mpx-view.jsx +2 -4
  30. package/lib/runtime/components/react/dist/utils.jsx +2 -2
  31. package/lib/runtime/components/react/mpx-button.tsx +9 -1
  32. package/lib/runtime/components/react/mpx-canvas/Image.ts +4 -4
  33. package/lib/runtime/components/react/mpx-canvas/index.tsx +24 -17
  34. package/lib/runtime/components/react/mpx-checkbox-group.tsx +9 -1
  35. package/lib/runtime/components/react/mpx-checkbox.tsx +9 -1
  36. package/lib/runtime/components/react/mpx-icon/index.tsx +9 -1
  37. package/lib/runtime/components/react/mpx-image.tsx +38 -19
  38. package/lib/runtime/components/react/mpx-input.tsx +10 -1
  39. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +1 -1
  40. package/lib/runtime/components/react/mpx-label.tsx +9 -1
  41. package/lib/runtime/components/react/mpx-movable-area.tsx +7 -1
  42. package/lib/runtime/components/react/mpx-movable-view.tsx +75 -42
  43. package/lib/runtime/components/react/mpx-picker/index.tsx +18 -16
  44. package/lib/runtime/components/react/mpx-picker-view/index.tsx +22 -8
  45. package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +34 -30
  46. package/lib/runtime/components/react/mpx-radio-group.tsx +20 -9
  47. package/lib/runtime/components/react/mpx-radio.tsx +9 -1
  48. package/lib/runtime/components/react/mpx-rich-text/index.tsx +10 -2
  49. package/lib/runtime/components/react/mpx-scroll-view.tsx +14 -3
  50. package/lib/runtime/components/react/mpx-swiper-item.tsx +11 -19
  51. package/lib/runtime/components/react/mpx-swiper.tsx +95 -38
  52. package/lib/runtime/components/react/mpx-switch.tsx +10 -2
  53. package/lib/runtime/components/react/mpx-text.tsx +10 -2
  54. package/lib/runtime/components/react/mpx-video.tsx +7 -2
  55. package/lib/runtime/components/react/mpx-view.tsx +8 -4
  56. package/lib/runtime/components/react/utils.tsx +4 -4
  57. package/lib/runtime/components/web/mpx-web-view.vue +1 -1
  58. package/lib/runtime/mpxGlobal.js +1 -0
  59. package/lib/runtime/optionProcessor.d.ts +5 -0
  60. package/lib/template-compiler/bind-this.js +8 -7
  61. package/lib/wxs/pre-loader.js +1 -0
  62. package/package.json +4 -4
@@ -27,6 +27,7 @@ import { SvgCssUri } from 'react-native-svg/css'
27
27
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
28
28
  import useNodesRef, { HandlerRef } from './useNodesRef'
29
29
  import { SVG_REGEXP, useLayout, useTransformStyle, renderImage, extendObject } from './utils'
30
+ import Portal from './mpx-portal'
30
31
 
31
32
  export type Mode =
32
33
  | 'scaleToFill'
@@ -159,7 +160,13 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
159
160
  }
160
161
  }
161
162
 
162
- const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
163
+ const {
164
+ hasPositionFixed,
165
+ hasSelfPercent,
166
+ normalStyle,
167
+ setWidth,
168
+ setHeight
169
+ } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
163
170
 
164
171
  const { layoutRef, layoutStyle, layoutProps } = useLayout({
165
172
  props,
@@ -356,25 +363,31 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
356
363
 
357
364
  useEffect(() => {
358
365
  if (!isSvg && isLayoutMode) {
359
- RNImage.getSize(src, (width: number, height: number) => {
360
- state.current.imageWidth = width
361
- state.current.imageHeight = height
362
- state.current.ratio = !width ? 0 : height / width
363
-
364
- if (isWidthFixMode
365
- ? state.current.viewWidth
366
- : isHeightFixMode
367
- ? state.current.viewHeight
368
- : state.current.viewWidth && state.current.viewHeight) {
369
- state.current.viewWidth && setViewWidth(state.current.viewWidth)
370
- state.current.viewHeight && setViewHeight(state.current.viewHeight)
371
- setRatio(!width ? 0 : height / width)
372
- setImageWidth(width)
373
- setImageHeight(height)
374
- state.current = {}
366
+ RNImage.getSize(
367
+ src,
368
+ (width: number, height: number) => {
369
+ state.current.imageWidth = width
370
+ state.current.imageHeight = height
371
+ state.current.ratio = !width ? 0 : height / width
372
+
373
+ if (isWidthFixMode
374
+ ? state.current.viewWidth
375
+ : isHeightFixMode
376
+ ? state.current.viewHeight
377
+ : state.current.viewWidth && state.current.viewHeight) {
378
+ state.current.viewWidth && setViewWidth(state.current.viewWidth)
379
+ state.current.viewHeight && setViewHeight(state.current.viewHeight)
380
+ setRatio(!width ? 0 : height / width)
381
+ setImageWidth(width)
382
+ setImageHeight(height)
383
+ state.current = {}
384
+ setLoaded(true)
385
+ }
386
+ },
387
+ () => {
375
388
  setLoaded(true)
376
389
  }
377
- })
390
+ )
378
391
  }
379
392
  }, [src, isSvg, isLayoutMode])
380
393
 
@@ -441,7 +454,13 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
441
454
 
442
455
  const LayoutImage = createElement(View, innerProps, loaded && BaseImage)
443
456
 
444
- return isSvg ? SvgImage : isLayoutMode ? LayoutImage : BaseImage
457
+ const finalComponent = isSvg ? SvgImage : isLayoutMode ? LayoutImage : BaseImage
458
+
459
+ if (hasPositionFixed) {
460
+ return createElement(Portal, null, finalComponent)
461
+ }
462
+
463
+ return finalComponent
445
464
  })
446
465
 
447
466
  Image.displayName = 'mpx-image'
@@ -58,6 +58,7 @@ import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isIOS } fr
58
58
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
59
59
  import useNodesRef, { HandlerRef } from './useNodesRef'
60
60
  import { FormContext, FormFieldValue, KeyboardAvoidContext } from './context'
61
+ import Portal from './mpx-portal'
61
62
 
62
63
  type InputStyle = Omit<
63
64
  TextStyle & ViewStyle & Pick<FlexStyle, 'minHeight'>,
@@ -202,6 +203,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
202
203
  )
203
204
 
204
205
  const {
206
+ hasPositionFixed,
205
207
  hasSelfPercent,
206
208
  normalStyle,
207
209
  setWidth,
@@ -481,7 +483,14 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
481
483
  layoutRef
482
484
  }
483
485
  )
484
- return createElement(TextInput, innerProps)
486
+
487
+ const finalComponent = createElement(TextInput, innerProps)
488
+
489
+ if (hasPositionFixed) {
490
+ return createElement(Portal, null, finalComponent)
491
+ }
492
+
493
+ return finalComponent
485
494
  })
486
495
 
487
496
  Input.displayName = 'MpxInput'
@@ -48,7 +48,7 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
48
48
  const { ref, cursorSpacing = 0 } = keyboardAvoid.current
49
49
  setTimeout(() => {
50
50
  ref?.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
51
- const aboveOffset = pageY + height - endCoordinates.screenY
51
+ const aboveOffset = offset.value + pageY + height - endCoordinates.screenY
52
52
  const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing
53
53
  const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing)
54
54
  const value = aboveOffset > 0 ? belowValue : aboveValue
@@ -8,6 +8,7 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners'
8
8
  import useNodesRef, { HandlerRef } from './useNodesRef'
9
9
  import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils'
10
10
  import { LabelContext, LabelContextValue } from './context'
11
+ import Portal from './mpx-portal'
11
12
 
12
13
  export interface LabelProps {
13
14
  for?: string
@@ -45,6 +46,7 @@ const Label = forwardRef<HandlerRef<View, LabelProps>, LabelProps>(
45
46
  const styleObj = extendObject({}, defaultStyle, style)
46
47
 
47
48
  const {
49
+ hasPositionFixed,
48
50
  hasSelfPercent,
49
51
  normalStyle,
50
52
  hasVarDec,
@@ -91,7 +93,7 @@ const Label = forwardRef<HandlerRef<View, LabelProps>, LabelProps>(
91
93
  }
92
94
  )
93
95
 
94
- return createElement(View, innerProps, createElement(
96
+ const finalComponent = createElement(View, innerProps, createElement(
95
97
  LabelContext.Provider,
96
98
  { value: contextRef },
97
99
  wrapChildren(
@@ -104,6 +106,12 @@ const Label = forwardRef<HandlerRef<View, LabelProps>, LabelProps>(
104
106
  }
105
107
  )
106
108
  ))
109
+
110
+ if (hasPositionFixed) {
111
+ return createElement(Portal, null, finalComponent)
112
+ }
113
+
114
+ return finalComponent
107
115
  }
108
116
  )
109
117
 
@@ -8,6 +8,7 @@ import useNodesRef, { HandlerRef } from './useNodesRef'
8
8
  import useInnerProps from './getInnerListeners'
9
9
  import { MovableAreaContext } from './context'
10
10
  import { useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
11
+ import Portal from './mpx-portal'
11
12
 
12
13
  interface MovableAreaProps {
13
14
  style?: Record<string, any>
@@ -30,6 +31,7 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
30
31
  normalStyle,
31
32
  hasVarDec,
32
33
  varContextRef,
34
+ hasPositionFixed,
33
35
  setWidth,
34
36
  setHeight
35
37
  } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
@@ -60,7 +62,7 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
60
62
  { layoutRef }
61
63
  )
62
64
 
63
- return createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(
65
+ let movableComponent: JSX.Element = createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(
64
66
  View,
65
67
  innerProps,
66
68
  wrapChildren(
@@ -71,6 +73,10 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
71
73
  }
72
74
  )
73
75
  ))
76
+ if (hasPositionFixed) {
77
+ movableComponent = createElement(Portal, null, movableComponent)
78
+ }
79
+ return movableComponent
74
80
  })
75
81
 
76
82
  _MovableArea.displayName = 'MpxMovableArea'
@@ -147,6 +147,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
147
147
  const yInertialMotion = useSharedValue(false)
148
148
  const isFirstTouch = useSharedValue(true)
149
149
  const touchEvent = useSharedValue<string>('')
150
+ const initialViewPosition = useSharedValue({ x: x || 0, y: y || 0 })
150
151
 
151
152
  const MovableAreaLayout = useContext(MovableAreaContext)
152
153
 
@@ -214,11 +215,13 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
214
215
  })
215
216
  : newY
216
217
  }
217
- runOnJS(handleTriggerChange)({
218
- x: newX,
219
- y: newY,
220
- type: 'setData'
221
- })
218
+ if (propsRef.current.bindchange) {
219
+ runOnJS(handleTriggerChange)({
220
+ x: newX,
221
+ y: newY,
222
+ type: 'setData'
223
+ })
224
+ }
222
225
  }
223
226
  })()
224
227
  }, [x, y])
@@ -230,19 +233,6 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
230
233
  }
231
234
  }, [MovableAreaLayout.height, MovableAreaLayout.width])
232
235
 
233
- useAnimatedReaction(
234
- () => ({
235
- offsetX: offsetX.value,
236
- offsetY: offsetY.value
237
- }),
238
- (currentValue: { offsetX: any; offsetY: any }) => {
239
- const { offsetX, offsetY } = currentValue
240
- runOnJS(handleTriggerChange)({
241
- x: offsetX,
242
- y: offsetY
243
- })
244
- })
245
-
246
236
  const getTouchSource = useCallback((offsetX: number, offsetY: number) => {
247
237
  const hasOverBoundary = offsetX < draggableXRange.value[0] || offsetX > draggableXRange.value[1] ||
248
238
  offsetY < draggableYRange.value[0] || offsetY > draggableYRange.value[1]
@@ -426,6 +416,13 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
426
416
  runOnJS(triggerStartOnJS)({ e })
427
417
  }
428
418
  })
419
+ .onStart(() => {
420
+ 'worklet'
421
+ initialViewPosition.value = {
422
+ x: offsetX.value,
423
+ y: offsetY.value
424
+ }
425
+ })
429
426
  .onTouchesMove((e: GestureTouchEvent) => {
430
427
  'worklet'
431
428
  const changedTouches = e.changedTouches[0] || { x: 0, y: 0 }
@@ -435,11 +432,12 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
435
432
  isFirstTouch.value = false
436
433
  }
437
434
  handleTriggerMove(e)
435
+ })
436
+ .onUpdate((e: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
437
+ 'worklet'
438
438
  if (disabled) return
439
- const changeX = changedTouches.x - startPosition.value.x
440
- const changeY = changedTouches.y - startPosition.value.y
441
439
  if (direction === 'horizontal' || direction === 'all') {
442
- const newX = offsetX.value + changeX
440
+ const newX = initialViewPosition.value.x + e.translationX
443
441
  if (!outOfBounds) {
444
442
  const { x } = checkBoundaryPosition({ positionX: newX, positionY: offsetY.value })
445
443
  offsetX.value = x
@@ -448,7 +446,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
448
446
  }
449
447
  }
450
448
  if (direction === 'vertical' || direction === 'all') {
451
- const newY = offsetY.value + changeY
449
+ const newY = initialViewPosition.value.y + e.translationY
452
450
  if (!outOfBounds) {
453
451
  const { y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: newY })
454
452
  offsetY.value = y
@@ -456,6 +454,12 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
456
454
  offsetY.value = newY
457
455
  }
458
456
  }
457
+ if (propsRef.current.bindchange) {
458
+ runOnJS(handleTriggerChange)({
459
+ x: offsetX.value,
460
+ y: offsetY.value
461
+ })
462
+ }
459
463
  })
460
464
  .onTouchesUp((e: GestureTouchEvent) => {
461
465
  'worklet'
@@ -464,31 +468,41 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
464
468
  if (bindtouchend || catchtouchend) {
465
469
  runOnJS(triggerEndOnJS)({ e })
466
470
  }
471
+ })
472
+ .onEnd((e: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
473
+ 'worklet'
474
+ isMoving.value = false
467
475
  if (disabled) return
468
- if (!inertia) {
476
+ // 处理没有惯性且超出边界的回弹
477
+ if (!inertia && outOfBounds) {
469
478
  const { x, y } = checkBoundaryPosition({ positionX: offsetX.value, positionY: offsetY.value })
470
- if (x !== offsetX.value) {
471
- offsetX.value = animation
472
- ? withSpring(x, {
473
- duration: 1500,
474
- dampingRatio: 0.8
479
+ if (x !== offsetX.value || y !== offsetY.value) {
480
+ if (x !== offsetX.value) {
481
+ offsetX.value = animation
482
+ ? withSpring(x, {
483
+ duration: 1500,
484
+ dampingRatio: 0.8
485
+ })
486
+ : x
487
+ }
488
+ if (y !== offsetY.value) {
489
+ offsetY.value = animation
490
+ ? withSpring(y, {
491
+ duration: 1500,
492
+ dampingRatio: 0.8
493
+ })
494
+ : y
495
+ }
496
+ if (propsRef.current.bindchange) {
497
+ runOnJS(handleTriggerChange)({
498
+ x,
499
+ y
475
500
  })
476
- : x
477
- }
478
- if (y !== offsetY.value) {
479
- offsetY.value = animation
480
- ? withSpring(y, {
481
- duration: 1500,
482
- dampingRatio: 0.8
483
- })
484
- : y
501
+ }
485
502
  }
503
+ return
486
504
  }
487
- })
488
- .onFinalize((e: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
489
- 'worklet'
490
- isMoving.value = false
491
- if (!inertia || disabled || !animation) return
505
+ // 惯性处理
492
506
  if (direction === 'horizontal' || direction === 'all') {
493
507
  xInertialMotion.value = true
494
508
  offsetX.value = withDecay({
@@ -497,6 +511,12 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
497
511
  clamp: draggableXRange.value
498
512
  }, () => {
499
513
  xInertialMotion.value = false
514
+ if (propsRef.current.bindchange) {
515
+ runOnJS(handleTriggerChange)({
516
+ x: offsetX.value,
517
+ y: offsetY.value
518
+ })
519
+ }
500
520
  })
501
521
  }
502
522
  if (direction === 'vertical' || direction === 'all') {
@@ -507,10 +527,23 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
507
527
  clamp: draggableYRange.value
508
528
  }, () => {
509
529
  yInertialMotion.value = false
530
+ if (propsRef.current.bindchange) {
531
+ runOnJS(handleTriggerChange)({
532
+ x: offsetX.value,
533
+ y: offsetY.value
534
+ })
535
+ }
510
536
  })
511
537
  }
512
538
  })
513
539
  .withRef(movableGestureRef)
540
+
541
+ if (direction === 'horizontal') {
542
+ gesturePan.activeOffsetX([-5, 5]).failOffsetY([-5, 5])
543
+ } else if (direction === 'vertical') {
544
+ gesturePan.activeOffsetY([-5, 5]).failOffsetX([-5, 5])
545
+ }
546
+
514
547
  if (simultaneousHandlers && simultaneousHandlers.length) {
515
548
  gesturePan.simultaneousWithExternalGesture(...simultaneousHandlers)
516
549
  }
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useRef, useContext, useEffect } from 'react'
1
+ import React, { forwardRef, useRef, useContext, useEffect, createElement } from 'react'
2
2
  import { StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native'
3
3
  import { warn } from '@mpxjs/utils'
4
4
  import PickerSelector from './selector'
@@ -9,7 +9,7 @@ import PickerRegion from './region'
9
9
  import { FormContext, FormFieldValue, RouteContext } from '../context'
10
10
  import useNodesRef, { HandlerRef } from '../useNodesRef'
11
11
  import useInnerProps, { getCustomEvent } from '../getInnerListeners'
12
- import { extendObject } from '../utils'
12
+ import { extendObject, useLayout } from '../utils'
13
13
  import { createPopupManager } from '../mpx-popup'
14
14
  import { EventType, LanguageCode, PickerMode, PickerProps } from './type'
15
15
 
@@ -127,26 +127,29 @@ const Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>(
127
127
  const buttonText = buttonTextMap[(global.__mpx?.i18n?.locale as LanguageCode) || 'zh-CN']
128
128
  const pickerValue = useRef(value)
129
129
  pickerValue.current = Array.isArray(value) ? value.slice() : value
130
- const innerLayout = useRef({})
131
- const nodeRef = useRef(null)
130
+ const nodeRef = useRef<View>(null)
132
131
  const pickerRef = useRef<any>(null)
133
132
  const { open, show, hide, remove } = useRef(createPopupManager()).current
134
133
 
135
134
  useNodesRef<View, PickerProps>(props, ref, nodeRef)
135
+ const { layoutRef, layoutProps } = useLayout({
136
+ props,
137
+ hasSelfPercent: false,
138
+ nodeRef
139
+ })
140
+
136
141
  const innerProps = useInnerProps(
137
142
  extendObject(
138
143
  {},
139
144
  props,
140
145
  {
141
146
  ref: nodeRef
142
- }
147
+ },
148
+ layoutProps
143
149
  ),
144
150
  [],
145
- { layoutRef: innerLayout }
151
+ { layoutRef }
146
152
  )
147
- const getInnerLayout = (layout: React.MutableRefObject<{}>) => {
148
- innerLayout.current = layout.current
149
- }
150
153
 
151
154
  useEffect(() => {
152
155
  if (range && pickerRef.current && mode === PickerMode.MULTI_SELECTOR) {
@@ -195,7 +198,7 @@ const Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>(
195
198
  const eventData = getCustomEvent(
196
199
  'columnchange',
197
200
  {},
198
- { detail: { column: columnIndex, value }, layoutRef: innerLayout }
201
+ { detail: { column: columnIndex, value }, layoutRef }
199
202
  )
200
203
  props.bindcolumnchange?.(eventData)
201
204
  }
@@ -209,7 +212,7 @@ const Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>(
209
212
  const eventData = getCustomEvent(
210
213
  'change',
211
214
  {},
212
- { detail: { value: pickerValue.current }, layoutRef: innerLayout }
215
+ { detail: { value: pickerValue.current }, layoutRef }
213
216
  )
214
217
  bindchange?.(eventData)
215
218
  hide()
@@ -220,7 +223,6 @@ const Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>(
220
223
  children,
221
224
  bindchange: onChange,
222
225
  bindcolumnchange: onColumnChange,
223
- getInnerLayout,
224
226
  getRange: () => range
225
227
  })
226
228
 
@@ -269,10 +271,10 @@ const Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>(
269
271
  }
270
272
  }, [])
271
273
 
272
- return (
273
- <TouchableWithoutFeedback onPress={show}>
274
- {children}
275
- </TouchableWithoutFeedback>
274
+ return createElement(
275
+ TouchableWithoutFeedback,
276
+ { onPress: show },
277
+ createElement(View, innerProps, children)
276
278
  )
277
279
  }
278
280
  )
@@ -1,5 +1,5 @@
1
1
  import { View } from 'react-native'
2
- import React, { forwardRef, useRef } from 'react'
2
+ import React, { createElement, forwardRef, useRef } from 'react'
3
3
  import useInnerProps, { getCustomEvent } from '../getInnerListeners'
4
4
  import useNodesRef, { HandlerRef } from '../useNodesRef'
5
5
  import {
@@ -11,6 +11,7 @@ import {
11
11
  extendObject
12
12
  } from '../utils'
13
13
  import { PickerViewStyleContext } from './pickerVIewContext'
14
+ import Portal from '../mpx-portal'
14
15
  import type { AnyFunc } from '../types/common'
15
16
  /**
16
17
  * ✔ value
@@ -86,7 +87,8 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
86
87
  varContextRef,
87
88
  hasSelfPercent,
88
89
  setWidth,
89
- setHeight
90
+ setHeight,
91
+ hasPositionFixed
90
92
  } = useTransformStyle(style, { enableVar, externalVarContext })
91
93
 
92
94
  useNodesRef<View, PickerViewProps>(props, ref, nodeRef, {
@@ -222,13 +224,25 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
222
224
  return renderColumns
223
225
  }
224
226
 
225
- return (
226
- <PickerViewStyleContext.Provider value={textStyle}>
227
- <View {...innerProps}>
228
- <View style={[styles.wrapper]}>{renderPickerColumns()}</View>
229
- </View>
230
- </PickerViewStyleContext.Provider>
227
+ const finalComponent = createElement(
228
+ PickerViewStyleContext.Provider,
229
+ { value: textStyle },
230
+ createElement(
231
+ View,
232
+ innerProps,
233
+ createElement(
234
+ View,
235
+ { style: [styles.wrapper] },
236
+ renderPickerColumns()
237
+ )
238
+ )
231
239
  )
240
+
241
+ if (hasPositionFixed) {
242
+ return createElement(Portal, null, finalComponent)
243
+ }
244
+
245
+ return finalComponent
232
246
  })
233
247
 
234
248
  _PickerView.displayName = 'MpxPickerView'
@@ -1,7 +1,7 @@
1
- import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react'
1
+ import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback, createElement } from 'react'
2
2
  import { GestureResponderEvent, LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, 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, isIOS, isHarmony } from '../utils'
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, isHarmony, extendObject } from '../utils'
5
5
  import useNodesRef, { HandlerRef } from '../useNodesRef'
6
6
  import PickerIndicator from './pickerViewIndicator'
7
7
  import PickerMask from './pickerViewMask'
@@ -302,33 +302,36 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
302
302
  })
303
303
 
304
304
  const renderScollView = () => {
305
- return (
306
- <PickerViewColumnAnimationContext.Provider value={offsetYShared}>
307
- <Reanimated.ScrollView
308
- ref={scrollViewRef}
309
- bounces={true}
310
- horizontal={false}
311
- nestedScrollEnabled={true}
312
- removeClippedSubviews={false}
313
- showsVerticalScrollIndicator={false}
314
- showsHorizontalScrollIndicator={false}
315
- scrollEventThrottle={16}
316
- {...layoutProps}
317
- onTouchEnd={onClickOnceItem}
318
- style={[{ width: '100%' }]}
319
- decelerationRate="fast"
320
- snapToOffsets={snapToOffsets}
321
- onScroll={onScroll}
322
- onScrollBeginDrag={onScrollBeginDrag}
323
- onScrollEndDrag={onScrollEndDrag}
324
- onMomentumScrollBegin={onMomentumScrollBegin}
325
- onMomentumScrollEnd={onMomentumScrollEnd}
326
- onContentSizeChange={onContentSizeChange}
327
- contentContainerStyle={contentContainerStyle}
328
- >
329
- {renderInnerchild()}
330
- </Reanimated.ScrollView>
331
- </PickerViewColumnAnimationContext.Provider>
305
+ const innerProps = extendObject({}, layoutProps, {
306
+ ref: scrollViewRef,
307
+ bounces: true,
308
+ horizontal: false,
309
+ nestedScrollEnabled: true,
310
+ removeClippedSubviews: false,
311
+ showsVerticalScrollIndicator: false,
312
+ showsHorizontalScrollIndicator: false,
313
+ scrollEventThrottle: 16,
314
+ style: styles.scrollView,
315
+ decelerationRate: 'fast',
316
+ snapToOffsets: snapToOffsets,
317
+ onTouchEnd: onClickOnceItem,
318
+ onScroll,
319
+ onScrollBeginDrag,
320
+ onScrollEndDrag,
321
+ onMomentumScrollBegin,
322
+ onMomentumScrollEnd,
323
+ onContentSizeChange,
324
+ contentContainerStyle
325
+ }) as React.ComponentProps<typeof Reanimated.ScrollView>
326
+
327
+ return createElement(
328
+ PickerViewColumnAnimationContext.Provider,
329
+ { value: offsetYShared },
330
+ createElement(
331
+ Reanimated.ScrollView,
332
+ innerProps,
333
+ renderInnerchild()
334
+ )
332
335
  )
333
336
  }
334
337
 
@@ -356,7 +359,8 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
356
359
  })
357
360
 
358
361
  const styles = StyleSheet.create({
359
- wrapper: { display: 'flex', flex: 1 }
362
+ wrapper: { display: 'flex', flex: 1 },
363
+ scrollView: { width: '100%' }
360
364
  })
361
365
 
362
366
  _PickerViewColumn.displayName = 'MpxPickerViewColumn'