@mpxjs/webpack-plugin 2.10.3 → 2.10.4-beta.11

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 (155) hide show
  1. package/lib/config.js +2 -1
  2. package/lib/index.js +1 -1
  3. package/lib/platform/json/wx/index.js +6 -4
  4. package/lib/platform/style/wx/index.js +42 -30
  5. package/lib/platform/template/wx/component-config/button.js +20 -3
  6. package/lib/platform/template/wx/component-config/canvas.js +4 -0
  7. package/lib/platform/template/wx/component-config/checkbox-group.js +4 -0
  8. package/lib/platform/template/wx/component-config/checkbox.js +4 -0
  9. package/lib/platform/template/wx/component-config/cover-image.js +7 -1
  10. package/lib/platform/template/wx/component-config/cover-view.js +4 -0
  11. package/lib/platform/template/wx/component-config/fix-component-name.js +3 -2
  12. package/lib/platform/template/wx/component-config/form.js +7 -1
  13. package/lib/platform/template/wx/component-config/icon.js +4 -0
  14. package/lib/platform/template/wx/component-config/image.js +7 -1
  15. package/lib/platform/template/wx/component-config/index.js +5 -1
  16. package/lib/platform/template/wx/component-config/input.js +19 -4
  17. package/lib/platform/template/wx/component-config/label.js +4 -0
  18. package/lib/platform/template/wx/component-config/movable-area.js +7 -1
  19. package/lib/platform/template/wx/component-config/movable-view.js +12 -3
  20. package/lib/platform/template/wx/component-config/navigator.js +4 -0
  21. package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
  22. package/lib/platform/template/wx/component-config/picker-view.js +7 -1
  23. package/lib/platform/template/wx/component-config/picker.js +7 -1
  24. package/lib/platform/template/wx/component-config/radio-group.js +4 -0
  25. package/lib/platform/template/wx/component-config/radio.js +4 -0
  26. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  27. package/lib/platform/template/wx/component-config/root-portal.js +4 -0
  28. package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
  29. package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
  30. package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
  31. package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
  32. package/lib/platform/template/wx/component-config/swiper.js +12 -3
  33. package/lib/platform/template/wx/component-config/switch.js +4 -0
  34. package/lib/platform/template/wx/component-config/text.js +24 -3
  35. package/lib/platform/template/wx/component-config/textarea.js +17 -2
  36. package/lib/platform/template/wx/component-config/unsupported.js +7 -0
  37. package/lib/platform/template/wx/component-config/video.js +10 -2
  38. package/lib/platform/template/wx/component-config/view.js +11 -1
  39. package/lib/platform/template/wx/component-config/web-view.js +4 -0
  40. package/lib/platform/template/wx/index.js +42 -75
  41. package/lib/react/processJSON.js +7 -6
  42. package/lib/react/processScript.js +1 -18
  43. package/lib/runtime/components/react/context.ts +12 -3
  44. package/lib/runtime/components/react/dist/context.js +4 -1
  45. package/lib/runtime/components/react/dist/event.config.js +0 -1
  46. package/lib/runtime/components/react/dist/getInnerListeners.js +127 -142
  47. package/lib/runtime/components/react/dist/mpx-button.jsx +4 -5
  48. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +4 -5
  49. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -2
  50. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +2 -3
  51. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -2
  52. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
  53. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  54. package/lib/runtime/components/react/dist/mpx-inline-text.jsx +11 -0
  55. package/lib/runtime/components/react/dist/mpx-input.jsx +20 -17
  56. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +24 -31
  57. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -3
  58. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +2 -2
  59. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +1 -1
  60. package/lib/runtime/components/react/dist/mpx-navigator.jsx +11 -3
  61. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +194 -68
  62. package/lib/runtime/components/react/dist/mpx-picker/dateData.js +17 -0
  63. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +180 -98
  64. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +79 -139
  65. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +190 -90
  66. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +60 -75
  67. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +100 -228
  68. package/lib/runtime/components/react/dist/{mpx-picker-view.jsx → mpx-picker-view/index.jsx} +5 -6
  69. package/lib/runtime/components/react/dist/{mpx-picker-view-column.jsx → mpx-picker-view-column/index.jsx} +66 -18
  70. package/lib/runtime/components/react/dist/{mpx-picker-view-column-item.jsx → mpx-picker-view-column/pickerViewColumnItem.jsx} +8 -5
  71. package/lib/runtime/components/react/dist/{pickerFaces.js → mpx-picker-view-column/pickerViewFaces.js} +6 -0
  72. package/lib/runtime/components/react/dist/mpx-popup/index.jsx +61 -0
  73. package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +92 -0
  74. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -2
  75. package/lib/runtime/components/react/dist/mpx-radio.jsx +2 -3
  76. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +2 -2
  77. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +207 -29
  78. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +7 -5
  79. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +11 -15
  80. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +115 -0
  81. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  82. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +4 -5
  83. package/lib/runtime/components/react/dist/mpx-swiper.jsx +9 -9
  84. package/lib/runtime/components/react/dist/mpx-switch.jsx +3 -5
  85. package/lib/runtime/components/react/dist/mpx-text.jsx +4 -7
  86. package/lib/runtime/components/react/dist/mpx-video.jsx +5 -5
  87. package/lib/runtime/components/react/dist/mpx-view.jsx +23 -9
  88. package/lib/runtime/components/react/dist/mpx-web-view.jsx +16 -13
  89. package/lib/runtime/components/react/dist/useAnimationHooks.js +26 -4
  90. package/lib/runtime/components/react/dist/utils.jsx +14 -2
  91. package/lib/runtime/components/react/event.config.ts +1 -6
  92. package/lib/runtime/components/react/getInnerListeners.ts +148 -191
  93. package/lib/runtime/components/react/mpx-button.tsx +7 -7
  94. package/lib/runtime/components/react/mpx-canvas/index.tsx +25 -17
  95. package/lib/runtime/components/react/mpx-checkbox-group.tsx +4 -3
  96. package/lib/runtime/components/react/mpx-checkbox.tsx +8 -9
  97. package/lib/runtime/components/react/mpx-form.tsx +25 -19
  98. package/lib/runtime/components/react/mpx-icon/index.tsx +4 -3
  99. package/lib/runtime/components/react/mpx-image.tsx +4 -3
  100. package/lib/runtime/components/react/mpx-inline-text.tsx +18 -0
  101. package/lib/runtime/components/react/mpx-input.tsx +24 -21
  102. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +31 -42
  103. package/lib/runtime/components/react/mpx-label.tsx +4 -5
  104. package/lib/runtime/components/react/mpx-movable-area.tsx +22 -13
  105. package/lib/runtime/components/react/mpx-movable-view.tsx +47 -40
  106. package/lib/runtime/components/react/mpx-navigator.tsx +4 -6
  107. package/lib/runtime/components/react/mpx-picker/date.tsx +226 -69
  108. package/lib/runtime/components/react/mpx-picker/dateData.ts +22 -0
  109. package/lib/runtime/components/react/mpx-picker/index.tsx +242 -118
  110. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +96 -139
  111. package/lib/runtime/components/react/mpx-picker/region.tsx +217 -89
  112. package/lib/runtime/components/react/mpx-picker/selector.tsx +75 -80
  113. package/lib/runtime/components/react/mpx-picker/time.tsx +119 -236
  114. package/lib/runtime/components/react/mpx-picker/type.ts +85 -71
  115. package/lib/runtime/components/react/{mpx-picker-view.tsx → mpx-picker-view/index.tsx} +24 -21
  116. package/lib/runtime/components/react/{mpx-picker-view-column.tsx → mpx-picker-view-column/index.tsx} +72 -21
  117. package/lib/runtime/components/react/{mpx-picker-view-column-item.tsx → mpx-picker-view-column/pickerViewColumnItem.tsx} +8 -5
  118. package/lib/runtime/components/react/{pickerFaces.ts → mpx-picker-view-column/pickerViewFaces.ts} +7 -0
  119. package/lib/runtime/components/react/mpx-popup/index.tsx +86 -0
  120. package/lib/runtime/components/react/mpx-popup/popupBase.tsx +130 -0
  121. package/lib/runtime/components/react/mpx-radio-group.tsx +4 -3
  122. package/lib/runtime/components/react/mpx-radio.tsx +8 -9
  123. package/lib/runtime/components/react/mpx-rich-text/index.tsx +15 -6
  124. package/lib/runtime/components/react/mpx-scroll-view.tsx +326 -96
  125. package/lib/runtime/components/react/mpx-simple-text.tsx +17 -8
  126. package/lib/runtime/components/react/mpx-simple-view.tsx +17 -16
  127. package/lib/runtime/components/react/mpx-sticky-header.tsx +179 -0
  128. package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
  129. package/lib/runtime/components/react/mpx-swiper-item.tsx +31 -24
  130. package/lib/runtime/components/react/mpx-swiper.tsx +67 -61
  131. package/lib/runtime/components/react/mpx-switch.tsx +19 -14
  132. package/lib/runtime/components/react/mpx-text.tsx +16 -13
  133. package/lib/runtime/components/react/mpx-video.tsx +36 -35
  134. package/lib/runtime/components/react/mpx-view.tsx +41 -17
  135. package/lib/runtime/components/react/mpx-web-view.tsx +15 -12
  136. package/lib/runtime/components/react/types/getInnerListeners.d.ts +69 -35
  137. package/lib/runtime/components/react/types/global.d.ts +1 -1
  138. package/lib/runtime/components/react/useAnimationHooks.ts +29 -9
  139. package/lib/runtime/components/react/utils.tsx +15 -3
  140. package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
  141. package/lib/runtime/components/web/mpx-input.vue +1 -1
  142. package/lib/runtime/components/web/mpx-scroll-view.vue +21 -4
  143. package/lib/runtime/components/web/mpx-sticky-header.vue +91 -0
  144. package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
  145. package/lib/runtime/stringify.wxs +2 -2
  146. package/lib/template-compiler/compiler.js +8 -8
  147. package/lib/utils/env.js +1 -1
  148. package/package.json +4 -5
  149. package/LICENSE +0 -433
  150. /package/lib/runtime/components/react/dist/{pickerVIewContext.js → mpx-picker-view/pickerVIewContext.js} +0 -0
  151. /package/lib/runtime/components/react/dist/{pickerViewIndicator.jsx → mpx-picker-view-column/pickerViewIndicator.jsx} +0 -0
  152. /package/lib/runtime/components/react/dist/{pickerViewMask.jsx → mpx-picker-view-column/pickerViewMask.jsx} +0 -0
  153. /package/lib/runtime/components/react/{pickerVIewContext.ts → mpx-picker-view/pickerVIewContext.ts} +0 -0
  154. /package/lib/runtime/components/react/{pickerViewIndicator.tsx → mpx-picker-view-column/pickerViewIndicator.tsx} +0 -0
  155. /package/lib/runtime/components/react/{pickerViewMask.tsx → mpx-picker-view-column/pickerViewMask.tsx} +0 -0
@@ -10,7 +10,7 @@
10
10
  * ✔ enable-back-to-top
11
11
  * ✘ enable-passive
12
12
  * ✔ refresher-enabled
13
- * refresher-threshold
13
+ * refresher-threshold(仅自定义下拉节点样式支持)
14
14
  * ✔ refresher-default-style(仅 android 支持)
15
15
  * ✔ refresher-background(仅 android 支持)
16
16
  * ✔ refresher-triggered
@@ -31,14 +31,14 @@
31
31
  * ✔ bindscrolltolower
32
32
  * ✔ bindscroll
33
33
  */
34
- import { ScrollView, RefreshControl } from 'react-native-gesture-handler'
35
- import { View, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle } from 'react-native'
36
- import { JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react'
37
- import { useAnimatedRef } from 'react-native-reanimated'
34
+ import { ScrollView, RefreshControl, Gesture, GestureDetector } from 'react-native-gesture-handler'
35
+ import { View, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle, Animated as RNAnimated } from 'react-native'
36
+ import { isValidElement, Children, JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext, useMemo, createElement } from 'react'
37
+ import Animated, { useAnimatedRef, useSharedValue, withTiming, useAnimatedStyle, runOnJS } from 'react-native-reanimated'
38
38
  import { warn } 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 } from './utils'
41
+ import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, GestureHandler, HIDDEN_STYLE } from './utils'
42
42
  import { IntersectionObserverContext, ScrollViewContext } from './context'
43
43
 
44
44
  interface ScrollViewProps {
@@ -58,6 +58,7 @@ interface ScrollViewProps {
58
58
  'refresher-enabled'?: boolean;
59
59
  'refresher-default-style'?: 'black' | 'white' | 'none';
60
60
  'refresher-background'?: string;
61
+ 'refresher-threshold'?: number;
61
62
  'scroll-top'?: number;
62
63
  'scroll-left'?: number;
63
64
  'enable-offset'?: boolean;
@@ -68,6 +69,7 @@ interface ScrollViewProps {
68
69
  'parent-font-size'?: number;
69
70
  'parent-width'?: number;
70
71
  'parent-height'?: number;
72
+ 'enable-sticky'?: boolean;
71
73
  'wait-for'?: Array<GestureHandler>;
72
74
  'simultaneous-handlers'?: Array<GestureHandler>;
73
75
  'scroll-event-throttle'?:number;
@@ -85,27 +87,29 @@ interface ScrollViewProps {
85
87
  __selectRef?: (selector: string, nodeType: 'node' | 'component', all?: boolean) => HandlerRef<any, any>
86
88
  }
87
89
  type ScrollAdditionalProps = {
88
- pinchGestureEnabled: boolean;
89
- horizontal: boolean;
90
- onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
91
- onContentSizeChange: (width: number, height: number) => void;
92
- onLayout?: (event: LayoutChangeEvent) => void;
93
- scrollEventThrottle: number;
94
- scrollsToTop: boolean;
95
- showsHorizontalScrollIndicator: boolean;
96
- showsVerticalScrollIndicator: boolean;
97
- scrollEnabled: boolean;
98
- ref: RefObject<ScrollView>;
99
- bounces?: boolean;
100
- pagingEnabled?: boolean;
101
- style?: ViewStyle;
102
- bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void;
103
- bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent>) => void;
104
- bindtouchend?: (event: NativeSyntheticEvent<TouchEvent>) => void;
105
- onScrollBeginDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
106
- onScrollEndDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
107
- onMomentumScrollEnd?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
108
- };
90
+ pinchGestureEnabled: boolean
91
+ horizontal: boolean
92
+ onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
93
+ onContentSizeChange: (width: number, height: number) => void
94
+ onLayout?: (event: LayoutChangeEvent) => void
95
+ scrollsToTop: boolean
96
+ showsHorizontalScrollIndicator: boolean
97
+ showsVerticalScrollIndicator: boolean
98
+ scrollEnabled: boolean
99
+ ref: RefObject<ScrollView>
100
+ bounces?: boolean
101
+ pagingEnabled?: boolean
102
+ style?: ViewStyle
103
+ bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent>) => void
104
+ bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent>) => void
105
+ bindtouchend?: (event: NativeSyntheticEvent<TouchEvent>) => void
106
+ onScrollBeginDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
107
+ onScrollEndDrag?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
108
+ onMomentumScrollEnd?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
109
+ }
110
+
111
+ const AnimatedScrollView = RNAnimated.createAnimatedComponent(ScrollView) as React.ComponentType<any>
112
+
109
113
  const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, ScrollViewProps>((scrollViewProps: ScrollViewProps = {}, ref): JSX.Element => {
110
114
  const { textProps, innerProps: props = {} } = splitProps(scrollViewProps)
111
115
  const {
@@ -129,6 +133,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
129
133
  'refresher-enabled': refresherEnabled,
130
134
  'refresher-default-style': refresherDefaultStyle,
131
135
  'refresher-background': refresherBackground,
136
+ 'refresher-threshold': refresherThreshold = 45,
132
137
  'show-scrollbar': showScrollbar = true,
133
138
  'scroll-into-view': scrollIntoView = '',
134
139
  'scroll-top': scrollTop = 0,
@@ -141,18 +146,31 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
141
146
  'parent-height': parentHeight,
142
147
  'simultaneous-handlers': originSimultaneousHandlers,
143
148
  'wait-for': waitFor,
149
+ 'enable-sticky': enableSticky,
144
150
  'scroll-event-throttle': scrollEventThrottle = 0,
145
151
  __selectRef
146
152
  } = props
147
153
 
154
+ const scrollOffset = useRef(new RNAnimated.Value(0)).current
155
+
148
156
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers)
149
157
  const waitForHandlers = flatGesture(waitFor)
150
158
 
151
- const [refreshing, setRefreshing] = useState(true)
152
-
153
159
  const snapScrollTop = useRef(0)
154
160
  const snapScrollLeft = useRef(0)
155
161
 
162
+ const [refreshing, setRefreshing] = useState(false)
163
+
164
+ const [enableScroll, setEnableScroll] = useState(true)
165
+ const enableScrollValue = useSharedValue(true)
166
+
167
+ const [scrollBounces, setScrollBounces] = useState(false)
168
+ const bouncesValue = useSharedValue(!!false)
169
+
170
+ const translateY = useSharedValue(0)
171
+ const isAtTop = useSharedValue(true)
172
+ const refresherHeight = useSharedValue(0)
173
+
156
174
  const scrollOptions = useRef({
157
175
  contentLength: 0,
158
176
  offset: 0,
@@ -168,6 +186,14 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
168
186
 
169
187
  const firstScrollIntoViewChange = useRef<boolean>(false)
170
188
 
189
+ const refreshColor = {
190
+ black: ['#000'],
191
+ white: ['#fff']
192
+ }
193
+
194
+ const { refresherContent, otherContent } = getRefresherContent(props.children)
195
+ const hasRefresher = refresherContent && refresherEnabled
196
+
171
197
  const {
172
198
  normalStyle,
173
199
  hasVarDec,
@@ -195,14 +221,19 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
195
221
  gestureRef: scrollViewRef
196
222
  })
197
223
 
224
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
225
+
198
226
  const contextValue = useMemo(() => {
199
227
  return {
200
- gestureRef: scrollViewRef
228
+ gestureRef: scrollViewRef,
229
+ scrollOffset
201
230
  }
202
231
  }, [])
203
232
 
204
- const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
233
+ const hasRefresherLayoutRef = useRef(false)
205
234
 
235
+ // layout 完成前先隐藏,避免安卓闪烁问题
236
+ const refresherLayoutStyle = useMemo(() => { return !hasRefresherLayoutRef.current ? HIDDEN_STYLE : {} }, [hasRefresherLayoutRef.current])
206
237
  const lastOffset = useRef(0)
207
238
 
208
239
  if (scrollX && scrollY) {
@@ -222,12 +253,6 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
222
253
  }
223
254
  }, [scrollTop, scrollLeft])
224
255
 
225
- useEffect(() => {
226
- if (refreshing !== refresherTriggered) {
227
- setRefreshing(!!refresherTriggered)
228
- }
229
- }, [refresherTriggered])
230
-
231
256
  useEffect(() => {
232
257
  if (scrollIntoView && __selectRef) {
233
258
  if (!firstScrollIntoViewChange.current) {
@@ -239,7 +264,23 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
239
264
  firstScrollIntoViewChange.current = true
240
265
  }, [scrollIntoView])
241
266
 
242
- function scrollTo ({ top = 0, left = 0, animated = false } : { top?: number; left?: number; animated?: boolean }) {
267
+ useEffect(() => {
268
+ if (refresherEnabled) {
269
+ setRefreshing(!!refresherTriggered)
270
+
271
+ if (!refresherContent) return
272
+
273
+ if (refresherTriggered) {
274
+ translateY.value = withTiming(refresherHeight.value)
275
+ resetScrollState(false)
276
+ } else {
277
+ translateY.value = withTiming(0)
278
+ resetScrollState(true)
279
+ }
280
+ }
281
+ }, [refresherTriggered])
282
+
283
+ function scrollTo ({ top = 0, left = 0, animated = false }: { top?: number; left?: number; animated?: boolean }) {
243
284
  scrollToOffset(left, top, animated)
244
285
  }
245
286
 
@@ -249,7 +290,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
249
290
  const { nodeRef } = refs.getNodeInstance()
250
291
  nodeRef.current?.measureLayout(
251
292
  scrollViewRef.current,
252
- (left: number, top:number) => {
293
+ (left: number, top: number) => {
253
294
  scrollToOffset(left, top)
254
295
  }
255
296
  )
@@ -333,6 +374,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
333
374
  const { bindscroll } = props
334
375
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset
335
376
  const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize
377
+ isAtTop.value = scrollTop <= 0
336
378
  bindscroll &&
337
379
  bindscroll(
338
380
  getCustomEvent('scroll', e, {
@@ -359,6 +401,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
359
401
  const { bindscrollend } = props
360
402
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset
361
403
  const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize
404
+ isAtTop.value = scrollTop <= 0
362
405
  bindscrollend &&
363
406
  bindscrollend(
364
407
  getCustomEvent('scrollend', e, {
@@ -394,14 +437,6 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
394
437
  }
395
438
  }
396
439
 
397
- function onRefresh () {
398
- const { bindrefresherrefresh } = props
399
- bindrefresherrefresh &&
400
- bindrefresherrefresh(
401
- getCustomEvent('refresherrefresh', {}, { layoutRef }, props)
402
- )
403
- }
404
-
405
440
  function onScrollTouchStart (e: NativeSyntheticEvent<TouchEvent>) {
406
441
  const { bindtouchstart } = props
407
442
  bindtouchstart && bindtouchstart(e)
@@ -456,12 +491,172 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
456
491
  updateIntersection()
457
492
  }
458
493
 
494
+ const scrollHandler = RNAnimated.event(
495
+ [{ nativeEvent: { contentOffset: { y: scrollOffset } } }],
496
+ {
497
+ useNativeDriver: true,
498
+ listener: (event: NativeSyntheticEvent<NativeScrollEvent>) => {
499
+ onScroll(event)
500
+ }
501
+ }
502
+ )
503
+
459
504
  function onScrollDragStart (e: NativeSyntheticEvent<NativeScrollEvent>) {
460
505
  hasCallScrollToLower.current = false
461
506
  hasCallScrollToUpper.current = false
462
507
  onScrollDrag(e)
463
508
  }
464
509
 
510
+ // 处理刷新
511
+ function onRefresh () {
512
+ if (hasRefresher && refresherTriggered === undefined) {
513
+ // 处理使用了自定义刷新组件,又没设置 refresherTriggered 的情况
514
+ setRefreshing(true)
515
+ setTimeout(() => {
516
+ setRefreshing(false)
517
+ translateY.value = withTiming(0)
518
+ if (!enableScrollValue.value) {
519
+ resetScrollState(true)
520
+ }
521
+ }, 500)
522
+ }
523
+ const { bindrefresherrefresh } = props
524
+ bindrefresherrefresh &&
525
+ bindrefresherrefresh(
526
+ getCustomEvent('refresherrefresh', {}, { layoutRef }, props)
527
+ )
528
+ }
529
+
530
+ function getRefresherContent (children: ReactNode) {
531
+ let refresherContent = null
532
+ const otherContent: ReactNode[] = []
533
+
534
+ Children.forEach(children, (child) => {
535
+ if (isValidElement(child) && child.props.slot === 'refresher') {
536
+ refresherContent = child
537
+ } else {
538
+ otherContent.push(child)
539
+ }
540
+ })
541
+
542
+ return {
543
+ refresherContent,
544
+ otherContent
545
+ }
546
+ }
547
+
548
+ // 刷新控件的动画样式
549
+ const refresherAnimatedStyle = useAnimatedStyle(() => {
550
+ return {
551
+ position: 'absolute',
552
+ left: 0,
553
+ right: 0,
554
+ top: -refresherHeight.value, // 初始隐藏在顶部
555
+ transform: [{ translateY: Math.min(translateY.value, refresherHeight.value) }],
556
+ backgroundColor: refresherBackground || 'transparent'
557
+ }
558
+ })
559
+
560
+ // 内容区域的动画样式 - 只有内容区域需要下移
561
+ const contentAnimatedStyle = useAnimatedStyle(() => {
562
+ return {
563
+ transform: [{
564
+ translateY: translateY.value > refresherHeight.value
565
+ ? refresherHeight.value
566
+ : translateY.value
567
+ }]
568
+ }
569
+ })
570
+
571
+ function onRefresherLayout (e: LayoutChangeEvent) {
572
+ const { height } = e.nativeEvent.layout
573
+ refresherHeight.value = height
574
+ hasRefresherLayoutRef.current = true
575
+ }
576
+
577
+ function updateScrollState (newValue: boolean) {
578
+ 'worklet'
579
+ if (enableScrollValue.value !== newValue) {
580
+ enableScrollValue.value = newValue
581
+ runOnJS(setEnableScroll)(newValue)
582
+ }
583
+ }
584
+
585
+ const resetScrollState = (value: boolean) => {
586
+ enableScrollValue.value = value
587
+ setEnableScroll(value)
588
+ }
589
+
590
+ function updateBouncesState (newValue: boolean) {
591
+ 'worklet'
592
+ if (bouncesValue.value !== newValue) {
593
+ bouncesValue.value = newValue
594
+ runOnJS(setScrollBounces)(newValue)
595
+ }
596
+ }
597
+
598
+ // 处理下拉刷新的手势
599
+ const panGesture = Gesture.Pan()
600
+ .onUpdate((event) => {
601
+ 'worklet'
602
+ if (enhanced && !!bounces) {
603
+ if (event.translationY > 0 && bouncesValue.value) {
604
+ updateBouncesState(false)
605
+ } else if ((event.translationY < 0) && !bouncesValue.value) {
606
+ updateBouncesState(true)
607
+ }
608
+ }
609
+
610
+ if (translateY.value <= 0 && event.translationY < 0) {
611
+ // 滑动到顶再向上开启滚动
612
+ updateScrollState(true)
613
+ } else if (event.translationY > 0 && isAtTop.value) {
614
+ // 滚动到顶再向下禁止滚动
615
+ updateScrollState(false)
616
+ }
617
+ // 禁止滚动后切换为滑动
618
+ if (!enableScrollValue.value && isAtTop.value) {
619
+ if (refreshing) {
620
+ // 从完全展开状态(refresherHeight.value)开始计算偏移
621
+ translateY.value = Math.max(
622
+ 0,
623
+ Math.min(
624
+ refresherHeight.value,
625
+ refresherHeight.value + event.translationY
626
+ )
627
+ )
628
+ } else if (event.translationY > 0) {
629
+ // 非刷新状态下的下拉逻辑保持不变
630
+ translateY.value = Math.min(event.translationY * 0.6, refresherHeight.value)
631
+ }
632
+ }
633
+ })
634
+ .onEnd((event) => {
635
+ 'worklet'
636
+ if (enableScrollValue.value) return
637
+ if (refreshing) {
638
+ // 刷新状态下,根据滑动距离决定是否隐藏
639
+ // 如果向下滑动没超过 refresherThreshold,就完全隐藏,如果向上滑动完全隐藏
640
+ if ((event.translationY > 0 && translateY.value < refresherThreshold) || event.translationY < 0) {
641
+ translateY.value = withTiming(0)
642
+ updateScrollState(true)
643
+ runOnJS(setRefreshing)(false)
644
+ } else {
645
+ translateY.value = withTiming(refresherHeight.value)
646
+ }
647
+ } else if (event.translationY >= refresherHeight.value) {
648
+ // 触发刷新
649
+ translateY.value = withTiming(refresherHeight.value)
650
+ runOnJS(onRefresh)()
651
+ } else {
652
+ // 回弹
653
+ translateY.value = withTiming(0)
654
+ updateScrollState(true)
655
+ runOnJS(setRefreshing)(false)
656
+ }
657
+ })
658
+ .simultaneousWithExternalGesture(scrollViewRef)
659
+
465
660
  const scrollAdditionalProps: ScrollAdditionalProps = extendObject(
466
661
  {
467
662
  style: extendObject({}, innerStyle, layoutStyle),
@@ -473,9 +668,10 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
473
668
  scrollsToTop: enableBackToTop,
474
669
  showsHorizontalScrollIndicator: scrollX && showScrollbar,
475
670
  showsVerticalScrollIndicator: scrollY && showScrollbar,
476
- scrollEnabled: scrollX || scrollY,
671
+ scrollEnabled: !enableScroll ? false : !!(scrollX || scrollY),
672
+ bounces: false,
477
673
  ref: scrollViewRef,
478
- onScroll: onScroll,
674
+ onScroll: enableSticky ? scrollHandler : onScroll,
479
675
  onContentSizeChange: onContentSizeChange,
480
676
  bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) && onScrollTouchStart,
481
677
  bindtouchmove: ((enhanced && binddragging) || bindtouchmove) && onScrollTouchMove,
@@ -491,68 +687,102 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
491
687
 
492
688
  if (enhanced) {
493
689
  Object.assign(scrollAdditionalProps, {
494
- bounces,
690
+ bounces: hasRefresher ? scrollBounces : !!bounces,
495
691
  pagingEnabled
496
692
  })
497
693
  }
498
694
 
499
- const innerProps = useInnerProps(props, scrollAdditionalProps, [
500
- 'id',
501
- 'scroll-x',
502
- 'scroll-y',
503
- 'enable-back-to-top',
504
- 'enable-trigger-intersection-observer',
505
- 'paging-enabled',
506
- 'show-scrollbar',
507
- 'upper-threshold',
508
- 'lower-threshold',
509
- 'scroll-top',
510
- 'scroll-left',
511
- 'scroll-with-animation',
512
- 'refresher-triggered',
513
- 'refresher-enabled',
514
- 'refresher-default-style',
515
- 'refresher-background',
516
- 'children',
517
- 'enhanced',
518
- 'binddragstart',
519
- 'binddragging',
520
- 'binddragend',
521
- 'bindscroll',
522
- 'bindscrolltoupper',
523
- 'bindscrolltolower',
524
- 'bindrefresherrefresh'
525
- ], { layoutRef })
526
-
527
- const refreshColor = {
528
- black: ['#000'],
529
- white: ['#fff']
530
- }
695
+ const innerProps = useInnerProps(
696
+ extendObject(
697
+ {},
698
+ props,
699
+ scrollAdditionalProps
700
+ ),
701
+ [
702
+ 'id',
703
+ 'scroll-x',
704
+ 'scroll-y',
705
+ 'enable-back-to-top',
706
+ 'enable-trigger-intersection-observer',
707
+ 'paging-enabled',
708
+ 'show-scrollbar',
709
+ 'upper-threshold',
710
+ 'lower-threshold',
711
+ 'scroll-top',
712
+ 'scroll-left',
713
+ 'scroll-with-animation',
714
+ 'refresher-triggered',
715
+ 'refresher-enabled',
716
+ 'refresher-default-style',
717
+ 'refresher-background',
718
+ 'children',
719
+ 'enhanced',
720
+ 'binddragstart',
721
+ 'binddragging',
722
+ 'binddragend',
723
+ 'bindscroll',
724
+ 'bindscrolltoupper',
725
+ 'bindscrolltolower',
726
+ 'bindrefresherrefresh'
727
+ ], { layoutRef })
728
+
729
+ const ScrollViewComponent = enableSticky ? AnimatedScrollView : ScrollView
730
+
731
+ const withRefresherScrollView = createElement(
732
+ GestureDetector,
733
+ { gesture: panGesture },
734
+ createElement(
735
+ ScrollViewComponent,
736
+ innerProps,
737
+ createElement(
738
+ Animated.View,
739
+ { style: [refresherAnimatedStyle, refresherLayoutStyle], onLayout: onRefresherLayout },
740
+ refresherContent
741
+ ),
742
+ createElement(
743
+ Animated.View,
744
+ { style: contentAnimatedStyle },
745
+ createElement(
746
+ ScrollViewContext.Provider,
747
+ { value: contextValue },
748
+ wrapChildren(
749
+ extendObject({}, props, { children: otherContent }),
750
+ {
751
+ hasVarDec,
752
+ varContext: varContextRef.current,
753
+ textStyle,
754
+ textProps
755
+ }
756
+ )
757
+ )
758
+ )
759
+ )
760
+ )
531
761
 
532
- return createElement(
533
- ScrollView,
762
+ const commonScrollView = createElement(
763
+ ScrollViewComponent,
534
764
  extendObject({}, innerProps, {
535
765
  refreshControl: refresherEnabled
536
766
  ? createElement(RefreshControl, extendObject({
537
767
  progressBackgroundColor: refresherBackground,
538
768
  refreshing: refreshing,
539
769
  onRefresh: onRefresh
540
- }, (refresherDefaultStyle && refresherDefaultStyle !== 'none' ? { colors: refreshColor[refresherDefaultStyle] } : null)))
770
+ }, refresherDefaultStyle && refresherDefaultStyle !== 'none'
771
+ ? { colors: refreshColor[refresherDefaultStyle] }
772
+ : {}))
541
773
  : undefined
542
774
  }),
543
- createElement(ScrollViewContext.Provider,
544
- { value: contextValue },
545
- wrapChildren(
546
- props,
547
- {
548
- hasVarDec,
549
- varContext: varContextRef.current,
550
- textStyle,
551
- textProps
552
- }
553
- )
775
+ createElement(ScrollViewContext.Provider, { value: contextValue },
776
+ wrapChildren(props, {
777
+ hasVarDec,
778
+ varContext: varContextRef.current,
779
+ textStyle,
780
+ textProps
781
+ })
554
782
  )
555
783
  )
784
+
785
+ return hasRefresher ? withRefresherScrollView : commonScrollView
556
786
  })
557
787
 
558
788
  _ScrollView.displayName = 'MpxScrollView'
@@ -1,18 +1,27 @@
1
1
  import { Text, TextProps } from 'react-native'
2
2
  import { JSX, createElement } from 'react'
3
-
3
+ import useInnerProps from './getInnerListeners'
4
4
  import { extendObject } from './utils'
5
5
 
6
- const _Text2 = (props: TextProps): JSX.Element => {
6
+ const SimpleText = (props: TextProps): JSX.Element => {
7
7
  const {
8
- allowFontScaling = false
8
+ allowFontScaling = false,
9
+ children
9
10
  } = props
10
11
 
11
- return createElement(Text, extendObject({}, props, {
12
- allowFontScaling
13
- }))
12
+ const innerProps = useInnerProps(
13
+ extendObject(
14
+ {},
15
+ props,
16
+ {
17
+ allowFontScaling
18
+ }
19
+ )
20
+ )
21
+
22
+ return createElement(Text, innerProps, children)
14
23
  }
15
24
 
16
- _Text2.displayName = 'MpxSimpleText'
25
+ SimpleText.displayName = 'MpxSimpleText'
17
26
 
18
- export default _Text2
27
+ export default SimpleText
@@ -1,23 +1,24 @@
1
1
  import { View, ViewProps, TextStyle } from 'react-native'
2
- import { createElement, forwardRef, useRef } from 'react'
3
- import useNodesRef, { HandlerRef } from './useNodesRef'
4
- import { extendObject, splitProps, splitStyle, wrapChildren } from './utils'
5
-
6
- const _View2 = forwardRef<HandlerRef<View, ViewProps>, ViewProps>((simpleViewProps: ViewProps, ref) => {
7
- const nodeRef = useRef(null)
2
+ import { createElement } from 'react'
3
+ import { splitProps, splitStyle, wrapChildren, extendObject } from './utils'
4
+ import useInnerProps from './getInnerListeners'
8
5
 
6
+ const SimpleView = (simpleViewProps: ViewProps): JSX.Element => {
9
7
  const { textProps, innerProps: props = {} } = splitProps(simpleViewProps)
10
8
 
11
9
  const { textStyle, innerStyle = {} } = splitStyle(props.style || {})
12
10
 
13
- useNodesRef(props, ref, nodeRef, {
14
- style: innerStyle || {}
15
- })
11
+ const innerProps = useInnerProps(
12
+ extendObject(
13
+ {},
14
+ props,
15
+ {
16
+ style: innerStyle
17
+ }
18
+ )
19
+ )
16
20
 
17
- return createElement(View, extendObject({}, props, {
18
- style: innerStyle,
19
- ref: nodeRef
20
- }), wrapChildren(
21
+ return createElement(View, innerProps, wrapChildren(
21
22
  props,
22
23
  {
23
24
  hasVarDec: false,
@@ -25,8 +26,8 @@ const _View2 = forwardRef<HandlerRef<View, ViewProps>, ViewProps>((simpleViewPro
25
26
  textProps
26
27
  }
27
28
  ))
28
- })
29
+ }
29
30
 
30
- _View2.displayName = 'MpxSimpleView'
31
+ SimpleView.displayName = 'MpxSimpleView'
31
32
 
32
- export default _View2
33
+ export default SimpleView