@mpxjs/webpack-plugin 2.10.13 → 2.10.14-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 (108) hide show
  1. package/lib/dependencies/ImportDependency.js +102 -0
  2. package/lib/index.js +9 -9
  3. package/lib/platform/style/wx/index.js +7 -1
  4. package/lib/platform/template/wx/component-config/button.js +13 -4
  5. package/lib/platform/template/wx/component-config/index.js +3 -1
  6. package/lib/platform/template/wx/component-config/nav-container.js +27 -0
  7. package/lib/react/processScript.js +4 -2
  8. package/lib/react/script-helper.js +3 -3
  9. package/lib/runtime/components/ali/mpx-nav-container.mpx +3 -0
  10. package/lib/runtime/components/react/context.ts +17 -6
  11. package/lib/runtime/components/react/dist/context.d.ts +78 -0
  12. package/lib/runtime/components/react/dist/context.js +1 -0
  13. package/lib/runtime/components/react/dist/event.config.d.ts +7 -0
  14. package/lib/runtime/components/react/dist/getInnerListeners.d.ts +7 -0
  15. package/lib/runtime/components/react/dist/mpx-async-suspense.d.ts +12 -0
  16. package/lib/runtime/components/react/dist/mpx-button.d.ts +68 -0
  17. package/lib/runtime/components/react/dist/mpx-canvas/Bus.d.ts +23 -0
  18. package/lib/runtime/components/react/dist/mpx-canvas/CanvasGradient.d.ts +7 -0
  19. package/lib/runtime/components/react/dist/mpx-canvas/CanvasRenderingContext2D.d.ts +6 -0
  20. package/lib/runtime/components/react/dist/mpx-canvas/Image.d.ts +20 -0
  21. package/lib/runtime/components/react/dist/mpx-canvas/ImageData.d.ts +8 -0
  22. package/lib/runtime/components/react/dist/mpx-canvas/constructorsRegistry.d.ts +10 -0
  23. package/lib/runtime/components/react/dist/mpx-canvas/html.d.ts +2 -0
  24. package/lib/runtime/components/react/dist/mpx-canvas/index.d.ts +32 -0
  25. package/lib/runtime/components/react/dist/mpx-canvas/utils.d.ts +52 -0
  26. package/lib/runtime/components/react/dist/mpx-checkbox-group.d.ts +20 -0
  27. package/lib/runtime/components/react/dist/mpx-checkbox.d.ts +32 -0
  28. package/lib/runtime/components/react/dist/mpx-form.d.ts +27 -0
  29. package/lib/runtime/components/react/dist/mpx-icon/index.d.ts +18 -0
  30. package/lib/runtime/components/react/dist/mpx-image.d.ts +21 -0
  31. package/lib/runtime/components/react/dist/mpx-inline-text.d.ts +7 -0
  32. package/lib/runtime/components/react/dist/mpx-input.d.ts +50 -0
  33. package/lib/runtime/components/react/dist/mpx-input.jsx +36 -17
  34. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.d.ts +12 -0
  35. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +66 -47
  36. package/lib/runtime/components/react/dist/mpx-label.d.ts +20 -0
  37. package/lib/runtime/components/react/dist/mpx-movable-area.d.ts +20 -0
  38. package/lib/runtime/components/react/dist/mpx-movable-view.d.ts +63 -0
  39. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +24 -17
  40. package/lib/runtime/components/react/dist/mpx-nav-container.d.ts +9 -0
  41. package/lib/runtime/components/react/dist/mpx-nav-container.jsx +23 -0
  42. package/lib/runtime/components/react/dist/mpx-navigator.d.ts +9 -0
  43. package/lib/runtime/components/react/dist/mpx-picker/date.d.ts +6 -0
  44. package/lib/runtime/components/react/dist/mpx-picker/dateData.d.ts +7 -0
  45. package/lib/runtime/components/react/dist/mpx-picker/index.d.ts +6 -0
  46. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.d.ts +6 -0
  47. package/lib/runtime/components/react/dist/mpx-picker/region.d.ts +6 -0
  48. package/lib/runtime/components/react/dist/mpx-picker/regionData.d.ts +2 -0
  49. package/lib/runtime/components/react/dist/mpx-picker/selector.d.ts +6 -0
  50. package/lib/runtime/components/react/dist/mpx-picker/time.d.ts +6 -0
  51. package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +106 -0
  52. package/lib/runtime/components/react/dist/mpx-picker-view/index.d.ts +31 -0
  53. package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.d.ts +8 -0
  54. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.d.ts +22 -0
  55. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.d.ts +14 -0
  56. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewFaces.d.ts +16 -0
  57. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewIndicator.d.ts +12 -0
  58. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewMask.d.ts +11 -0
  59. package/lib/runtime/components/react/dist/mpx-popup/index.d.ts +22 -0
  60. package/lib/runtime/components/react/dist/mpx-popup/popupBase.d.ts +16 -0
  61. package/lib/runtime/components/react/dist/mpx-portal/index.d.ts +15 -0
  62. package/lib/runtime/components/react/dist/mpx-portal/portal-host.d.ts +29 -0
  63. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.d.ts +9 -0
  64. package/lib/runtime/components/react/dist/mpx-radio-group.d.ts +20 -0
  65. package/lib/runtime/components/react/dist/mpx-radio.d.ts +26 -0
  66. package/lib/runtime/components/react/dist/mpx-rich-text/html.d.ts +1 -0
  67. package/lib/runtime/components/react/dist/mpx-rich-text/index.d.ts +24 -0
  68. package/lib/runtime/components/react/dist/mpx-root-portal.d.ts +14 -0
  69. package/lib/runtime/components/react/dist/mpx-scroll-view.d.ts +54 -0
  70. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +26 -8
  71. package/lib/runtime/components/react/dist/mpx-simple-text.d.ts +7 -0
  72. package/lib/runtime/components/react/dist/mpx-simple-view.d.ts +7 -0
  73. package/lib/runtime/components/react/dist/mpx-sticky-header.d.ts +17 -0
  74. package/lib/runtime/components/react/dist/mpx-sticky-section.d.ts +15 -0
  75. package/lib/runtime/components/react/dist/mpx-swiper-item.d.ts +18 -0
  76. package/lib/runtime/components/react/dist/mpx-swiper.d.ts +52 -0
  77. package/lib/runtime/components/react/dist/mpx-swiper.jsx +49 -40
  78. package/lib/runtime/components/react/dist/mpx-switch.d.ts +26 -0
  79. package/lib/runtime/components/react/dist/mpx-text.d.ts +21 -0
  80. package/lib/runtime/components/react/dist/mpx-textarea.d.ts +7 -0
  81. package/lib/runtime/components/react/dist/mpx-video.d.ts +101 -0
  82. package/lib/runtime/components/react/dist/mpx-view.d.ts +34 -0
  83. package/lib/runtime/components/react/dist/mpx-view.jsx +8 -11
  84. package/lib/runtime/components/react/dist/mpx-web-view.d.ts +22 -0
  85. package/lib/runtime/components/react/dist/nav.d.ts +8 -0
  86. package/lib/runtime/components/react/dist/nav.jsx +137 -0
  87. package/lib/runtime/components/react/dist/parser.d.ts +39 -0
  88. package/lib/runtime/components/react/dist/useAnimationHooks.d.ts +32 -0
  89. package/lib/runtime/components/react/dist/useNavShared.d.ts +2 -0
  90. package/lib/runtime/components/react/dist/useNavShared.js +6 -0
  91. package/lib/runtime/components/react/dist/useNodesRef.d.ts +11 -0
  92. package/lib/runtime/components/react/dist/utils.d.ts +122 -0
  93. package/lib/runtime/components/react/mpx-input.tsx +46 -24
  94. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +75 -46
  95. package/lib/runtime/components/react/mpx-movable-view.tsx +26 -20
  96. package/lib/runtime/components/react/mpx-nav-container.tsx +33 -0
  97. package/lib/runtime/components/react/mpx-scroll-view.tsx +30 -8
  98. package/lib/runtime/components/react/mpx-swiper.tsx +49 -38
  99. package/lib/runtime/components/react/mpx-view.tsx +8 -11
  100. package/lib/runtime/components/react/nav.tsx +163 -0
  101. package/lib/runtime/components/react/types/common.d.ts +19 -0
  102. package/lib/runtime/components/react/useNavShared.ts +8 -0
  103. package/lib/runtime/components/web/mpx-nav-container.vue +13 -0
  104. package/lib/runtime/components/wx/mpx-nav-container.mpx +9 -0
  105. package/lib/utils/dom-tag-config.js +2 -2
  106. package/package.json +2 -2
  107. package/LICENSE +0 -433
  108. package/lib/dependencies/ImportDependencyTemplate.js +0 -50
@@ -95,13 +95,15 @@ export interface InputProps {
95
95
  'selection-start'?: number
96
96
  'selection-end'?: number
97
97
  'placeholder-style'?: { color?: string }
98
- 'enable-offset'?: boolean,
98
+ 'enable-offset'?: boolean
99
99
  'enable-var'?: boolean
100
100
  'external-var-context'?: Record<string, any>
101
101
  'parent-font-size'?: number
102
102
  'parent-width'?: number
103
103
  'parent-height'?: number
104
- 'adjust-position': boolean,
104
+ // 只有 RN 环境读取
105
+ 'keyboard-type'?: string
106
+ 'adjust-position': boolean
105
107
  bindinput?: (evt: NativeSyntheticEvent<TextInputTextInputEventData> | unknown) => void
106
108
  bindfocus?: (evt: NativeSyntheticEvent<TextInputFocusEventData> | unknown) => void
107
109
  bindblur?: (evt: NativeSyntheticEvent<TextInputFocusEventData> | unknown) => void
@@ -118,11 +120,11 @@ export interface PrivateInputProps {
118
120
 
119
121
  type FinalInputProps = InputProps & PrivateInputProps
120
122
 
121
- const keyboardTypeMap: Record<Type, string> = {
122
- text: 'default',
123
+ const inputModeMap: Record<Type, string> = {
124
+ text: 'text',
123
125
  number: 'numeric',
124
- idcard: 'default',
125
- digit: isIOS ? 'decimal-pad' : 'numeric'
126
+ idcard: 'text',
127
+ digit: 'decimal'
126
128
  }
127
129
 
128
130
  const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps>((props: FinalInputProps, ref): JSX.Element => {
@@ -150,6 +152,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
150
152
  'parent-width': parentWidth,
151
153
  'parent-height': parentHeight,
152
154
  'adjust-position': adjustPosition = true,
155
+ 'keyboard-type': originalKeyboardType,
153
156
  bindinput,
154
157
  bindfocus,
155
158
  bindblur,
@@ -182,7 +185,6 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
182
185
  return ''
183
186
  }
184
187
 
185
- const keyboardType = keyboardTypeMap[type]
186
188
  const defaultValue = parseValue(value)
187
189
  const textAlignVertical = multiline ? 'top' : 'auto'
188
190
 
@@ -280,8 +282,8 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
280
282
  }
281
283
 
282
284
  const setKeyboardAvoidContext = () => {
283
- if (adjustPosition && keyboardAvoid) {
284
- keyboardAvoid.current = { cursorSpacing, ref: nodeRef }
285
+ if (keyboardAvoid) {
286
+ keyboardAvoid.current = { cursorSpacing, ref: nodeRef, adjustPosition }
285
287
  }
286
288
  }
287
289
 
@@ -295,20 +297,39 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
295
297
  }
296
298
 
297
299
  const onFocus = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
298
- setKeyboardAvoidContext()
299
- bindfocus && bindfocus(
300
- getCustomEvent(
301
- 'focus',
302
- evt,
303
- {
304
- detail: {
305
- value: tmpValue.current || ''
306
- },
307
- layoutRef
308
- },
309
- props
310
- )
311
- )
300
+ if (!keyboardAvoid?.current) {
301
+ setKeyboardAvoidContext()
302
+ }
303
+
304
+ if (bindfocus && keyboardAvoid?.current) {
305
+ const focusAction = () => {
306
+ bindfocus(
307
+ getCustomEvent(
308
+ 'focus',
309
+ evt,
310
+ {
311
+ detail: {
312
+ value: tmpValue.current || '',
313
+ height: keyboardAvoid.current?.keyboardHeight,
314
+ },
315
+ layoutRef
316
+ },
317
+ props
318
+ )
319
+ )
320
+ if (keyboardAvoid.current?.onKeyboardShow) {
321
+ keyboardAvoid.current.onKeyboardShow = undefined
322
+ }
323
+ }
324
+ if (keyboardAvoid.current.keyboardHeight) {
325
+ // iOS: keyboard 获取高度时机 keyboardWillShow 在 input focus 之前,可以立即执行
326
+ focusAction()
327
+ } else {
328
+ // Android,Harmony: keyboard 获取高度时机 keyboardDidShow 在 input focus 之后,需要延迟回调
329
+ evt.persist()
330
+ keyboardAvoid.current.onKeyboardShow = focusAction
331
+ }
332
+ }
312
333
  }
313
334
 
314
335
  const onBlur = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
@@ -440,7 +461,8 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
440
461
  ref: nodeRef,
441
462
  style: extendObject({}, normalStyle, layoutStyle),
442
463
  allowFontScaling,
443
- keyboardType: keyboardType,
464
+ inputMode: originalKeyboardType ? undefined : inputModeMap[type],
465
+ keyboardType: originalKeyboardType,
444
466
  secureTextEntry: !!password,
445
467
  defaultValue: defaultValue,
446
468
  value: inputValue,
@@ -1,8 +1,9 @@
1
- import React, { ReactNode, useContext, useEffect } from 'react'
1
+ /* eslint-disable space-before-function-paren */
2
+ import React, { ReactNode, useContext, useEffect, useRef } from 'react'
2
3
  import { DimensionValue, EmitterSubscription, Keyboard, View, ViewStyle, NativeSyntheticEvent, NativeTouchEvent } from 'react-native'
3
- import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated'
4
+ import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, cancelAnimation } from 'react-native-reanimated'
4
5
  import { KeyboardAvoidContext } from './context'
5
- import { isIOS } from './utils'
6
+ import { isAndroid, isIOS } from './utils'
6
7
 
7
8
  type KeyboardAvoidViewProps = {
8
9
  children?: ReactNode
@@ -18,15 +19,36 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
18
19
  const basic = useSharedValue('auto')
19
20
  const keyboardAvoid = useContext(KeyboardAvoidContext)
20
21
 
22
+ // fix: 某些特殊机型下隐藏键盘可能会先触发一次 keyboardWillShow,
23
+ // 比如机型 iPhone 11 Pro,可能会导致显隐动画冲突
24
+ // 因此增加状态标记 + clearTimeout + cancelAnimation 来优化
25
+ const isShow = useRef<boolean>(false)
26
+ const timerRef = useRef<NodeJS.Timeout | null>(null)
27
+
21
28
  const animatedStyle = useAnimatedStyle(() => ({
29
+ // translate/position top可能会导致底部渲染区域缺失(需要 android 配置聚焦时禁用高度缩小),margin-top 会导致 portal 的定位失效,无法顶起 portal
22
30
  transform: [{ translateY: -offset.value }],
23
31
  flexBasis: basic.value as DimensionValue
24
32
  }))
25
33
 
26
34
  const resetKeyboard = () => {
35
+ if (!isShow.current) {
36
+ return
37
+ }
38
+
39
+ isShow.current = false
40
+ timerRef.current && clearTimeout(timerRef.current)
41
+
27
42
  if (keyboardAvoid?.current) {
43
+ const inputRef = keyboardAvoid.current.ref?.current
44
+ if (inputRef && inputRef.isFocused()) {
45
+ // 修复 Android 点击键盘收起按钮时当前 input 没触发失焦的问题
46
+ inputRef.blur()
47
+ }
28
48
  keyboardAvoid.current = null
29
49
  }
50
+
51
+ cancelAnimation(offset)
30
52
  offset.value = withTiming(0, { duration, easing })
31
53
  basic.value = 'auto'
32
54
  }
@@ -40,68 +62,75 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
40
62
  useEffect(() => {
41
63
  let subscriptions: EmitterSubscription[] = []
42
64
 
43
- if (isIOS) {
44
- subscriptions = [
45
- Keyboard.addListener('keyboardWillShow', (evt: any) => {
46
- if (!keyboardAvoid?.current) return
47
- const { endCoordinates } = evt
48
- const { ref, cursorSpacing = 0 } = keyboardAvoid.current
49
- setTimeout(() => {
50
- ref?.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
65
+ function keybaordAvoding(evt: any, ios = false) {
66
+ if (!keyboardAvoid?.current || isShow.current) {
67
+ return
68
+ }
69
+
70
+ isShow.current = true
71
+
72
+ if (ios) {
73
+ timerRef.current && clearTimeout(timerRef.current)
74
+ }
75
+
76
+ const { endCoordinates } = evt
77
+ const { ref, cursorSpacing = 0, adjustPosition, onKeyboardShow } = keyboardAvoid.current
78
+ keyboardAvoid.current.keyboardHeight = endCoordinates.height
79
+ onKeyboardShow?.()
80
+ if (adjustPosition) {
81
+ // 默认沿用旧版本逻辑,在 android 原生关闭键盘避让的情况下应该将该配置设置为 false,走 mpx 的键盘避让逻辑,否则bundle内的所有input都会无法避让键盘
82
+ const enableNativeKeyboardAvoiding = mpxGlobal?.__mpx?.config?.rnConfig?.enableNativeKeyboardAvoiding ?? true
83
+ const callback = () => {
84
+ ref?.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
85
+ function calculateOffset() {
86
+ // enableNativeKeyboardAvoding 默认开启
87
+ if (enableNativeKeyboardAvoiding && isAndroid) {
88
+ const aboveOffset = pageY + height - endCoordinates.screenY
89
+ const belowOffset = endCoordinates.height - aboveOffset
90
+ const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing
91
+ const belowValue = Math.min(belowOffset, cursorSpacing)
92
+ return aboveOffset > 0 ? belowValue : aboveValue
93
+ }
94
+
51
95
  const aboveOffset = offset.value + pageY + height - endCoordinates.screenY
52
96
  const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing
53
97
  const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing)
54
- const value = aboveOffset > 0 ? belowValue : aboveValue
55
- offset.value = withTiming(value, { duration, easing }, (finished) => {
56
- if (finished) {
57
- // Set flexBasic after animation to trigger re-layout and reset layout information
58
- basic.value = '99.99%'
59
- }
60
- })
61
- })
62
- })
63
- }),
64
- Keyboard.addListener('keyboardWillHide', resetKeyboard)
65
- ]
66
- } else {
67
- subscriptions = [
68
- Keyboard.addListener('keyboardDidShow', (evt: any) => {
69
- if (!keyboardAvoid?.current) return
70
- const { endCoordinates } = evt
71
- const { ref, cursorSpacing = 0 } = keyboardAvoid.current
72
- ref?.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
73
- const aboveOffset = pageY + height - endCoordinates.screenY
74
- const belowOffset = endCoordinates.height - aboveOffset
75
- const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing
76
- const belowValue = Math.min(belowOffset, cursorSpacing)
77
- const value = aboveOffset > 0 ? belowValue : aboveValue
78
- offset.value = withTiming(value, { duration, easing }, (finished) => {
98
+ return aboveOffset > 0 ? belowValue : aboveValue
99
+ }
100
+
101
+ cancelAnimation(offset)
102
+ offset.value = withTiming(calculateOffset(), { duration, easing }, finished => {
79
103
  if (finished) {
80
104
  // Set flexBasic after animation to trigger re-layout and reset layout information
81
105
  basic.value = '99.99%'
82
106
  }
83
107
  })
84
108
  })
109
+ }
110
+ ;(isIOS ? () => (timerRef.current = setTimeout(callback)) : callback)()
111
+ }
112
+ }
113
+
114
+ if (isIOS) {
115
+ subscriptions = [
116
+ Keyboard.addListener('keyboardWillShow', (evt: any) => {
117
+ keybaordAvoding(evt, true)
85
118
  }),
86
- Keyboard.addListener('keyboardDidHide', resetKeyboard)
119
+ Keyboard.addListener('keyboardWillHide', resetKeyboard)
87
120
  ]
121
+ } else {
122
+ subscriptions = [Keyboard.addListener('keyboardDidShow', keybaordAvoding), Keyboard.addListener('keyboardDidHide', resetKeyboard)]
88
123
  }
89
124
 
90
125
  return () => {
91
126
  subscriptions.forEach(subscription => subscription.remove())
127
+ timerRef.current && clearTimeout(timerRef.current)
92
128
  }
93
129
  }, [keyboardAvoid])
94
130
 
95
131
  return (
96
- <View style={style} onTouchEnd={onTouchEnd}>
97
- <Animated.View
98
- style={[
99
- contentContainerStyle,
100
- animatedStyle
101
- ]}
102
- >
103
- {children}
104
- </Animated.View>
132
+ <View style={style} onTouchEnd={onTouchEnd} onTouchMove={onTouchEnd}>
133
+ <Animated.View style={[contentContainerStyle, animatedStyle]}>{children}</Animated.View>
105
134
  </View>
106
135
  )
107
136
  }
@@ -22,7 +22,7 @@ import { StyleSheet, View, LayoutChangeEvent } from 'react-native'
22
22
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
23
23
  import useNodesRef, { HandlerRef } from './useNodesRef'
24
24
  import { MovableAreaContext } from './context'
25
- import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, GestureHandler, flatGesture, extendObject, omit, useNavigation } from './utils'
25
+ import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, GestureHandler, flatGesture, extendObject, omit, useNavigation, useRunOnJSCallback } from './utils'
26
26
  import { GestureDetector, Gesture, GestureTouchEvent, GestureStateChangeEvent, PanGestureHandlerEventPayload, PanGesture } from 'react-native-gesture-handler'
27
27
  import Animated, {
28
28
  useSharedValue,
@@ -30,7 +30,6 @@ import Animated, {
30
30
  withDecay,
31
31
  runOnJS,
32
32
  runOnUI,
33
- useAnimatedReaction,
34
33
  withSpring
35
34
  } from 'react-native-reanimated'
36
35
  import { collectDataset, noop } from '@mpxjs/utils'
@@ -87,7 +86,6 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
87
86
  const layoutRef = useRef<any>({})
88
87
  const changeSource = useRef<any>('')
89
88
  const hasLayoutRef = useRef(false)
90
-
91
89
  const propsRef = useRef<any>({})
92
90
  propsRef.current = (props || {}) as MovableViewProps
93
91
 
@@ -202,16 +200,6 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
202
200
  )
203
201
  }, [])
204
202
 
205
- // 节流版本的 change 事件触发
206
- const handleTriggerChangeThrottled = useCallback(({ x, y, type }: { x: number; y: number; type?: string }) => {
207
- 'worklet'
208
- const now = Date.now()
209
- if (now - lastChangeTime.value >= changeThrottleTime) {
210
- lastChangeTime.value = now
211
- runOnJS(handleTriggerChange)({ x, y, type })
212
- }
213
- }, [changeThrottleTime])
214
-
215
203
  useEffect(() => {
216
204
  runOnUI(() => {
217
205
  if (offsetX.value !== x || offsetY.value !== y) {
@@ -233,7 +221,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
233
221
  : newY
234
222
  }
235
223
  if (bindchange) {
236
- runOnJS(handleTriggerChange)({
224
+ runOnJS(runOnJSCallback)('handleTriggerChange', {
237
225
  x: newX,
238
226
  y: newY,
239
227
  type: 'setData'
@@ -408,13 +396,31 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
408
396
  catchtouchend && catchtouchend(e)
409
397
  }
410
398
 
399
+ const runOnJSCallbackRef = useRef({
400
+ handleTriggerChange,
401
+ triggerStartOnJS,
402
+ triggerMoveOnJS,
403
+ triggerEndOnJS
404
+ })
405
+ const runOnJSCallback = useRunOnJSCallback(runOnJSCallbackRef)
406
+
407
+ // 节流版本的 change 事件触发
408
+ const handleTriggerChangeThrottled = useCallback(({ x, y, type }: { x: number; y: number; type?: string }) => {
409
+ 'worklet'
410
+ const now = Date.now()
411
+ if (now - lastChangeTime.value >= changeThrottleTime) {
412
+ lastChangeTime.value = now
413
+ runOnJS(runOnJSCallback)('handleTriggerChange', { x, y, type })
414
+ }
415
+ }, [changeThrottleTime])
416
+
411
417
  const gesture = useMemo(() => {
412
418
  const handleTriggerMove = (e: GestureTouchEvent) => {
413
419
  'worklet'
414
420
  const hasTouchmove = !!bindhtouchmove || !!bindvtouchmove || !!bindtouchmove
415
421
  const hasCatchTouchmove = !!catchhtouchmove || !!catchvtouchmove || !!catchtouchmove
416
422
  if (hasTouchmove || hasCatchTouchmove) {
417
- runOnJS(triggerMoveOnJS)({
423
+ runOnJS(runOnJSCallback)('triggerMoveOnJS', {
418
424
  e,
419
425
  touchEvent: touchEvent.value,
420
426
  hasTouchmove,
@@ -433,7 +439,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
433
439
  y: changedTouches.y
434
440
  }
435
441
  if (bindtouchstart || catchtouchstart) {
436
- runOnJS(triggerStartOnJS)({ e })
442
+ runOnJS(runOnJSCallback)('triggerStartOnJS', { e })
437
443
  }
438
444
  })
439
445
  .onStart(() => {
@@ -487,7 +493,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
487
493
  isFirstTouch.value = true
488
494
  isMoving.value = false
489
495
  if (bindtouchend || catchtouchend) {
490
- runOnJS(triggerEndOnJS)({ e })
496
+ runOnJS(runOnJSCallback)('triggerEndOnJS', { e })
491
497
  }
492
498
  })
493
499
  .onEnd((e: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
@@ -515,7 +521,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
515
521
  : y
516
522
  }
517
523
  if (bindchange) {
518
- runOnJS(handleTriggerChange)({
524
+ runOnJS(runOnJSCallback)('handleTriggerChange', {
519
525
  x,
520
526
  y
521
527
  })
@@ -532,7 +538,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
532
538
  }, () => {
533
539
  xInertialMotion.value = false
534
540
  if (bindchange) {
535
- runOnJS(handleTriggerChange)({
541
+ runOnJS(runOnJSCallback)('handleTriggerChange', {
536
542
  x: offsetX.value,
537
543
  y: offsetY.value
538
544
  })
@@ -548,7 +554,7 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
548
554
  }, () => {
549
555
  yInertialMotion.value = false
550
556
  if (bindchange) {
551
- runOnJS(handleTriggerChange)({
557
+ runOnJS(runOnJSCallback)('handleTriggerChange', {
552
558
  x: offsetX.value,
553
559
  y: offsetY.value
554
560
  })
@@ -0,0 +1,33 @@
1
+ import { AnimatedStyle } from 'react-native-reanimated'
2
+ import { useNavShared } from './useNavShared'
3
+ import { NavSharedContext, NavSharedValue } from './context'
4
+ import { useLayoutEffect, useMemo, useState } from 'react'
5
+ import { StyleProp } from 'react-native'
6
+ import { isAndroid } from './utils'
7
+
8
+ interface MpxNavContainerProps {
9
+ children?: React.ReactNode
10
+ }
11
+
12
+ export default function MpxNavContainer(props: MpxNavContainerProps) {
13
+ const [, setCustomNav] = useNavShared()
14
+
15
+ useLayoutEffect(() => {
16
+ if (!isAndroid) return
17
+ if (props.children) {
18
+ setCustomNav(props.children)
19
+ }
20
+
21
+ return () => {
22
+ setCustomNav(undefined)
23
+ }
24
+ }, [props.children])
25
+
26
+ return isAndroid ? null : props.children
27
+ }
28
+
29
+ export function NavSharedProvider({ children }: { children?: React.ReactNode }) {
30
+ const [customNav, setCustomNav] = useState()
31
+ const value = useMemo(() => ({ customNav, setCustomNav } as NavSharedValue), [customNav])
32
+ return <NavSharedContext.Provider value={value}>{children}</NavSharedContext.Provider>
33
+ }
@@ -38,7 +38,7 @@ import Animated, { useSharedValue, withTiming, useAnimatedStyle, runOnJS } from
38
38
  import { warn, hasOwn } from '@mpxjs/utils'
39
39
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
40
40
  import useNodesRef, { HandlerRef } from './useNodesRef'
41
- import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, GestureHandler, HIDDEN_STYLE } from './utils'
41
+ import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, GestureHandler, HIDDEN_STYLE, useRunOnJSCallback } from './utils'
42
42
  import { IntersectionObserverContext, ScrollViewContext } from './context'
43
43
  import Portal from './mpx-portal'
44
44
 
@@ -210,6 +210,27 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
210
210
  const { textStyle, innerStyle = {} } = splitStyle(normalStyle)
211
211
 
212
212
  const scrollViewRef = useRef<ScrollView>(null)
213
+
214
+ const propsRef = useRef(props)
215
+ const refresherStateRef = useRef({
216
+ hasRefresher,
217
+ refresherTriggered
218
+ })
219
+
220
+ propsRef.current = props
221
+ refresherStateRef.current = {
222
+ hasRefresher,
223
+ refresherTriggered
224
+ }
225
+
226
+ const runOnJSCallbackRef = useRef({
227
+ setEnableScroll,
228
+ setScrollBounces,
229
+ setRefreshing,
230
+ onRefresh
231
+ })
232
+ const runOnJSCallback = useRunOnJSCallback(runOnJSCallbackRef)
233
+
213
234
  useNodesRef(props, ref, scrollViewRef, {
214
235
  style: normalStyle,
215
236
  scrollOffset: scrollOptions,
@@ -518,6 +539,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
518
539
 
519
540
  // 处理刷新
520
541
  function onRefresh () {
542
+ const { hasRefresher, refresherTriggered } = refresherStateRef.current
521
543
  if (hasRefresher && refresherTriggered === undefined) {
522
544
  // 处理使用了自定义刷新组件,又没设置 refresherTriggered 的情况
523
545
  setRefreshing(true)
@@ -529,10 +551,10 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
529
551
  }
530
552
  }, 500)
531
553
  }
532
- const { bindrefresherrefresh } = props
554
+ const { bindrefresherrefresh } = propsRef.current
533
555
  bindrefresherrefresh &&
534
556
  bindrefresherrefresh(
535
- getCustomEvent('refresherrefresh', {}, { layoutRef }, props)
557
+ getCustomEvent('refresherrefresh', {}, { layoutRef }, propsRef.current)
536
558
  )
537
559
  }
538
560
 
@@ -587,7 +609,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
587
609
  'worklet'
588
610
  if (enableScrollValue.value !== newValue) {
589
611
  enableScrollValue.value = newValue
590
- runOnJS(setEnableScroll)(newValue)
612
+ runOnJS(runOnJSCallback)('setEnableScroll', newValue)
591
613
  }
592
614
  }
593
615
 
@@ -600,7 +622,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
600
622
  'worklet'
601
623
  if (bouncesValue.value !== newValue) {
602
624
  bouncesValue.value = newValue
603
- runOnJS(setScrollBounces)(newValue)
625
+ runOnJS(runOnJSCallback)('setScrollBounces', newValue)
604
626
  }
605
627
  }
606
628
 
@@ -649,19 +671,19 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
649
671
  if ((event.translationY > 0 && translateY.value < refresherThreshold) || event.translationY < 0) {
650
672
  translateY.value = withTiming(0)
651
673
  updateScrollState(true)
652
- runOnJS(setRefreshing)(false)
674
+ runOnJS(runOnJSCallback)('setRefreshing', false)
653
675
  } else {
654
676
  translateY.value = withTiming(refresherHeight.value)
655
677
  }
656
678
  } else if (event.translationY >= refresherHeight.value) {
657
679
  // 触发刷新
658
680
  translateY.value = withTiming(refresherHeight.value)
659
- runOnJS(onRefresh)()
681
+ runOnJS(runOnJSCallback)('onRefresh')
660
682
  } else {
661
683
  // 回弹
662
684
  translateY.value = withTiming(0)
663
685
  updateScrollState(true)
664
- runOnJS(setRefreshing)(false)
686
+ runOnJS(runOnJSCallback)('setRefreshing', false)
665
687
  }
666
688
  })
667
689
  .simultaneousWithExternalGesture(scrollViewRef)