@mpxjs/webpack-plugin 2.10.3 → 2.10.4

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 (103) 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 -3
  4. package/lib/platform/style/wx/index.js +23 -12
  5. package/lib/platform/template/wx/component-config/button.js +19 -2
  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/input.js +18 -3
  16. package/lib/platform/template/wx/component-config/label.js +4 -0
  17. package/lib/platform/template/wx/component-config/movable-area.js +7 -1
  18. package/lib/platform/template/wx/component-config/movable-view.js +12 -3
  19. package/lib/platform/template/wx/component-config/navigator.js +4 -0
  20. package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
  21. package/lib/platform/template/wx/component-config/picker-view.js +7 -1
  22. package/lib/platform/template/wx/component-config/picker.js +7 -1
  23. package/lib/platform/template/wx/component-config/radio-group.js +4 -0
  24. package/lib/platform/template/wx/component-config/radio.js +4 -0
  25. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  26. package/lib/platform/template/wx/component-config/root-portal.js +4 -0
  27. package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
  28. package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
  29. package/lib/platform/template/wx/component-config/swiper.js +12 -3
  30. package/lib/platform/template/wx/component-config/switch.js +4 -0
  31. package/lib/platform/template/wx/component-config/text.js +24 -3
  32. package/lib/platform/template/wx/component-config/textarea.js +17 -2
  33. package/lib/platform/template/wx/component-config/unsupported.js +7 -0
  34. package/lib/platform/template/wx/component-config/video.js +10 -2
  35. package/lib/platform/template/wx/component-config/view.js +11 -1
  36. package/lib/platform/template/wx/component-config/web-view.js +4 -0
  37. package/lib/platform/template/wx/index.js +42 -75
  38. package/lib/react/processScript.js +1 -18
  39. package/lib/runtime/components/react/dist/event.config.js +1 -0
  40. package/lib/runtime/components/react/dist/getInnerListeners.js +18 -7
  41. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -1
  42. package/lib/runtime/components/react/dist/mpx-inline-text.jsx +11 -0
  43. package/lib/runtime/components/react/dist/mpx-input.jsx +3 -6
  44. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +2 -2
  45. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +194 -68
  46. package/lib/runtime/components/react/dist/mpx-picker/dateData.js +17 -0
  47. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +178 -96
  48. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +79 -139
  49. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +190 -90
  50. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +60 -75
  51. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +100 -228
  52. package/lib/runtime/components/react/dist/{mpx-picker-view.jsx → mpx-picker-view/index.jsx} +3 -3
  53. package/lib/runtime/components/react/dist/{mpx-picker-view-column.jsx → mpx-picker-view-column/index.jsx} +64 -16
  54. package/lib/runtime/components/react/dist/{mpx-picker-view-column-item.jsx → mpx-picker-view-column/pickerViewColumnItem.jsx} +8 -5
  55. package/lib/runtime/components/react/dist/{pickerFaces.js → mpx-picker-view-column/pickerViewFaces.js} +6 -0
  56. package/lib/runtime/components/react/dist/mpx-popup/index.jsx +61 -0
  57. package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +92 -0
  58. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +192 -25
  59. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +8 -7
  60. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +11 -15
  61. package/lib/runtime/components/react/dist/mpx-video.jsx +3 -3
  62. package/lib/runtime/components/react/dist/mpx-web-view.jsx +7 -4
  63. package/lib/runtime/components/react/dist/utils.jsx +2 -1
  64. package/lib/runtime/components/react/event.config.ts +2 -0
  65. package/lib/runtime/components/react/getInnerListeners.ts +28 -25
  66. package/lib/runtime/components/react/mpx-canvas/index.tsx +2 -2
  67. package/lib/runtime/components/react/mpx-inline-text.tsx +18 -0
  68. package/lib/runtime/components/react/mpx-input.tsx +2 -6
  69. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +1 -1
  70. package/lib/runtime/components/react/mpx-picker/date.tsx +226 -69
  71. package/lib/runtime/components/react/mpx-picker/dateData.ts +22 -0
  72. package/lib/runtime/components/react/mpx-picker/index.tsx +239 -118
  73. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +96 -139
  74. package/lib/runtime/components/react/mpx-picker/region.tsx +217 -89
  75. package/lib/runtime/components/react/mpx-picker/selector.tsx +75 -80
  76. package/lib/runtime/components/react/mpx-picker/time.tsx +119 -236
  77. package/lib/runtime/components/react/mpx-picker/type.ts +85 -71
  78. package/lib/runtime/components/react/{mpx-picker-view.tsx → mpx-picker-view/index.tsx} +7 -7
  79. package/lib/runtime/components/react/{mpx-picker-view-column.tsx → mpx-picker-view-column/index.tsx} +70 -19
  80. package/lib/runtime/components/react/{mpx-picker-view-column-item.tsx → mpx-picker-view-column/pickerViewColumnItem.tsx} +8 -5
  81. package/lib/runtime/components/react/{pickerFaces.ts → mpx-picker-view-column/pickerViewFaces.ts} +7 -0
  82. package/lib/runtime/components/react/mpx-popup/index.tsx +86 -0
  83. package/lib/runtime/components/react/mpx-popup/popupBase.tsx +130 -0
  84. package/lib/runtime/components/react/mpx-scroll-view.tsx +249 -43
  85. package/lib/runtime/components/react/mpx-simple-text.tsx +10 -8
  86. package/lib/runtime/components/react/mpx-simple-view.tsx +11 -16
  87. package/lib/runtime/components/react/mpx-video.tsx +2 -2
  88. package/lib/runtime/components/react/mpx-web-view.tsx +7 -4
  89. package/lib/runtime/components/react/types/getInnerListeners.d.ts +5 -1
  90. package/lib/runtime/components/react/types/global.d.ts +1 -1
  91. package/lib/runtime/components/react/utils.tsx +3 -2
  92. package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
  93. package/lib/runtime/components/web/mpx-input.vue +1 -1
  94. package/lib/runtime/stringify.wxs +2 -2
  95. package/lib/template-compiler/compiler.js +8 -8
  96. package/lib/utils/env.js +1 -1
  97. package/package.json +4 -5
  98. /package/lib/runtime/components/react/dist/{pickerVIewContext.js → mpx-picker-view/pickerVIewContext.js} +0 -0
  99. /package/lib/runtime/components/react/dist/{pickerViewIndicator.jsx → mpx-picker-view-column/pickerViewIndicator.jsx} +0 -0
  100. /package/lib/runtime/components/react/dist/{pickerViewMask.jsx → mpx-picker-view-column/pickerViewMask.jsx} +0 -0
  101. /package/lib/runtime/components/react/{pickerVIewContext.ts → mpx-picker-view/pickerVIewContext.ts} +0 -0
  102. /package/lib/runtime/components/react/{pickerViewIndicator.tsx → mpx-picker-view-column/pickerViewIndicator.tsx} +0 -0
  103. /package/lib/runtime/components/react/{pickerViewMask.tsx → mpx-picker-view-column/pickerViewMask.tsx} +0 -0
@@ -0,0 +1,92 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
3
+ import { getWindowInfo } from '@mpxjs/api-proxy';
4
+ import { useUpdateEffect } from '../utils';
5
+ const windowInfo = getWindowInfo();
6
+ const bottom = windowInfo.screenHeight - windowInfo.safeArea.bottom;
7
+ const styles = StyleSheet.create({
8
+ mask: {
9
+ left: 0,
10
+ top: 0,
11
+ bottom: 0,
12
+ right: 0,
13
+ backgroundColor: 'rgba(0,0,0,0.6)',
14
+ position: 'absolute',
15
+ zIndex: 1000
16
+ },
17
+ content: {
18
+ backgroundColor: '#ffffff',
19
+ borderTopLeftRadius: 10,
20
+ borderTopRightRadius: 10,
21
+ position: 'absolute',
22
+ bottom: 0,
23
+ left: 0,
24
+ right: 0,
25
+ paddingBottom: bottom
26
+ },
27
+ buttonStyle: {
28
+ fontSize: 18,
29
+ paddingTop: 10,
30
+ paddingBottom: 10
31
+ }
32
+ });
33
+ const MASK_ON = 1;
34
+ const MASK_OFF = 0;
35
+ const MOVEOUT_HEIGHT = 330;
36
+ /**
37
+ * 类似微信 picker 弹窗的动画效果都可以复用此类容器
38
+ * 其他特定类型的弹窗容器组件可以在此基础上封装,或者扩展实现
39
+ */
40
+ const PopupBase = (props = {}) => {
41
+ const { children, hide = () => null, contentHeight = MOVEOUT_HEIGHT, visible = false } = props;
42
+ const fade = useSharedValue(MASK_OFF);
43
+ const slide = useSharedValue(contentHeight);
44
+ const animatedStylesMask = useAnimatedStyle(() => ({
45
+ opacity: fade.value
46
+ }));
47
+ const animatedStylesContent = useAnimatedStyle(() => ({
48
+ transform: [{ translateY: slide.value }]
49
+ }));
50
+ const showAimation = () => {
51
+ fade.value = withTiming(MASK_ON, {
52
+ easing: Easing.inOut(Easing.poly(3)),
53
+ duration: 300
54
+ });
55
+ slide.value = withTiming(0, {
56
+ easing: Easing.out(Easing.poly(3)),
57
+ duration: 300
58
+ });
59
+ };
60
+ const hideAnimation = () => {
61
+ fade.value = withTiming(MASK_OFF, {
62
+ easing: Easing.inOut(Easing.poly(3)),
63
+ duration: 300
64
+ });
65
+ slide.value = withTiming(contentHeight, {
66
+ easing: Easing.inOut(Easing.poly(3)),
67
+ duration: 300
68
+ });
69
+ };
70
+ useUpdateEffect(() => {
71
+ if (visible) {
72
+ showAimation();
73
+ }
74
+ else {
75
+ hideAnimation();
76
+ }
77
+ }, [visible]);
78
+ const preventMaskClick = (e) => {
79
+ e.stopPropagation();
80
+ };
81
+ return (<Animated.View onTouchEnd={hide} style={[
82
+ styles.mask,
83
+ animatedStylesMask,
84
+ { pointerEvents: visible ? 'auto' : 'none' }
85
+ ]}>
86
+ <Animated.View style={[styles.content, animatedStylesContent]} onTouchEnd={preventMaskClick}>
87
+ {children}
88
+ </Animated.View>
89
+ </Animated.View>);
90
+ };
91
+ PopupBase.displayName = 'MpxPopupBase';
92
+ export default PopupBase;
@@ -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,22 +31,29 @@
31
31
  * ✔ bindscrolltolower
32
32
  * ✔ bindscroll
33
33
  */
34
- import { ScrollView, RefreshControl } from 'react-native-gesture-handler';
35
- import { useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react';
36
- import { useAnimatedRef } from 'react-native-reanimated';
34
+ import { ScrollView, RefreshControl, Gesture, GestureDetector } from 'react-native-gesture-handler';
35
+ import { isValidElement, Children, useRef, useState, useEffect, forwardRef, useContext, useMemo, createElement } from 'react';
36
+ import Animated, { useAnimatedRef, useSharedValue, withTiming, useAnimatedStyle, runOnJS } from 'react-native-reanimated';
37
37
  import { warn } from '@mpxjs/utils';
38
38
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
39
39
  import useNodesRef from './useNodesRef';
40
- import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture } from './utils';
40
+ import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, HIDDEN_STYLE } from './utils';
41
41
  import { IntersectionObserverContext, ScrollViewContext } from './context';
42
42
  const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
43
43
  const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
44
- const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, 'scroll-event-throttle': scrollEventThrottle = 0, __selectRef } = props;
44
+ const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'refresher-threshold': refresherThreshold = 45, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, 'scroll-event-throttle': scrollEventThrottle = 0, __selectRef } = props;
45
45
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
46
46
  const waitForHandlers = flatGesture(waitFor);
47
- const [refreshing, setRefreshing] = useState(true);
48
47
  const snapScrollTop = useRef(0);
49
48
  const snapScrollLeft = useRef(0);
49
+ const [refreshing, setRefreshing] = useState(false);
50
+ const [enableScroll, setEnableScroll] = useState(true);
51
+ const enableScrollValue = useSharedValue(true);
52
+ const [scrollBounces, setScrollBounces] = useState(false);
53
+ const bouncesValue = useSharedValue(!!false);
54
+ const translateY = useSharedValue(0);
55
+ const isAtTop = useSharedValue(true);
56
+ const refresherHeight = useSharedValue(0);
50
57
  const scrollOptions = useRef({
51
58
  contentLength: 0,
52
59
  offset: 0,
@@ -59,6 +66,12 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
59
66
  const initialTimeout = useRef(null);
60
67
  const intersectionObservers = useContext(IntersectionObserverContext);
61
68
  const firstScrollIntoViewChange = useRef(false);
69
+ const refreshColor = {
70
+ black: ['#000'],
71
+ white: ['#fff']
72
+ };
73
+ const { refresherContent, otherContent } = getRefresherContent(props.children);
74
+ const hasRefresher = refresherContent && refresherEnabled;
62
75
  const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
63
76
  const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
64
77
  const scrollViewRef = useAnimatedRef();
@@ -82,6 +95,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
82
95
  };
83
96
  }, []);
84
97
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
98
+ const hasRefresherLayoutRef = useRef(false);
99
+ // layout 完成前先隐藏,避免安卓闪烁问题
100
+ const refresherLayoutStyle = useMemo(() => { return !hasRefresherLayoutRef.current ? HIDDEN_STYLE : {}; }, [hasRefresherLayoutRef.current]);
85
101
  const lastOffset = useRef(0);
86
102
  if (scrollX && scrollY) {
87
103
  warn('scroll-x and scroll-y cannot be set to true at the same time, Mpx will use the value of scroll-y as the criterion');
@@ -96,11 +112,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
96
112
  };
97
113
  }
98
114
  }, [scrollTop, scrollLeft]);
99
- useEffect(() => {
100
- if (refreshing !== refresherTriggered) {
101
- setRefreshing(!!refresherTriggered);
102
- }
103
- }, [refresherTriggered]);
104
115
  useEffect(() => {
105
116
  if (scrollIntoView && __selectRef) {
106
117
  if (!firstScrollIntoViewChange.current) {
@@ -112,6 +123,21 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
112
123
  }
113
124
  firstScrollIntoViewChange.current = true;
114
125
  }, [scrollIntoView]);
126
+ useEffect(() => {
127
+ if (refresherEnabled) {
128
+ setRefreshing(!!refresherTriggered);
129
+ if (!refresherContent)
130
+ return;
131
+ if (refresherTriggered) {
132
+ translateY.value = withTiming(refresherHeight.value);
133
+ resetScrollState(false);
134
+ }
135
+ else {
136
+ translateY.value = withTiming(0);
137
+ resetScrollState(true);
138
+ }
139
+ }
140
+ }, [refresherTriggered]);
115
141
  function scrollTo({ top = 0, left = 0, animated = false }) {
116
142
  scrollToOffset(left, top, animated);
117
143
  }
@@ -192,6 +218,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
192
218
  const { bindscroll } = props;
193
219
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
194
220
  const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize;
221
+ isAtTop.value = scrollTop <= 0;
195
222
  bindscroll &&
196
223
  bindscroll(getCustomEvent('scroll', e, {
197
224
  detail: {
@@ -215,6 +242,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
215
242
  const { bindscrollend } = props;
216
243
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
217
244
  const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize;
245
+ isAtTop.value = scrollTop <= 0;
218
246
  bindscrollend &&
219
247
  bindscrollend(getCustomEvent('scrollend', e, {
220
248
  detail: {
@@ -247,11 +275,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
247
275
  snapScrollTop.current = y;
248
276
  }
249
277
  }
250
- function onRefresh() {
251
- const { bindrefresherrefresh } = props;
252
- bindrefresherrefresh &&
253
- bindrefresherrefresh(getCustomEvent('refresherrefresh', {}, { layoutRef }, props));
254
- }
255
278
  function onScrollTouchStart(e) {
256
279
  const { bindtouchstart } = props;
257
280
  bindtouchstart && bindtouchstart(e);
@@ -302,6 +325,144 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
302
325
  hasCallScrollToUpper.current = false;
303
326
  onScrollDrag(e);
304
327
  }
328
+ // 处理刷新
329
+ function onRefresh() {
330
+ if (hasRefresher && refresherTriggered === undefined) {
331
+ // 处理使用了自定义刷新组件,又没设置 refresherTriggered 的情况
332
+ setRefreshing(true);
333
+ setTimeout(() => {
334
+ setRefreshing(false);
335
+ translateY.value = withTiming(0);
336
+ if (!enableScrollValue.value) {
337
+ resetScrollState(true);
338
+ }
339
+ }, 500);
340
+ }
341
+ const { bindrefresherrefresh } = props;
342
+ bindrefresherrefresh &&
343
+ bindrefresherrefresh(getCustomEvent('refresherrefresh', {}, { layoutRef }, props));
344
+ }
345
+ function getRefresherContent(children) {
346
+ let refresherContent = null;
347
+ const otherContent = [];
348
+ Children.forEach(children, (child) => {
349
+ if (isValidElement(child) && child.props.slot === 'refresher') {
350
+ refresherContent = child;
351
+ }
352
+ else {
353
+ otherContent.push(child);
354
+ }
355
+ });
356
+ return {
357
+ refresherContent,
358
+ otherContent
359
+ };
360
+ }
361
+ // 刷新控件的动画样式
362
+ const refresherAnimatedStyle = useAnimatedStyle(() => {
363
+ return {
364
+ position: 'absolute',
365
+ left: 0,
366
+ right: 0,
367
+ top: -refresherHeight.value,
368
+ transform: [{ translateY: Math.min(translateY.value, refresherHeight.value) }],
369
+ backgroundColor: refresherBackground || 'transparent'
370
+ };
371
+ });
372
+ // 内容区域的动画样式 - 只有内容区域需要下移
373
+ const contentAnimatedStyle = useAnimatedStyle(() => {
374
+ return {
375
+ transform: [{
376
+ translateY: translateY.value > refresherHeight.value
377
+ ? refresherHeight.value
378
+ : translateY.value
379
+ }]
380
+ };
381
+ });
382
+ function onRefresherLayout(e) {
383
+ const { height } = e.nativeEvent.layout;
384
+ refresherHeight.value = height;
385
+ hasRefresherLayoutRef.current = true;
386
+ }
387
+ function updateScrollState(newValue) {
388
+ 'worklet';
389
+ if (enableScrollValue.value !== newValue) {
390
+ enableScrollValue.value = newValue;
391
+ runOnJS(setEnableScroll)(newValue);
392
+ }
393
+ }
394
+ const resetScrollState = (value) => {
395
+ enableScrollValue.value = value;
396
+ setEnableScroll(value);
397
+ };
398
+ function updateBouncesState(newValue) {
399
+ 'worklet';
400
+ if (bouncesValue.value !== newValue) {
401
+ bouncesValue.value = newValue;
402
+ runOnJS(setScrollBounces)(newValue);
403
+ }
404
+ }
405
+ // 处理下拉刷新的手势
406
+ const panGesture = Gesture.Pan()
407
+ .onUpdate((event) => {
408
+ 'worklet';
409
+ if (enhanced && !!bounces) {
410
+ if (event.translationY > 0 && bouncesValue.value) {
411
+ updateBouncesState(false);
412
+ }
413
+ else if ((event.translationY < 0) && !bouncesValue.value) {
414
+ updateBouncesState(true);
415
+ }
416
+ }
417
+ if (translateY.value <= 0 && event.translationY < 0) {
418
+ // 滑动到顶再向上开启滚动
419
+ updateScrollState(true);
420
+ }
421
+ else if (event.translationY > 0 && isAtTop.value) {
422
+ // 滚动到顶再向下禁止滚动
423
+ updateScrollState(false);
424
+ }
425
+ // 禁止滚动后切换为滑动
426
+ if (!enableScrollValue.value && isAtTop.value) {
427
+ if (refreshing) {
428
+ // 从完全展开状态(refresherHeight.value)开始计算偏移
429
+ translateY.value = Math.max(0, Math.min(refresherHeight.value, refresherHeight.value + event.translationY));
430
+ }
431
+ else if (event.translationY > 0) {
432
+ // 非刷新状态下的下拉逻辑保持不变
433
+ translateY.value = Math.min(event.translationY * 0.6, refresherHeight.value);
434
+ }
435
+ }
436
+ })
437
+ .onEnd((event) => {
438
+ 'worklet';
439
+ if (enableScrollValue.value)
440
+ return;
441
+ if (refreshing) {
442
+ // 刷新状态下,根据滑动距离决定是否隐藏
443
+ // 如果向下滑动没超过 refresherThreshold,就完全隐藏,如果向上滑动完全隐藏
444
+ if ((event.translationY > 0 && translateY.value < refresherThreshold) || event.translationY < 0) {
445
+ translateY.value = withTiming(0);
446
+ updateScrollState(true);
447
+ runOnJS(setRefreshing)(false);
448
+ }
449
+ else {
450
+ translateY.value = withTiming(refresherHeight.value);
451
+ }
452
+ }
453
+ else if (event.translationY >= refresherHeight.value) {
454
+ // 触发刷新
455
+ translateY.value = withTiming(refresherHeight.value);
456
+ runOnJS(onRefresh)();
457
+ }
458
+ else {
459
+ // 回弹
460
+ translateY.value = withTiming(0);
461
+ updateScrollState(true);
462
+ runOnJS(setRefreshing)(false);
463
+ }
464
+ })
465
+ .simultaneousWithExternalGesture(scrollViewRef);
305
466
  const scrollAdditionalProps = extendObject({
306
467
  style: extendObject({}, innerStyle, layoutStyle),
307
468
  pinchGestureEnabled: false,
@@ -312,7 +473,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
312
473
  scrollsToTop: enableBackToTop,
313
474
  showsHorizontalScrollIndicator: scrollX && showScrollbar,
314
475
  showsVerticalScrollIndicator: scrollY && showScrollbar,
315
- scrollEnabled: scrollX || scrollY,
476
+ scrollEnabled: !enableScroll ? false : !!(scrollX || scrollY),
477
+ bounces: false,
316
478
  ref: scrollViewRef,
317
479
  onScroll: onScroll,
318
480
  onContentSizeChange: onContentSizeChange,
@@ -325,7 +487,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
325
487
  }, (simultaneousHandlers ? { simultaneousHandlers } : {}), (waitForHandlers ? { waitFor: waitForHandlers } : {}), layoutProps);
326
488
  if (enhanced) {
327
489
  Object.assign(scrollAdditionalProps, {
328
- bounces,
490
+ bounces: hasRefresher ? scrollBounces : !!bounces,
329
491
  pagingEnabled
330
492
  });
331
493
  }
@@ -356,17 +518,21 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
356
518
  'bindscrolltolower',
357
519
  'bindrefresherrefresh'
358
520
  ], { layoutRef });
359
- const refreshColor = {
360
- black: ['#000'],
361
- white: ['#fff']
362
- };
363
- return createElement(ScrollView, extendObject({}, innerProps, {
521
+ const withRefresherScrollView = createElement(GestureDetector, { gesture: panGesture }, createElement(ScrollView, innerProps, createElement(Animated.View, { style: [refresherAnimatedStyle, refresherLayoutStyle], onLayout: onRefresherLayout }, refresherContent), createElement(Animated.View, { style: contentAnimatedStyle }, createElement(ScrollViewContext.Provider, { value: contextValue }, wrapChildren(extendObject({}, props, { children: otherContent }), {
522
+ hasVarDec,
523
+ varContext: varContextRef.current,
524
+ textStyle,
525
+ textProps
526
+ })))));
527
+ const commonScrollView = createElement(ScrollView, extendObject(innerProps, {
364
528
  refreshControl: refresherEnabled
365
529
  ? createElement(RefreshControl, extendObject({
366
530
  progressBackgroundColor: refresherBackground,
367
531
  refreshing: refreshing,
368
532
  onRefresh: onRefresh
369
- }, (refresherDefaultStyle && refresherDefaultStyle !== 'none' ? { colors: refreshColor[refresherDefaultStyle] } : null)))
533
+ }, refresherDefaultStyle && refresherDefaultStyle !== 'none'
534
+ ? { colors: refreshColor[refresherDefaultStyle] }
535
+ : {}))
370
536
  : undefined
371
537
  }), createElement(ScrollViewContext.Provider, { value: contextValue }, wrapChildren(props, {
372
538
  hasVarDec,
@@ -374,6 +540,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
374
540
  textStyle,
375
541
  textProps
376
542
  })));
543
+ return hasRefresher ? withRefresherScrollView : commonScrollView;
377
544
  });
378
545
  _ScrollView.displayName = 'MpxScrollView';
379
546
  export default _ScrollView;
@@ -1,11 +1,12 @@
1
1
  import { Text } from 'react-native';
2
2
  import { createElement } from 'react';
3
- import { extendObject } from './utils';
4
- const _Text2 = (props) => {
5
- const { allowFontScaling = false } = props;
6
- return createElement(Text, extendObject({}, props, {
3
+ import useInnerProps from './getInnerListeners';
4
+ const SimpleText = (props) => {
5
+ const { allowFontScaling = false, children } = props;
6
+ const innerProps = useInnerProps(props, {
7
7
  allowFontScaling
8
- }));
8
+ }, []);
9
+ return createElement(Text, innerProps, children);
9
10
  };
10
- _Text2.displayName = 'MpxSimpleText';
11
- export default _Text2;
11
+ SimpleText.displayName = 'MpxSimpleText';
12
+ export default SimpleText;
@@ -1,22 +1,18 @@
1
1
  import { View } from 'react-native';
2
- import { createElement, forwardRef, useRef } from 'react';
3
- import useNodesRef from './useNodesRef';
4
- import { extendObject, splitProps, splitStyle, wrapChildren } from './utils';
5
- const _View2 = forwardRef((simpleViewProps, ref) => {
6
- const nodeRef = useRef(null);
2
+ import { createElement } from 'react';
3
+ import { splitProps, splitStyle, wrapChildren } from './utils';
4
+ import useInnerProps from './getInnerListeners';
5
+ const SimpleView = (simpleViewProps) => {
7
6
  const { textProps, innerProps: props = {} } = splitProps(simpleViewProps);
8
7
  const { textStyle, innerStyle = {} } = splitStyle(props.style || {});
9
- useNodesRef(props, ref, nodeRef, {
10
- style: innerStyle || {}
11
- });
12
- return createElement(View, extendObject({}, props, {
13
- style: innerStyle,
14
- ref: nodeRef
15
- }), wrapChildren(props, {
8
+ const innerProps = useInnerProps(props, {
9
+ style: innerStyle
10
+ }, []);
11
+ return createElement(View, innerProps, wrapChildren(props, {
16
12
  hasVarDec: false,
17
13
  textStyle: textStyle,
18
14
  textProps
19
15
  }));
20
- });
21
- _View2.displayName = 'MpxSimpleView';
22
- export default _View2;
16
+ };
17
+ SimpleView.displayName = 'MpxSimpleView';
18
+ export default SimpleView;
@@ -64,7 +64,7 @@
64
64
  */
65
65
  import { useRef, forwardRef, createElement } from 'react';
66
66
  import Video, { DRMType } from 'react-native-video';
67
- import { StyleSheet, View, Platform } from 'react-native';
67
+ import { StyleSheet, View } from 'react-native';
68
68
  import { splitProps, useTransformStyle, useLayout, extendObject } from './utils';
69
69
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
70
70
  import useNodesRef from './useNodesRef';
@@ -132,7 +132,7 @@ const MpxVideo = forwardRef((videoProps, ref) => {
132
132
  // 手动拖拽进度条场景,android 可以触发,ios 不可以
133
133
  bindseekcomplete(getCustomEvent('seekcomplete', {}, {
134
134
  detail: {
135
- position: Platform.OS === 'android' ? seekTime * 1000 : seekTime
135
+ position: __mpx_mode__ !== 'ios' ? seekTime * 1000 : seekTime
136
136
  },
137
137
  layoutRef
138
138
  }, propsRef.current));
@@ -202,7 +202,7 @@ const MpxVideo = forwardRef((videoProps, ref) => {
202
202
  if (isDrm) {
203
203
  source.drm = {
204
204
  type: DRMType.FAIRPLAY,
205
- certificateUrl: Platform.OS === 'android' ? provisionUrl : certificateUrl,
205
+ certificateUrl: __mpx_mode__ !== 'ios' ? provisionUrl : certificateUrl,
206
206
  licenseServer: licenseUrl
207
207
  };
208
208
  }
@@ -75,7 +75,10 @@ const _WebView = forwardRef((props, ref) => {
75
75
  };
76
76
  const navigation = useNavigation();
77
77
  useEffect(() => {
78
- const beforeRemoveSubscription = navigation?.addListener?.('beforeRemove', beforeRemoveHandle);
78
+ let beforeRemoveSubscription;
79
+ if (__mpx_mode__ !== 'ios') {
80
+ beforeRemoveSubscription = navigation?.addListener?.('beforeRemove', beforeRemoveHandle);
81
+ }
79
82
  return () => {
80
83
  if (isFunction(beforeRemoveSubscription)) {
81
84
  beforeRemoveSubscription();
@@ -89,7 +92,7 @@ const _WebView = forwardRef((props, ref) => {
89
92
  return null;
90
93
  }
91
94
  const _reload = function () {
92
- if (__mpx_mode__ === 'android') {
95
+ if (__mpx_mode__ !== 'ios') {
93
96
  fristLoaded.current = false; // 安卓需要重新设置
94
97
  }
95
98
  setPageLoadErr(false);
@@ -133,7 +136,7 @@ const _WebView = forwardRef((props, ref) => {
133
136
  }
134
137
  };
135
138
  const _onLoadProgress = function (event) {
136
- if (__mpx_mode__ === 'android') {
139
+ if (__mpx_mode__ !== 'ios') {
137
140
  canGoBack.current = event.nativeEvent.canGoBack;
138
141
  }
139
142
  };
@@ -251,7 +254,7 @@ const _WebView = forwardRef((props, ref) => {
251
254
  }
252
255
  };
253
256
  const onLoadEnd = function (res) {
254
- if (__mpx_mode__ === 'android') {
257
+ if (__mpx_mode__ !== 'ios') {
255
258
  res.persist();
256
259
  setTimeout(() => {
257
260
  onLoadEndHandle(res);
@@ -19,6 +19,7 @@ export const HIDDEN_STYLE = {
19
19
  };
20
20
  export const isIOS = __mpx_mode__ === 'ios';
21
21
  export const isAndroid = __mpx_mode__ === 'android';
22
+ export const isHarmony = __mpx_mode__ === 'harmony';
22
23
  const varDecRegExp = /^--/;
23
24
  const varUseRegExp = /var\(/;
24
25
  const unoVarDecRegExp = /^--un-/;
@@ -80,7 +81,7 @@ export function isText(ele) {
80
81
  if (isValidElement(ele)) {
81
82
  const displayName = ele.type?.displayName;
82
83
  const isCustomText = ele.type?.isCustomText;
83
- return displayName === 'MpxText' || displayName === 'MpxSimpleText' || displayName === 'Text' || !!isCustomText;
84
+ return displayName === 'MpxText' || displayName === 'MpxSimpleText' || displayName === 'MpxInlineText' || displayName === 'Text' || !!isCustomText;
84
85
  }
85
86
  return false;
86
87
  }
@@ -4,6 +4,8 @@ interface EventConfig {
4
4
 
5
5
  export const TAP_EVENTS = ['bindtap', 'catchtap', 'capture-bindtap', 'capture-catchtap']
6
6
 
7
+ export const LONGPRESS_EVENTS = ['bindlongpress', 'catchlongpress', 'capture-bindlongpress', 'capture-catchlongpress']
8
+
7
9
  const eventConfigMap: { [key: string]: { bitFlag: string; events: string[] } } = {
8
10
  bindtap: { bitFlag: '0', events: ['onTouchStart', 'onTouchMove', 'onTouchEnd'] },
9
11
  bindlongpress: { bitFlag: '1', events: ['onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'] },