@mpxjs/webpack-plugin 2.10.4-beta.2 → 2.10.4-beta.20

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 (88) hide show
  1. package/lib/parser.js +1 -1
  2. package/lib/platform/json/wx/index.js +0 -1
  3. package/lib/platform/style/wx/index.js +22 -21
  4. package/lib/platform/template/wx/component-config/button.js +1 -1
  5. package/lib/platform/template/wx/component-config/index.js +5 -1
  6. package/lib/platform/template/wx/component-config/input.js +1 -1
  7. package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
  8. package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
  9. package/lib/react/processJSON.js +7 -6
  10. package/lib/runtime/components/react/context.ts +12 -3
  11. package/lib/runtime/components/react/dist/context.js +4 -1
  12. package/lib/runtime/components/react/dist/event.config.js +0 -2
  13. package/lib/runtime/components/react/dist/getInnerListeners.js +127 -153
  14. package/lib/runtime/components/react/dist/mpx-button.jsx +4 -5
  15. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +3 -4
  16. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -2
  17. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +2 -3
  18. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -2
  19. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
  20. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  21. package/lib/runtime/components/react/dist/mpx-input.jsx +8 -5
  22. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +23 -30
  23. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -3
  24. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +2 -2
  25. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +1 -1
  26. package/lib/runtime/components/react/dist/mpx-navigator.jsx +11 -3
  27. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +2 -2
  28. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +2 -3
  29. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +3 -3
  30. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -2
  31. package/lib/runtime/components/react/dist/mpx-radio.jsx +2 -3
  32. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +2 -2
  33. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +32 -16
  34. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +3 -2
  35. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +3 -3
  36. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +115 -0
  37. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  38. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +5 -6
  39. package/lib/runtime/components/react/dist/mpx-swiper.jsx +99 -37
  40. package/lib/runtime/components/react/dist/mpx-switch.jsx +3 -5
  41. package/lib/runtime/components/react/dist/mpx-text.jsx +4 -7
  42. package/lib/runtime/components/react/dist/mpx-video.jsx +2 -2
  43. package/lib/runtime/components/react/dist/mpx-view.jsx +23 -9
  44. package/lib/runtime/components/react/dist/mpx-web-view.jsx +13 -13
  45. package/lib/runtime/components/react/dist/useAnimationHooks.js +26 -4
  46. package/lib/runtime/components/react/dist/utils.jsx +12 -1
  47. package/lib/runtime/components/react/event.config.ts +1 -8
  48. package/lib/runtime/components/react/getInnerListeners.ts +146 -192
  49. package/lib/runtime/components/react/mpx-button.tsx +7 -7
  50. package/lib/runtime/components/react/mpx-canvas/index.tsx +23 -15
  51. package/lib/runtime/components/react/mpx-checkbox-group.tsx +4 -3
  52. package/lib/runtime/components/react/mpx-checkbox.tsx +8 -9
  53. package/lib/runtime/components/react/mpx-form.tsx +25 -19
  54. package/lib/runtime/components/react/mpx-icon/index.tsx +4 -3
  55. package/lib/runtime/components/react/mpx-image.tsx +4 -3
  56. package/lib/runtime/components/react/mpx-input.tsx +14 -9
  57. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +31 -42
  58. package/lib/runtime/components/react/mpx-label.tsx +4 -5
  59. package/lib/runtime/components/react/mpx-movable-area.tsx +22 -13
  60. package/lib/runtime/components/react/mpx-movable-view.tsx +47 -40
  61. package/lib/runtime/components/react/mpx-navigator.tsx +4 -6
  62. package/lib/runtime/components/react/mpx-picker/index.tsx +7 -4
  63. package/lib/runtime/components/react/mpx-picker-view/index.tsx +17 -14
  64. package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +3 -3
  65. package/lib/runtime/components/react/mpx-radio-group.tsx +4 -3
  66. package/lib/runtime/components/react/mpx-radio.tsx +8 -9
  67. package/lib/runtime/components/react/mpx-rich-text/index.tsx +15 -6
  68. package/lib/runtime/components/react/mpx-scroll-view.tsx +97 -66
  69. package/lib/runtime/components/react/mpx-simple-text.tsx +10 -3
  70. package/lib/runtime/components/react/mpx-simple-view.tsx +10 -4
  71. package/lib/runtime/components/react/mpx-sticky-header.tsx +179 -0
  72. package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
  73. package/lib/runtime/components/react/mpx-swiper-item.tsx +32 -25
  74. package/lib/runtime/components/react/mpx-swiper.tsx +166 -88
  75. package/lib/runtime/components/react/mpx-switch.tsx +19 -14
  76. package/lib/runtime/components/react/mpx-text.tsx +16 -13
  77. package/lib/runtime/components/react/mpx-video.tsx +34 -33
  78. package/lib/runtime/components/react/mpx-view.tsx +41 -17
  79. package/lib/runtime/components/react/mpx-web-view.tsx +12 -12
  80. package/lib/runtime/components/react/types/getInnerListeners.d.ts +65 -35
  81. package/lib/runtime/components/react/useAnimationHooks.ts +29 -9
  82. package/lib/runtime/components/react/utils.tsx +12 -1
  83. package/lib/runtime/components/web/mpx-scroll-view.vue +21 -4
  84. package/lib/runtime/components/web/mpx-sticky-header.vue +91 -0
  85. package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
  86. package/lib/script-setup-compiler/index.js +27 -5
  87. package/lib/template-compiler/compiler.js +3 -2
  88. package/package.json +1 -1
@@ -0,0 +1,115 @@
1
+ import { useEffect, useRef, useContext, forwardRef, useMemo, createElement, useId } from 'react';
2
+ import { Animated, StyleSheet, useAnimatedValue } from 'react-native';
3
+ import { ScrollViewContext, StickyContext } from './context';
4
+ import useNodesRef from './useNodesRef';
5
+ import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
6
+ import { error } from '@mpxjs/utils';
7
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
8
+ const _StickyHeader = forwardRef((stickyHeaderProps = {}, ref) => {
9
+ const { textProps, innerProps: props = {} } = splitProps(stickyHeaderProps);
10
+ const { style, bindstickontopchange, padding = [0, 0, 0, 0], 'offset-top': offsetTop = 0, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
11
+ const scrollViewContext = useContext(ScrollViewContext);
12
+ const stickyContext = useContext(StickyContext);
13
+ const { scrollOffset } = scrollViewContext;
14
+ const { registerStickyHeader, unregisterStickyHeader } = stickyContext;
15
+ const headerRef = useRef(null);
16
+ const isStickOnTopRef = useRef(false);
17
+ const id = useId();
18
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
19
+ const { layoutRef, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: headerRef, onLayout });
20
+ const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
21
+ const headerTopAnimated = useAnimatedValue(0);
22
+ // harmony animatedValue 不支持通过 _value 访问
23
+ const headerTopRef = useRef(0);
24
+ useEffect(() => {
25
+ registerStickyHeader({ key: id, updatePosition });
26
+ return () => {
27
+ unregisterStickyHeader(id);
28
+ };
29
+ }, []);
30
+ function updatePosition() {
31
+ if (headerRef.current) {
32
+ const scrollViewRef = scrollViewContext.gestureRef;
33
+ if (scrollViewRef && scrollViewRef.current) {
34
+ headerRef.current.measureLayout(scrollViewRef.current, (left, top) => {
35
+ Animated.timing(headerTopAnimated, {
36
+ toValue: top,
37
+ duration: 0,
38
+ useNativeDriver: true
39
+ }).start();
40
+ headerTopRef.current = top;
41
+ });
42
+ }
43
+ else {
44
+ error('StickyHeader measureLayout error: scrollViewRef is not a valid native component reference');
45
+ }
46
+ }
47
+ }
48
+ function onLayout(e) {
49
+ updatePosition();
50
+ }
51
+ useNodesRef(props, ref, headerRef, {
52
+ style: normalStyle
53
+ });
54
+ useEffect(() => {
55
+ if (!bindstickontopchange)
56
+ return;
57
+ const listener = scrollOffset.addListener((state) => {
58
+ const currentScrollValue = state.value;
59
+ const newIsStickOnTop = currentScrollValue > headerTopRef.current;
60
+ if (newIsStickOnTop !== isStickOnTopRef.current) {
61
+ isStickOnTopRef.current = newIsStickOnTop;
62
+ bindstickontopchange(getCustomEvent('stickontopchange', {}, {
63
+ detail: {
64
+ isStickOnTop: newIsStickOnTop
65
+ },
66
+ layoutRef
67
+ }, props));
68
+ }
69
+ });
70
+ return () => {
71
+ scrollOffset.removeListener(listener);
72
+ };
73
+ }, []);
74
+ const animatedStyle = useMemo(() => {
75
+ const translateY = Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
76
+ inputRange: [0, 1],
77
+ outputRange: [0, 1],
78
+ extrapolateLeft: 'clamp',
79
+ extrapolateRight: 'extend'
80
+ });
81
+ const finalTranslateY = offsetTop === 0
82
+ ? translateY
83
+ : Animated.add(translateY, Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
84
+ inputRange: [0, 1],
85
+ outputRange: [0, offsetTop],
86
+ extrapolate: 'clamp'
87
+ }));
88
+ return {
89
+ transform: [{ translateY: finalTranslateY }]
90
+ };
91
+ }, [scrollOffset, headerTopAnimated, offsetTop]);
92
+ const innerProps = useInnerProps(extendObject({}, props, {
93
+ ref: headerRef,
94
+ style: extendObject({}, styles.content, innerStyle, animatedStyle, {
95
+ paddingTop: padding[0] || 0,
96
+ paddingRight: padding[1] || 0,
97
+ paddingBottom: padding[2] || 0,
98
+ paddingLeft: padding[3] || 0
99
+ })
100
+ }, layoutProps), [], { layoutRef });
101
+ return (createElement(Animated.View, innerProps, wrapChildren(props, {
102
+ hasVarDec,
103
+ varContext: varContextRef.current,
104
+ textStyle,
105
+ textProps
106
+ })));
107
+ });
108
+ const styles = StyleSheet.create({
109
+ content: {
110
+ width: '100%',
111
+ zIndex: 10
112
+ }
113
+ });
114
+ _StickyHeader.displayName = 'MpxStickyHeader';
115
+ export default _StickyHeader;
@@ -0,0 +1,45 @@
1
+ import { useRef, forwardRef, createElement, useCallback, useMemo } from 'react';
2
+ import { View } from 'react-native';
3
+ import useNodesRef from './useNodesRef';
4
+ import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
5
+ import { StickyContext } from './context';
6
+ import useInnerProps from './getInnerListeners';
7
+ const _StickySection = forwardRef((stickySectionProps = {}, ref) => {
8
+ const { textProps, innerProps: props = {} } = splitProps(stickySectionProps);
9
+ const { style, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
10
+ const sectionRef = useRef(null);
11
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
12
+ const { layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: sectionRef, onLayout });
13
+ const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
14
+ const stickyHeaders = useRef(new Map());
15
+ const registerStickyHeader = useCallback((item) => {
16
+ stickyHeaders.current.set(item.id, item);
17
+ }, []);
18
+ const unregisterStickyHeader = useCallback((id) => {
19
+ stickyHeaders.current.delete(id);
20
+ }, []);
21
+ const contextValue = useMemo(() => ({
22
+ registerStickyHeader,
23
+ unregisterStickyHeader
24
+ }), []);
25
+ useNodesRef(props, ref, sectionRef, {
26
+ style: normalStyle
27
+ });
28
+ function onLayout() {
29
+ stickyHeaders.current.forEach(item => {
30
+ item.updatePosition();
31
+ });
32
+ }
33
+ const innerProps = useInnerProps(extendObject({}, props, {
34
+ style: extendObject(innerStyle, layoutStyle),
35
+ ref: sectionRef
36
+ }, layoutProps), [], { layoutRef });
37
+ return (createElement(View, innerProps, createElement(StickyContext.Provider, { value: contextValue }, wrapChildren(props, {
38
+ hasVarDec,
39
+ varContext: varContextRef.current,
40
+ textStyle,
41
+ textProps
42
+ }))));
43
+ });
44
+ _StickySection.displayName = 'MpxStickySection';
45
+ export default _StickySection;
@@ -2,7 +2,7 @@ import Animated, { useAnimatedStyle, interpolate } from 'react-native-reanimated
2
2
  import { forwardRef, useRef, useContext } from 'react';
3
3
  import useInnerProps from './getInnerListeners';
4
4
  import useNodesRef from './useNodesRef'; // 引入辅助函数
5
- import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils';
5
+ import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout, extendObject, isHarmony } from './utils';
6
6
  import { SwiperContext } from './context';
7
7
  const _SwiperItem = forwardRef((props, ref) => {
8
8
  const { 'enable-var': enableVar, 'external-var-context': externalVarContext, style, customStyle, itemIndex } = props;
@@ -21,16 +21,15 @@ const _SwiperItem = forwardRef((props, ref) => {
21
21
  const {
22
22
  // 存储layout布局信息
23
23
  layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef });
24
- const innerProps = useInnerProps(props, {
25
- ref: nodeRef,
26
- ...layoutProps
27
- }, [
24
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
25
+ ref: nodeRef
26
+ }), [
28
27
  'children',
29
28
  'enable-offset',
30
29
  'style'
31
30
  ], { layoutRef });
32
31
  const itemAnimatedStyle = useAnimatedStyle(() => {
33
- if (!step.value)
32
+ if (!step.value && !isHarmony)
34
33
  return {};
35
34
  const inputRange = [step.value, 0];
36
35
  const outputRange = [0.7, 1];
@@ -4,7 +4,7 @@ import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, runOnJS
4
4
  import React, { forwardRef, useRef, useEffect, useMemo } from 'react';
5
5
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
6
6
  import useNodesRef from './useNodesRef'; // 引入辅助函数
7
- import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from './utils';
7
+ import { useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren, extendObject, flatGesture } from './utils';
8
8
  import { SwiperContext } from './context';
9
9
  /**
10
10
  * 默认的Style类型
@@ -70,11 +70,13 @@ const easeMap = {
70
70
  easeInOutCubic: Easing.inOut(Easing.cubic)
71
71
  };
72
72
  const SwiperWrapper = forwardRef((props, ref) => {
73
- const { 'indicator-dots': showsPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, style = {}, autoplay = false, circular = false } = props;
73
+ const { 'indicator-dots': showsPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, autoplay = false, circular = false, disableGesture = false } = props;
74
74
  const easeingFunc = props['easing-function'] || 'default';
75
75
  const easeDuration = props.duration || 500;
76
76
  const horizontal = props.vertical !== undefined ? !props.vertical : true;
77
77
  const nodeRef = useRef(null);
78
+ // 手势协同gesture 1.0
79
+ const swiperGestureRef = useRef();
78
80
  useNodesRef(props, ref, nodeRef, {});
79
81
  // 计算transfrom之类的
80
82
  const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, {
@@ -119,14 +121,35 @@ const SwiperWrapper = forwardRef((props, ref) => {
119
121
  const moveTranstion = useSharedValue(0);
120
122
  // 记录从onBegin 到 onTouchesUp 的时间
121
123
  const moveTime = useSharedValue(0);
124
+ // 记录从onBegin 到 onTouchesCancelled 另外一个方向移动的距离
125
+ const anotherDirectionMove = useSharedValue(0);
126
+ // 另一个方向的
127
+ const anotherAbso = 'absolute' + (dir === 'x' ? 'y' : 'x').toUpperCase();
122
128
  const timerId = useRef(0);
123
129
  const intervalTimer = props.interval || 500;
130
+ const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
131
+ const waitForHandlers = flatGesture(waitFor);
132
+ // 判断gesture手势是否需要协同处理、等待手势失败响应
133
+ const gestureSwitch = useRef(false);
134
+ // 初始化上一次的手势
135
+ const prevSimultaneousHandlersRef = useRef(originSimultaneousHandlers || []);
136
+ const prevWaitForHandlersRef = useRef(waitFor || []);
137
+ const hasSimultaneousHandlersChanged = prevSimultaneousHandlersRef.current.length !== (originSimultaneousHandlers?.length || 0) ||
138
+ (originSimultaneousHandlers || []).some((handler, index) => handler !== prevSimultaneousHandlersRef.current[index]);
139
+ const hasWaitForHandlersChanged = prevWaitForHandlersRef.current.length !== (waitFor?.length || 0) ||
140
+ (waitFor || []).some((handler, index) => handler !== prevWaitForHandlersRef.current[index]);
141
+ if (hasSimultaneousHandlersChanged || hasWaitForHandlersChanged) {
142
+ gestureSwitch.current = !gestureSwitch.current;
143
+ }
144
+ // 存储上一次的手势
145
+ prevSimultaneousHandlersRef.current = originSimultaneousHandlers || [];
146
+ prevWaitForHandlersRef.current = waitFor || [];
124
147
  const {
125
148
  // 存储layout布局信息
126
149
  layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef, onLayout: onWrapperLayout });
127
- const innerProps = useInnerProps(props, {
150
+ const innerProps = useInnerProps(extendObject({}, props, {
128
151
  ref: nodeRef
129
- }, [
152
+ }), [
130
153
  'style',
131
154
  'indicator-dots',
132
155
  'indicator-color',
@@ -187,8 +210,8 @@ const SwiperWrapper = forwardRef((props, ref) => {
187
210
  dotAnimatedStyle
188
211
  ]}/>
189
212
  {dots}
190
- </View>
191
- </View>);
213
+ </View>
214
+ </View>);
192
215
  }
193
216
  function renderItems() {
194
217
  const intLen = children.length;
@@ -384,7 +407,11 @@ const SwiperWrapper = forwardRef((props, ref) => {
384
407
  }
385
408
  }, [children.length]);
386
409
  useEffect(() => {
387
- updateCurrent(props.current || 0, step.value);
410
+ // 1. 如果用户在touch的过程中, 外部更新了current以外部为准(小程序表现)
411
+ // 2. 手指滑动过程中更新索引,外部会把current再穿进来,导致offset直接更新了
412
+ if (props.current !== currentIndex.value) {
413
+ updateCurrent(props.current || 0, step.value);
414
+ }
388
415
  }, [props.current]);
389
416
  useEffect(() => {
390
417
  autoplayShared.value = autoplay;
@@ -447,20 +474,26 @@ const SwiperWrapper = forwardRef((props, ref) => {
447
474
  targetOffset: -moveToTargetPos
448
475
  };
449
476
  }
450
- function canMove(eventData) {
477
+ function checkUnCircular(eventData) {
451
478
  'worklet';
452
479
  const { translation } = eventData;
453
480
  const currentOffset = Math.abs(offset.value);
454
- if (!circularShared.value) {
455
- if (translation < 0) {
456
- return currentOffset < step.value * (childrenLength.value - 1);
457
- }
458
- else {
459
- return currentOffset > 0;
460
- }
481
+ // 向右滑动swiper
482
+ if (translation < 0) {
483
+ const boundaryOffset = step.value * (childrenLength.value - 1);
484
+ const gestureMovePos = Math.abs(translation) + currentOffset;
485
+ return {
486
+ // 防止快速连续向右滑动时,手势移动的距离 当前的offset超出边界
487
+ targetOffset: gestureMovePos > boundaryOffset ? -boundaryOffset : offset.value + translation,
488
+ canMove: currentOffset < boundaryOffset
489
+ };
461
490
  }
462
491
  else {
463
- return true;
492
+ const gestureMovePos = currentOffset - translation;
493
+ return {
494
+ targetOffset: gestureMovePos < 0 ? 0 : offset.value + translation,
495
+ canMove: currentOffset > 0
496
+ };
464
497
  }
465
498
  }
466
499
  function handleEnd(eventData) {
@@ -511,7 +544,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
511
544
  }
512
545
  });
513
546
  }
514
- function handleLongPress() {
547
+ function computeHalf() {
515
548
  'worklet';
516
549
  const currentOffset = Math.abs(offset.value);
517
550
  let preOffset = (currentIndex.value + patchElmNumShared.value) * step.value;
@@ -521,6 +554,14 @@ const SwiperWrapper = forwardRef((props, ref) => {
521
554
  // 正常事件中拿到的transition值(正向滑动<0,倒着滑>0)
522
555
  const diffOffset = preOffset - currentOffset;
523
556
  const half = Math.abs(diffOffset) > step.value / 2;
557
+ return {
558
+ diffOffset,
559
+ half
560
+ };
561
+ }
562
+ function handleLongPress() {
563
+ 'worklet';
564
+ const { diffOffset, half } = computeHalf();
524
565
  if (+diffOffset === 0) {
525
566
  runOnJS(resumeLoop)();
526
567
  }
@@ -580,19 +621,30 @@ const SwiperWrapper = forwardRef((props, ref) => {
580
621
  runOnJS(pauseLoop)();
581
622
  preAbsolutePos.value = e[strAbso];
582
623
  moveTranstion.value = e[strAbso];
624
+ anotherDirectionMove.value = e[anotherAbso];
583
625
  moveTime.value = new Date().getTime();
584
626
  })
585
- .onTouchesMove((e) => {
627
+ .onUpdate((e) => {
586
628
  'worklet';
587
629
  if (touchfinish.value)
588
630
  return;
589
- const touchEventData = e.changedTouches[0];
590
- const moveDistance = touchEventData[strAbso] - preAbsolutePos.value;
631
+ const moveDistance = e[strAbso] - preAbsolutePos.value;
591
632
  const eventData = {
592
633
  translation: moveDistance
593
634
  };
594
- // 处理用户一直拖拽到临界点的场景, 不会执行onEnd
595
- if (!circularShared.value && !canMove(eventData)) {
635
+ // 1. 在Move过程中,如果手指一直没抬起来,超过一半的话也会更新索引
636
+ const { half } = computeHalf();
637
+ if (half) {
638
+ const { selectedIndex } = getTargetPosition(eventData);
639
+ currentIndex.value = selectedIndex;
640
+ }
641
+ // 2. 处理用户一直拖拽到临界点的场景, 不会执行onEnd
642
+ const { canMove, targetOffset } = checkUnCircular(eventData);
643
+ if (!circularShared.value) {
644
+ if (canMove) {
645
+ offset.value = targetOffset;
646
+ preAbsolutePos.value = e[strAbso];
647
+ }
596
648
  return;
597
649
  }
598
650
  const { isBoundary, resetOffset } = reachBoundary(eventData);
@@ -602,34 +654,44 @@ const SwiperWrapper = forwardRef((props, ref) => {
602
654
  else {
603
655
  offset.value = moveDistance + offset.value;
604
656
  }
605
- preAbsolutePos.value = touchEventData[strAbso];
657
+ preAbsolutePos.value = e[strAbso];
606
658
  })
607
- .onTouchesUp((e) => {
659
+ .onFinalize((e) => {
608
660
  'worklet';
609
661
  if (touchfinish.value)
610
662
  return;
611
- const touchEventData = e.changedTouches[0];
612
- const moveDistance = touchEventData[strAbso] - moveTranstion.value;
663
+ const moveDistance = e[strAbso] - moveTranstion.value;
613
664
  touchfinish.value = true;
614
665
  const eventData = {
615
666
  translation: moveDistance
616
667
  };
617
- // 用户手指按下起来, 需要计算正确的位置, 比如在滑动过程中突然按下然后起来,需要计算到正确的位置
618
- if (!circularShared.value && !canMove(eventData)) {
619
- return;
620
- }
621
668
  const strVelocity = moveDistance / (new Date().getTime() - moveTime.value) * 1000;
622
669
  if (Math.abs(strVelocity) < longPressRatio) {
623
670
  handleLongPress();
624
671
  }
625
672
  else {
673
+ // 如果触发了onTouchesCancelled,不会触发onUpdate不会更新offset值, 索引不会变更
626
674
  handleEnd(eventData);
627
675
  }
628
- });
676
+ }).withRef(swiperGestureRef);
677
+ // swiper横向,当y轴滑动5像素手势失效;swiper纵向只响应swiper的滑动事件
678
+ if (dir === 'x') {
679
+ gesturePan.activeOffsetX([-5, 5]).failOffsetY([-5, 5]);
680
+ }
681
+ else {
682
+ gesturePan.activeOffsetY([-5, 5]).failOffsetX([-5, 5]);
683
+ }
684
+ // 手势协同2.0
685
+ if (simultaneousHandlers && simultaneousHandlers.length) {
686
+ gesturePan.simultaneousWithExternalGesture(...simultaneousHandlers);
687
+ }
688
+ if (waitForHandlers && waitForHandlers.length) {
689
+ gesturePan.requireExternalGestureToFail(...waitForHandlers);
690
+ }
629
691
  return {
630
692
  gestureHandler: gesturePan
631
693
  };
632
- }, []);
694
+ }, [gestureSwitch.current]);
633
695
  const animatedStyles = useAnimatedStyle(() => {
634
696
  if (dir === 'x') {
635
697
  return { transform: [{ translateX: offset.value }], opacity: step.value > 0 ? 1 : 0 };
@@ -641,12 +703,12 @@ const SwiperWrapper = forwardRef((props, ref) => {
641
703
  function renderSwiper() {
642
704
  const arrPages = renderItems();
643
705
  return (<View style={[normalStyle, layoutStyle, styles.swiper]} {...layoutProps} {...innerProps}>
644
- <Animated.View style={[{
706
+ <Animated.View style={[{
645
707
  flexDirection: dir === 'x' ? 'row' : 'column',
646
708
  width: '100%',
647
709
  height: '100%'
648
710
  }, animatedStyles]}>
649
- {wrapChildren({
711
+ {wrapChildren({
650
712
  children: arrPages
651
713
  }, {
652
714
  hasVarDec,
@@ -654,11 +716,11 @@ const SwiperWrapper = forwardRef((props, ref) => {
654
716
  textStyle,
655
717
  textProps
656
718
  })}
657
- </Animated.View>
658
- {showsPagination && renderPagination()}
719
+ </Animated.View>
720
+ {showsPagination && renderPagination()}
659
721
  </View>);
660
722
  }
661
- if (children.length === 1) {
723
+ if (children.length === 1 || disableGesture) {
662
724
  return renderSwiper();
663
725
  }
664
726
  else {
@@ -67,17 +67,15 @@ const _Switch = forwardRef((props, ref) => {
67
67
  }
68
68
  };
69
69
  }, []);
70
- const innerProps = useInnerProps(props, extendObject({
70
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
71
71
  ref: nodeRef,
72
72
  style: extendObject({}, normalStyle, layoutStyle)
73
- }, layoutProps, !disabled ? { [type === 'switch' ? 'onValueChange' : '_onChange']: onChange } : {}), [
73
+ }, !disabled ? { [type === 'switch' ? 'onValueChange' : '_onChange']: onChange } : {}), [
74
74
  'checked',
75
75
  'disabled',
76
76
  'type',
77
77
  'color'
78
- ], {
79
- layoutRef
80
- });
78
+ ], { layoutRef });
81
79
  if (type === 'checkbox') {
82
80
  return createElement(CheckBox, extendObject({}, innerProps, {
83
81
  color: color,
@@ -7,10 +7,9 @@ import { Text } from 'react-native';
7
7
  import { useRef, forwardRef, createElement } from 'react';
8
8
  import useInnerProps from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef'; // 引入辅助函数
10
- import { useTransformStyle, wrapChildren } from './utils';
10
+ import { useTransformStyle, wrapChildren, extendObject } from './utils';
11
11
  const _Text = forwardRef((props, ref) => {
12
12
  const { style = {}, allowFontScaling = false, selectable, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'user-select': userSelect, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
- const layoutRef = useRef({});
14
13
  const { normalStyle, hasVarDec, varContextRef } = useTransformStyle(style, {
15
14
  enableVar,
16
15
  externalVarContext,
@@ -22,16 +21,14 @@ const _Text = forwardRef((props, ref) => {
22
21
  useNodesRef(props, ref, nodeRef, {
23
22
  style: normalStyle
24
23
  });
25
- const innerProps = useInnerProps(props, {
24
+ const innerProps = useInnerProps(extendObject({}, props, {
26
25
  ref: nodeRef,
27
26
  style: normalStyle,
28
27
  selectable: !!selectable || !!userSelect,
29
28
  allowFontScaling
30
- }, [
29
+ }), [
31
30
  'user-select'
32
- ], {
33
- layoutRef
34
- });
31
+ ]);
35
32
  return createElement(Text, innerProps, wrapChildren(props, {
36
33
  hasVarDec,
37
34
  varContext: varContextRef.current
@@ -206,7 +206,7 @@ const MpxVideo = forwardRef((videoProps, ref) => {
206
206
  licenseServer: licenseUrl
207
207
  };
208
208
  }
209
- const innerProps = useInnerProps(props, extendObject({
209
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
210
210
  style: styles.video,
211
211
  ref: videoRef,
212
212
  source,
@@ -228,7 +228,7 @@ const MpxVideo = forwardRef((videoProps, ref) => {
228
228
  onFullscreenPlayerWillDismiss: bindfullscreenchange && handleExitFullScreen,
229
229
  onControlsVisibilityChange: bindcontrolstoggle && handleAndroidControlsVisibilityChange,
230
230
  onLoad: handleVideoLoad
231
- }, layoutProps), [
231
+ }), [
232
232
  'src',
233
233
  'autoplay',
234
234
  'loop',
@@ -11,7 +11,7 @@ import Animated from 'react-native-reanimated';
11
11
  import useAnimationHooks from './useAnimationHooks';
12
12
  import useNodesRef from './useNodesRef';
13
13
  import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject, useHover } from './utils';
14
- import { error } from '@mpxjs/utils';
14
+ import { error, isFunction } from '@mpxjs/utils';
15
15
  import LinearGradient from 'react-native-linear-gradient';
16
16
  import { GestureDetector } from 'react-native-gesture-handler';
17
17
  import Portal from './mpx-portal';
@@ -543,7 +543,7 @@ function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backg
543
543
  }
544
544
  const _View = forwardRef((viewProps, ref) => {
545
545
  const { textProps, innerProps: props = {} } = splitProps(viewProps);
546
- let { style = {}, 'hover-style': hoverStyle, 'hover-start-time': hoverStartTime = 50, 'hover-stay-time': hoverStayTime = 400, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'enable-background': enableBackground, 'enable-fast-image': enableFastImage, 'enable-animation': enableAnimation, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, animation } = props;
546
+ let { style = {}, 'hover-style': hoverStyle, 'hover-start-time': hoverStartTime = 50, 'hover-stay-time': hoverStayTime = 400, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'enable-background': enableBackground, 'enable-fast-image': enableFastImage, 'enable-animation': enableAnimation, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, animation, catchtransitionend, bindtransitionend } = props;
547
547
  // 默认样式
548
548
  const defaultStyle = style.display === 'flex'
549
549
  ? {
@@ -575,15 +575,29 @@ const _View = forwardRef((viewProps, ref) => {
575
575
  });
576
576
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
577
577
  const viewStyle = extendObject({}, innerStyle, layoutStyle);
578
- const { enableStyleAnimation, animationStyle } = useAnimationHooks({
579
- enableAnimation,
580
- animation,
581
- style: viewStyle
582
- });
583
- const innerProps = useInnerProps(props, extendObject({
578
+ const transitionend = isFunction(catchtransitionend)
579
+ ? catchtransitionend
580
+ : isFunction(bindtransitionend)
581
+ ? bindtransitionend
582
+ : null;
583
+ const { enableStyleAnimation, animationStyle } = useAnimationHooks(transitionend
584
+ ? {
585
+ layoutRef,
586
+ animation,
587
+ enableAnimation,
588
+ style: viewStyle,
589
+ transitionend
590
+ }
591
+ : {
592
+ layoutRef,
593
+ animation,
594
+ enableAnimation,
595
+ style: viewStyle
596
+ });
597
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
584
598
  ref: nodeRef,
585
599
  style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
586
- }, layoutProps), [
600
+ }), [
587
601
  'hover-start-time',
588
602
  'hover-stay-time',
589
603
  'hover-style',
@@ -1,4 +1,4 @@
1
- import { forwardRef, useRef, useContext, useMemo, useState, useEffect } from 'react';
1
+ import { forwardRef, useRef, useContext, useMemo, useState } from 'react';
2
2
  import { warn, isFunction } from '@mpxjs/utils';
3
3
  import Portal from './mpx-portal/index';
4
4
  import { getCustomEvent } from './getInnerListeners';
@@ -74,17 +74,17 @@ const _WebView = forwardRef((props, ref) => {
74
74
  isNavigateBack.current = false;
75
75
  };
76
76
  const navigation = useNavigation();
77
- useEffect(() => {
78
- let beforeRemoveSubscription;
79
- if (__mpx_mode__ !== 'ios') {
80
- beforeRemoveSubscription = navigation?.addListener?.('beforeRemove', beforeRemoveHandle);
81
- }
82
- return () => {
83
- if (isFunction(beforeRemoveSubscription)) {
84
- beforeRemoveSubscription();
85
- }
86
- };
87
- }, []);
77
+ // useEffect(() => {
78
+ // let beforeRemoveSubscription:any
79
+ // if (__mpx_mode__ !== 'ios') {
80
+ // beforeRemoveSubscription = navigation?.addListener?.('beforeRemove', beforeRemoveHandle)
81
+ // }
82
+ // return () => {
83
+ // if (isFunction(beforeRemoveSubscription)) {
84
+ // beforeRemoveSubscription()
85
+ // }
86
+ // }
87
+ // }, [])
88
88
  useNodesRef(props, ref, webViewRef, {
89
89
  style: defaultWebViewStyle
90
90
  });
@@ -160,7 +160,7 @@ const _WebView = forwardRef((props, ref) => {
160
160
  { // case下不允许直接声明,包个块解决该问题
161
161
  const title = postData._documentTitle?.trim();
162
162
  if (title !== undefined) {
163
- navigation && navigation.setOptions({ title });
163
+ navigation && navigation.setPageConfig({ navigationBarTitleText: title });
164
164
  }
165
165
  }
166
166
  break;