@mpxjs/webpack-plugin 2.10.4-beta.9 → 2.10.5-beta.1

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 (70) hide show
  1. package/lib/index.js +10 -1
  2. package/lib/json-compiler/helper.js +1 -4
  3. package/lib/platform/style/wx/index.js +22 -21
  4. package/lib/platform/template/wx/index.js +21 -1
  5. package/lib/react/processScript.js +9 -1
  6. package/lib/react/script-helper.js +5 -1
  7. package/lib/resolver/PackageEntryPlugin.js +3 -1
  8. package/lib/runtime/components/react/dist/mpx-button.jsx +9 -4
  9. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +2 -4
  10. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +20 -17
  11. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +7 -2
  12. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +7 -2
  13. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +7 -2
  14. package/lib/runtime/components/react/dist/mpx-image.jsx +9 -2
  15. package/lib/runtime/components/react/dist/mpx-input.jsx +7 -2
  16. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +1 -1
  17. package/lib/runtime/components/react/dist/mpx-label.jsx +7 -2
  18. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +7 -2
  19. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +76 -42
  20. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -13
  21. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +8 -7
  22. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +28 -10
  23. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +9 -2
  24. package/lib/runtime/components/react/dist/mpx-radio.jsx +7 -2
  25. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +7 -2
  26. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +13 -4
  27. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +6 -3
  28. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +11 -9
  29. package/lib/runtime/components/react/dist/mpx-swiper.jsx +82 -36
  30. package/lib/runtime/components/react/dist/mpx-switch.jsx +7 -2
  31. package/lib/runtime/components/react/dist/mpx-text.jsx +7 -2
  32. package/lib/runtime/components/react/dist/mpx-video.jsx +7 -2
  33. package/lib/runtime/components/react/dist/mpx-view.jsx +13 -8
  34. package/lib/runtime/components/react/dist/useAnimationHooks.js +27 -4
  35. package/lib/runtime/components/react/dist/utils.jsx +87 -97
  36. package/lib/runtime/components/react/mpx-button.tsx +12 -3
  37. package/lib/runtime/components/react/mpx-canvas/Image.ts +4 -4
  38. package/lib/runtime/components/react/mpx-canvas/index.tsx +24 -17
  39. package/lib/runtime/components/react/mpx-checkbox-group.tsx +9 -1
  40. package/lib/runtime/components/react/mpx-checkbox.tsx +9 -1
  41. package/lib/runtime/components/react/mpx-icon/index.tsx +9 -1
  42. package/lib/runtime/components/react/mpx-image.tsx +38 -19
  43. package/lib/runtime/components/react/mpx-input.tsx +10 -1
  44. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +1 -1
  45. package/lib/runtime/components/react/mpx-label.tsx +9 -1
  46. package/lib/runtime/components/react/mpx-movable-area.tsx +7 -1
  47. package/lib/runtime/components/react/mpx-movable-view.tsx +75 -42
  48. package/lib/runtime/components/react/mpx-picker/index.tsx +18 -16
  49. package/lib/runtime/components/react/mpx-picker-view/index.tsx +22 -8
  50. package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +36 -32
  51. package/lib/runtime/components/react/mpx-radio-group.tsx +20 -9
  52. package/lib/runtime/components/react/mpx-radio.tsx +9 -1
  53. package/lib/runtime/components/react/mpx-rich-text/index.tsx +10 -2
  54. package/lib/runtime/components/react/mpx-scroll-view.tsx +14 -3
  55. package/lib/runtime/components/react/mpx-sticky-header.tsx +7 -4
  56. package/lib/runtime/components/react/mpx-swiper-item.tsx +11 -19
  57. package/lib/runtime/components/react/mpx-swiper.tsx +95 -38
  58. package/lib/runtime/components/react/mpx-switch.tsx +10 -2
  59. package/lib/runtime/components/react/mpx-text.tsx +10 -2
  60. package/lib/runtime/components/react/mpx-video.tsx +7 -2
  61. package/lib/runtime/components/react/mpx-view.tsx +23 -9
  62. package/lib/runtime/components/react/useAnimationHooks.ts +30 -9
  63. package/lib/runtime/components/react/utils.tsx +95 -102
  64. package/lib/runtime/components/web/mpx-web-view.vue +1 -1
  65. package/lib/runtime/mpxGlobal.js +1 -0
  66. package/lib/runtime/optionProcessor.d.ts +5 -0
  67. package/lib/template-compiler/bind-this.js +8 -7
  68. package/lib/template-compiler/compiler.js +1 -1
  69. package/lib/wxs/pre-loader.js +1 -0
  70. package/package.json +2 -2
@@ -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 } 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'
@@ -209,9 +209,9 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
209
209
 
210
210
  const onScrollEndDrag = useCallback((e: NativeSyntheticEvent<NativeScrollEvent>) => {
211
211
  dragging.current = false
212
- if (isIOS) {
212
+ if (!isAndroid) {
213
213
  const { y } = e.nativeEvent.contentOffset
214
- if (y % itemRawH === 0) {
214
+ if (y % itemRawH === 0 || (isHarmony && y > snapToOffsets[maxIndex])) {
215
215
  onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } })
216
216
  } else if (y > 0 && y < snapToOffsets[maxIndex]) {
217
217
  timerResetPosition.current = setTimeout(() => {
@@ -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'
@@ -22,6 +22,7 @@ import { FormContext, FormFieldValue, RadioGroupContext, GroupValue } from './co
22
22
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
23
23
  import useNodesRef, { HandlerRef } from './useNodesRef'
24
24
  import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils'
25
+ import Portal from './mpx-portal'
25
26
 
26
27
  export interface RadioGroupProps {
27
28
  name: string
@@ -71,6 +72,7 @@ const radioGroup = forwardRef<
71
72
  const styleObj = extendObject({}, defaultStyle, style)
72
73
 
73
74
  const {
75
+ hasPositionFixed,
74
76
  hasSelfPercent,
75
77
  normalStyle,
76
78
  hasVarDec,
@@ -156,18 +158,27 @@ const radioGroup = forwardRef<
156
158
  }
157
159
  )
158
160
 
159
- return createElement(View, innerProps, createElement(
160
- RadioGroupContext.Provider,
161
- { value: contextValue },
162
- wrapChildren(
163
- props,
161
+ const finalComponent = createElement(View, innerProps,
162
+ createElement(
163
+ RadioGroupContext.Provider,
164
164
  {
165
- hasVarDec,
166
- varContext: varContextRef.current
167
- }
165
+ value: contextValue
166
+ },
167
+ wrapChildren(
168
+ props,
169
+ {
170
+ hasVarDec,
171
+ varContext: varContextRef.current
172
+ }
173
+ )
168
174
  )
169
175
  )
170
- )
176
+
177
+ if (hasPositionFixed) {
178
+ return createElement(Portal, null, finalComponent)
179
+ }
180
+
181
+ return finalComponent
171
182
  })
172
183
 
173
184
  radioGroup.displayName = 'MpxRadioGroup'
@@ -12,6 +12,7 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners'
12
12
  import useNodesRef, { HandlerRef } from './useNodesRef'
13
13
  import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils'
14
14
  import Icon from './mpx-icon'
15
+ import Portal from './mpx-portal'
15
16
 
16
17
  export interface RadioProps {
17
18
  value?: string
@@ -117,6 +118,7 @@ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
117
118
  }
118
119
 
119
120
  const {
121
+ hasPositionFixed,
120
122
  hasSelfPercent,
121
123
  normalStyle,
122
124
  hasVarDec,
@@ -192,7 +194,7 @@ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
192
194
  }
193
195
  }, [checked])
194
196
 
195
- return createElement(View, innerProps,
197
+ const finalComponent = createElement(View, innerProps,
196
198
  createElement(
197
199
  View,
198
200
  { style: defaultStyle },
@@ -213,6 +215,12 @@ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
213
215
  }
214
216
  )
215
217
  )
218
+
219
+ if (hasPositionFixed) {
220
+ return createElement(Portal, null, finalComponent)
221
+ }
222
+
223
+ return finalComponent
216
224
  }
217
225
  )
218
226
 
@@ -9,6 +9,7 @@ import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
9
9
  import { useTransformStyle, useLayout, extendObject } from '../utils'
10
10
  import { WebView, WebViewMessageEvent } from 'react-native-webview'
11
11
  import { generateHTML } from './html'
12
+ import Portal from '../mpx-portal'
12
13
 
13
14
  type Node = {
14
15
  type: 'node' | 'text'
@@ -69,7 +70,8 @@ const _RichText = forwardRef<HandlerRef<View, _RichTextProps>, _RichTextProps>((
69
70
  normalStyle,
70
71
  hasSelfPercent,
71
72
  setWidth,
72
- setHeight
73
+ setHeight,
74
+ hasPositionFixed
73
75
  } = useTransformStyle(Object.assign({
74
76
  width: '100%',
75
77
  height: webViewHeight
@@ -109,7 +111,7 @@ const _RichText = forwardRef<HandlerRef<View, _RichTextProps>, _RichTextProps>((
109
111
 
110
112
  const html: string = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes)
111
113
 
112
- return createElement(View, innerProps,
114
+ let finalComponent: JSX.Element = createElement(View, innerProps,
113
115
  createElement(WebView, {
114
116
  source: { html: generateHTML(html) },
115
117
  onMessage: (event: WebViewMessageEvent) => {
@@ -117,6 +119,12 @@ const _RichText = forwardRef<HandlerRef<View, _RichTextProps>, _RichTextProps>((
117
119
  }
118
120
  })
119
121
  )
122
+
123
+ if (hasPositionFixed) {
124
+ finalComponent = createElement(Portal, null, finalComponent)
125
+ }
126
+
127
+ return finalComponent
120
128
  })
121
129
 
122
130
  _RichText.displayName = 'mpx-rich-text'
@@ -35,11 +35,12 @@ import { ScrollView, RefreshControl, Gesture, GestureDetector } from 'react-nati
35
35
  import { View, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle, Animated as RNAnimated } from 'react-native'
36
36
  import { isValidElement, Children, JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, useMemo, createElement } from 'react'
37
37
  import Animated, { useAnimatedRef, useSharedValue, withTiming, useAnimatedStyle, runOnJS } from 'react-native-reanimated'
38
- import { warn } from '@mpxjs/utils'
38
+ import { warn, hasOwn } from '@mpxjs/utils'
39
39
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
40
40
  import useNodesRef, { HandlerRef } from './useNodesRef'
41
41
  import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, GestureHandler, HIDDEN_STYLE } from './utils'
42
42
  import { IntersectionObserverContext, ScrollViewContext } from './context'
43
+ import Portal from './mpx-portal'
43
44
 
44
45
  interface ScrollViewProps {
45
46
  children?: ReactNode;
@@ -199,6 +200,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
199
200
  hasVarDec,
200
201
  varContextRef,
201
202
  hasSelfPercent,
203
+ hasPositionFixed,
202
204
  setWidth,
203
205
  setHeight
204
206
  } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
@@ -659,7 +661,11 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
659
661
 
660
662
  const scrollAdditionalProps: ScrollAdditionalProps = extendObject(
661
663
  {
662
- style: extendObject({}, innerStyle, layoutStyle),
664
+ style: extendObject(hasOwn(innerStyle, 'flex') || hasOwn(innerStyle, 'flexGrow')
665
+ ? {}
666
+ : {
667
+ flexGrow: 0
668
+ }, innerStyle, layoutStyle),
663
669
  pinchGestureEnabled: false,
664
670
  alwaysBounceVertical: false,
665
671
  alwaysBounceHorizontal: false,
@@ -782,7 +788,12 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
782
788
  )
783
789
  )
784
790
 
785
- return hasRefresher ? withRefresherScrollView : commonScrollView
791
+ let scrollViewComponent = hasRefresher ? withRefresherScrollView : commonScrollView
792
+
793
+ if (hasPositionFixed) {
794
+ scrollViewComponent = createElement(Portal, null, scrollViewComponent)
795
+ }
796
+ return scrollViewComponent
786
797
  })
787
798
 
788
799
  _ScrollView.displayName = 'MpxScrollView'
@@ -1,5 +1,5 @@
1
- import { useEffect, useRef, useState, useContext, forwardRef, useMemo, createElement, ReactNode, useId } from 'react'
2
- import { Animated, StyleSheet, View, NativeSyntheticEvent, ViewStyle, LayoutChangeEvent } from 'react-native'
1
+ import { useEffect, useRef, useContext, forwardRef, useMemo, createElement, ReactNode, useId } from 'react'
2
+ import { Animated, StyleSheet, View, NativeSyntheticEvent, ViewStyle, LayoutChangeEvent, useAnimatedValue } from 'react-native'
3
3
  import { ScrollViewContext, StickyContext } from './context'
4
4
  import useNodesRef, { HandlerRef } from './useNodesRef'
5
5
  import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
@@ -54,7 +54,9 @@ const _StickyHeader = forwardRef<HandlerRef<View, StickyHeaderProps>, StickyHead
54
54
 
55
55
  const { textStyle, innerStyle = {} } = splitStyle(normalStyle)
56
56
 
57
- const headerTopAnimated = useRef(new Animated.Value(0)).current
57
+ const headerTopAnimated = useAnimatedValue(0)
58
+ // harmony animatedValue 不支持通过 _value 访问
59
+ const headerTopRef = useRef(0)
58
60
 
59
61
  useEffect(() => {
60
62
  registerStickyHeader({ key: id, updatePosition })
@@ -75,6 +77,7 @@ const _StickyHeader = forwardRef<HandlerRef<View, StickyHeaderProps>, StickyHead
75
77
  duration: 0,
76
78
  useNativeDriver: true
77
79
  }).start()
80
+ headerTopRef.current = top
78
81
  }
79
82
  )
80
83
  } else {
@@ -96,7 +99,7 @@ const _StickyHeader = forwardRef<HandlerRef<View, StickyHeaderProps>, StickyHead
96
99
 
97
100
  const listener = scrollOffset.addListener((state: { value: number }) => {
98
101
  const currentScrollValue = state.value
99
- const newIsStickOnTop = currentScrollValue > (headerTopAnimated as any)._value
102
+ const newIsStickOnTop = currentScrollValue > headerTopRef.current
100
103
  if (newIsStickOnTop !== isStickOnTopRef.current) {
101
104
  isStickOnTopRef.current = newIsStickOnTop
102
105
  bindstickontopchange(