@mpxjs/webpack-plugin 2.9.65 → 2.9.67

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 (80) hide show
  1. package/lib/dependencies/RecordGlobalComponentsDependency.js +11 -12
  2. package/lib/dependencies/RecordRuntimeInfoDependency.js +1 -1
  3. package/lib/index.js +28 -8
  4. package/lib/json-compiler/index.js +2 -11
  5. package/lib/loader.js +24 -45
  6. package/lib/native-loader.js +49 -64
  7. package/lib/platform/json/wx/index.js +3 -10
  8. package/lib/platform/style/wx/index.js +32 -56
  9. package/lib/react/index.js +4 -3
  10. package/lib/react/processJSON.js +5 -13
  11. package/lib/react/processMainScript.js +7 -3
  12. package/lib/react/processScript.js +3 -4
  13. package/lib/react/processTemplate.js +6 -4
  14. package/lib/resolver/AddModePlugin.js +17 -4
  15. package/lib/runtime/components/react/context.ts +8 -0
  16. package/lib/runtime/components/react/dist/context.js +1 -0
  17. package/lib/runtime/components/react/dist/mpx-button.jsx +1 -1
  18. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +30 -17
  19. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +1 -1
  20. package/lib/runtime/components/react/dist/mpx-form.jsx +33 -24
  21. package/lib/runtime/components/react/dist/mpx-icon.jsx +1 -1
  22. package/lib/runtime/components/react/dist/mpx-image/index.jsx +1 -1
  23. package/lib/runtime/components/react/dist/mpx-input.jsx +44 -38
  24. package/lib/runtime/components/react/dist/mpx-label.jsx +10 -7
  25. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +10 -17
  26. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +378 -294
  27. package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
  28. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +30 -17
  29. package/lib/runtime/components/react/dist/mpx-radio.jsx +1 -1
  30. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  31. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +58 -30
  32. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +77 -77
  33. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +1 -1
  34. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +1 -1
  35. package/lib/runtime/components/react/dist/mpx-switch.jsx +8 -1
  36. package/lib/runtime/components/react/dist/mpx-text.jsx +1 -1
  37. package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
  38. package/lib/runtime/components/react/dist/mpx-view.jsx +31 -12
  39. package/lib/runtime/components/react/dist/mpx-web-view.jsx +2 -2
  40. package/lib/runtime/components/react/dist/useAnimationHooks.js +303 -0
  41. package/lib/runtime/components/react/dist/utils.jsx +13 -3
  42. package/lib/runtime/components/react/getInnerListeners.ts +1 -0
  43. package/lib/runtime/components/react/mpx-button.tsx +1 -1
  44. package/lib/runtime/components/react/mpx-checkbox-group.tsx +52 -29
  45. package/lib/runtime/components/react/mpx-checkbox.tsx +1 -1
  46. package/lib/runtime/components/react/mpx-form.tsx +42 -34
  47. package/lib/runtime/components/react/mpx-icon.tsx +1 -1
  48. package/lib/runtime/components/react/mpx-image/index.tsx +2 -3
  49. package/lib/runtime/components/react/mpx-input.tsx +68 -66
  50. package/lib/runtime/components/react/mpx-label.tsx +11 -8
  51. package/lib/runtime/components/react/mpx-movable-area.tsx +11 -19
  52. package/lib/runtime/components/react/mpx-movable-view.tsx +456 -334
  53. package/lib/runtime/components/react/mpx-navigator.tsx +1 -1
  54. package/lib/runtime/components/react/mpx-radio-group.tsx +55 -29
  55. package/lib/runtime/components/react/mpx-radio.tsx +1 -1
  56. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  57. package/lib/runtime/components/react/mpx-scroll-view.tsx +92 -37
  58. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +77 -76
  59. package/lib/runtime/components/react/mpx-swiper/index.tsx +2 -1
  60. package/lib/runtime/components/react/mpx-swiper-item.tsx +1 -1
  61. package/lib/runtime/components/react/mpx-switch.tsx +10 -2
  62. package/lib/runtime/components/react/mpx-text.tsx +1 -1
  63. package/lib/runtime/components/react/mpx-textarea.tsx +1 -1
  64. package/lib/runtime/components/react/mpx-view.tsx +40 -20
  65. package/lib/runtime/components/react/mpx-web-view.tsx +2 -2
  66. package/lib/runtime/components/react/types/common.ts +8 -2
  67. package/lib/runtime/components/react/useAnimationHooks.ts +332 -0
  68. package/lib/runtime/components/react/useNodesRef.ts +1 -0
  69. package/lib/runtime/components/react/utils.tsx +23 -6
  70. package/lib/runtime/optionProcessorReact.js +0 -15
  71. package/lib/runtime/swanHelper.wxs +1 -1
  72. package/lib/style-compiler/index.js +1 -1
  73. package/lib/style-compiler/plugins/scope-id.js +1 -0
  74. package/lib/template-compiler/compiler.js +68 -33
  75. package/lib/template-compiler/index.js +4 -4
  76. package/lib/utils/pre-process-json.js +113 -0
  77. package/lib/web/index.js +5 -4
  78. package/lib/web/processJSON.js +5 -13
  79. package/lib/web/processTemplate.js +2 -2
  80. package/package.json +5 -4
@@ -31,5 +31,5 @@ const _Navigator = forwardRef((props, ref) => {
31
31
  {children}
32
32
  </MpxView>);
33
33
  });
34
- _Navigator.displayName = 'mpx-navigator';
34
+ _Navigator.displayName = 'MpxNavigator';
35
35
  export default _Navigator;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * ✔ bindchange
3
3
  */
4
- import { useRef, forwardRef, useContext } from 'react';
4
+ import { useRef, forwardRef, useContext, useMemo, useEffect } from 'react';
5
5
  import { View } from 'react-native';
6
6
  import { warn } from '@mpxjs/utils';
7
7
  import { FormContext, RadioGroupContext } from './context';
@@ -9,7 +9,9 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef';
10
10
  import { useLayout, useTransformStyle, wrapChildren } from './utils';
11
11
  const radioGroup = forwardRef((props, ref) => {
12
- const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, bindchange } = props;
12
+ const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
+ const propsRef = useRef({});
14
+ propsRef.current = props;
13
15
  const formContext = useContext(FormContext);
14
16
  let formValuesMap;
15
17
  if (formContext) {
@@ -28,16 +30,13 @@ const radioGroup = forwardRef((props, ref) => {
28
30
  const nodeRef = useRef(null);
29
31
  useNodesRef(props, ref, nodeRef, { defaultStyle });
30
32
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
31
- const getSelectionValue = () => {
33
+ const getValue = () => {
32
34
  for (const key in groupValue) {
33
35
  if (groupValue[key].checked) {
34
36
  return key;
35
37
  }
36
38
  }
37
39
  };
38
- const getValue = () => {
39
- return getSelectionValue();
40
- };
41
40
  const resetValue = () => {
42
41
  Object.keys(groupValue).forEach((key) => {
43
42
  groupValue[key].checked = false;
@@ -52,15 +51,29 @@ const radioGroup = forwardRef((props, ref) => {
52
51
  formValuesMap.set(props.name, { getValue, resetValue });
53
52
  }
54
53
  }
55
- const notifyChange = (evt) => {
56
- bindchange &&
57
- bindchange(getCustomEvent('tap', evt, {
58
- layoutRef,
59
- detail: {
60
- value: getSelectionValue()
61
- }
62
- }, props));
63
- };
54
+ useEffect(() => {
55
+ return () => {
56
+ if (formValuesMap && props.name) {
57
+ formValuesMap.delete(props.name);
58
+ }
59
+ };
60
+ }, []);
61
+ const contextValue = useMemo(() => {
62
+ const notifyChange = (evt) => {
63
+ const { bindchange } = propsRef.current;
64
+ bindchange &&
65
+ bindchange(getCustomEvent('tap', evt, {
66
+ layoutRef,
67
+ detail: {
68
+ value: getValue()
69
+ }
70
+ }, propsRef.current));
71
+ };
72
+ return {
73
+ groupValue,
74
+ notifyChange
75
+ };
76
+ }, []);
64
77
  const innerProps = useInnerProps(props, {
65
78
  ref: nodeRef,
66
79
  style: { ...normalStyle, ...layoutStyle },
@@ -69,7 +82,7 @@ const radioGroup = forwardRef((props, ref) => {
69
82
  layoutRef
70
83
  });
71
84
  return (<View {...innerProps}>
72
- <RadioGroupContext.Provider value={{ groupValue, notifyChange }}>
85
+ <RadioGroupContext.Provider value={contextValue}>
73
86
  {wrapChildren(props, {
74
87
  hasVarDec,
75
88
  varContext: varContextRef.current
@@ -77,5 +90,5 @@ const radioGroup = forwardRef((props, ref) => {
77
90
  </RadioGroupContext.Provider>
78
91
  </View>);
79
92
  });
80
- radioGroup.displayName = 'mpx-radio-group';
93
+ radioGroup.displayName = 'MpxRadioGroup';
81
94
  export default radioGroup;
@@ -151,5 +151,5 @@ const Radio = forwardRef((radioProps, ref) => {
151
151
  })}
152
152
  </View>);
153
153
  });
154
- Radio.displayName = 'mpx-radio';
154
+ Radio.displayName = 'MpxRadio';
155
155
  export default Radio;
@@ -11,5 +11,5 @@ const _RootPortal = (props) => {
11
11
  </Portal>
12
12
  : <>{children}</>;
13
13
  };
14
- _RootPortal.displayName = 'mpx-root-portal';
14
+ _RootPortal.displayName = 'MpxRootPortal';
15
15
  export default _RootPortal;
@@ -5,7 +5,7 @@
5
5
  * ✔ lower-threshold
6
6
  * ✔ scroll-top
7
7
  * ✔ scroll-left
8
- * scroll-into-view
8
+ * scroll-into-view
9
9
  * ✔ scroll-with-animation
10
10
  * ✔ enable-back-to-top
11
11
  * ✘ enable-passive
@@ -33,15 +33,18 @@
33
33
  */
34
34
  import { ScrollView } from 'react-native-gesture-handler';
35
35
  import { RefreshControl } from 'react-native';
36
- import { useRef, useState, useEffect, forwardRef } from 'react';
36
+ import { useRef, useState, useEffect, forwardRef, useContext } from 'react';
37
37
  import { useAnimatedRef } from 'react-native-reanimated';
38
38
  import { warn } from '@mpxjs/utils';
39
39
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
40
40
  import useNodesRef from './useNodesRef';
41
- import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren } from './utils';
41
+ import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, flatGesture } from './utils';
42
+ import { IntersectionObserverContext } from './context';
42
43
  const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
43
44
  const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
44
- const { enhanced = false, bounces = true, style = {}, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'show-scrollbar': showScrollbar = true, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
45
+ 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, '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, __selectRef } = props;
46
+ const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
47
+ const waitForHandlers = flatGesture(waitFor);
45
48
  const [refreshing, setRefreshing] = useState(true);
46
49
  const snapScrollTop = useRef(0);
47
50
  const snapScrollLeft = useRef(0);
@@ -56,6 +59,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
56
59
  const hasCallScrollToUpper = useRef(true);
57
60
  const hasCallScrollToLower = useRef(false);
58
61
  const initialTimeout = useRef(null);
62
+ const intersectionObservers = useContext(IntersectionObserverContext);
63
+ const snapScrollIntoView = useRef('');
59
64
  const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
60
65
  const { textStyle, innerStyle } = splitStyle(normalStyle);
61
66
  const scrollViewRef = useAnimatedRef();
@@ -69,30 +74,42 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
69
74
  fastDeceleration: false,
70
75
  decelerationDisabled: false,
71
76
  scrollTo: scrollToOffset
72
- }
77
+ },
78
+ gestureRef: scrollViewRef
73
79
  });
74
80
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
75
81
  if (scrollX && scrollY) {
76
82
  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');
77
83
  }
78
84
  useEffect(() => {
79
- if (snapScrollTop.current !== props['scroll-top'] ||
80
- snapScrollLeft.current !== props['scroll-left']) {
81
- snapScrollTop.current = props['scroll-top'] || 0;
82
- snapScrollLeft.current = props['scroll-left'] || 0;
85
+ if (snapScrollTop.current !== scrollTop || snapScrollLeft.current !== scrollLeft) {
83
86
  initialTimeout.current = setTimeout(() => {
84
- scrollToOffset(snapScrollLeft.current, snapScrollTop.current);
87
+ scrollToOffset(scrollLeft, scrollTop);
85
88
  }, 0);
86
89
  return () => {
87
90
  initialTimeout.current && clearTimeout(initialTimeout.current);
88
91
  };
89
92
  }
90
- }, [props['scroll-top'], props['scroll-left']]);
93
+ }, [scrollTop, scrollLeft]);
94
+ useEffect(() => {
95
+ if (refreshing !== refresherTriggered) {
96
+ setRefreshing(!!refresherTriggered);
97
+ }
98
+ }, [refresherTriggered]);
91
99
  useEffect(() => {
92
- if (refreshing !== props['refresher-triggered']) {
93
- setRefreshing(!!props['refresher-triggered']);
100
+ if (scrollIntoView && __selectRef && snapScrollIntoView.current !== scrollIntoView) {
101
+ snapScrollIntoView.current = scrollIntoView || '';
102
+ setTimeout(() => {
103
+ const refs = __selectRef(`#${scrollIntoView}`, 'node');
104
+ if (refs) {
105
+ const { nodeRef } = refs.getNodeInstance();
106
+ nodeRef.current?.measureLayout(scrollViewRef.current, (left, top) => {
107
+ scrollToOffset(left, top);
108
+ });
109
+ }
110
+ });
94
111
  }
95
- }, [props['refresher-triggered']]);
112
+ }, [scrollIntoView]);
96
113
  function selectLength(size) {
97
114
  return !scrollX ? size.height : size.width;
98
115
  }
@@ -173,6 +190,11 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
173
190
  layoutRef
174
191
  }, props));
175
192
  updateScrollOptions(e, { scrollLeft, scrollTop });
193
+ if (enableTriggerIntersectionObserver && intersectionObservers) {
194
+ for (const key in intersectionObservers) {
195
+ intersectionObservers[key].throttleMeasure();
196
+ }
197
+ }
176
198
  }
177
199
  function onScrollEnd(e) {
178
200
  const { bindscrollend } = props;
@@ -197,6 +219,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
197
219
  scrollViewRef.current.scrollTo({ x, y, animated: !!scrollWithAnimation });
198
220
  scrollOptions.current.scrollLeft = x;
199
221
  scrollOptions.current.scrollTop = y;
222
+ snapScrollLeft.current = x;
223
+ snapScrollTop.current = y;
200
224
  }
201
225
  }
202
226
  function onRefresh() {
@@ -205,7 +229,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
205
229
  bindrefresherrefresh(getCustomEvent('refresherrefresh', {}, { layoutRef }, props));
206
230
  }
207
231
  function onScrollTouchStart(e) {
208
- const { binddragstart, bindtouchstart, enhanced } = props;
232
+ const { bindtouchstart } = props;
209
233
  bindtouchstart && bindtouchstart(e);
210
234
  if (enhanced) {
211
235
  binddragstart &&
@@ -219,7 +243,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
219
243
  }
220
244
  }
221
245
  function onScrollTouchMove(e) {
222
- const { binddragging, bindtouchmove, enhanced } = props;
223
246
  bindtouchmove && bindtouchmove(e);
224
247
  if (enhanced) {
225
248
  binddragging &&
@@ -232,24 +255,23 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
232
255
  }, props));
233
256
  }
234
257
  }
235
- function onScrollEndDrag(e) {
236
- const { binddragend, enhanced } = props;
258
+ function onScrollTouchEnd(e) {
259
+ bindtouchend && bindtouchend(e);
237
260
  if (enhanced) {
238
- const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
239
- const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize;
240
261
  binddragend &&
241
262
  binddragend(getCustomEvent('dragend', e, {
242
263
  detail: {
243
- scrollLeft: scrollLeft,
244
- scrollTop: scrollTop,
245
- scrollHeight,
246
- scrollWidth
264
+ scrollLeft: scrollOptions.current.scrollLeft || 0,
265
+ scrollTop: scrollOptions.current.scrollTop || 0
247
266
  },
248
267
  layoutRef
249
268
  }, props));
250
- updateScrollOptions(e, { scrollLeft, scrollTop });
251
269
  }
252
270
  }
271
+ function onScrollDrag(e) {
272
+ const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
273
+ updateScrollOptions(e, { scrollLeft, scrollTop });
274
+ }
253
275
  let scrollAdditionalProps = {
254
276
  style: { ...innerStyle, ...layoutStyle },
255
277
  pinchGestureEnabled: false,
@@ -262,11 +284,15 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
262
284
  ref: scrollViewRef,
263
285
  onScroll: onScroll,
264
286
  onContentSizeChange: onContentSizeChange,
265
- bindtouchstart: onScrollTouchStart,
266
- bindtouchmove: onScrollTouchMove,
267
- onScrollEndDrag,
287
+ bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) ? onScrollTouchStart : undefined,
288
+ bindtouchmove: ((enhanced && binddragging) || bindtouchend) ? onScrollTouchMove : undefined,
289
+ bindtouchend: ((enhanced && binddragend) || bindtouchend) ? onScrollTouchEnd : undefined,
290
+ onScrollBeginDrag: onScrollDrag,
291
+ onScrollEndDrag: onScrollDrag,
268
292
  onMomentumScrollEnd: onScrollEnd,
269
- ...layoutProps
293
+ ...layoutProps,
294
+ ...(simultaneousHandlers ? { simultaneousHandlers } : {}),
295
+ ...(waitForHandlers ? { waitFor: waitForHandlers } : {})
270
296
  };
271
297
  if (enhanced) {
272
298
  scrollAdditionalProps = {
@@ -276,9 +302,11 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
276
302
  };
277
303
  }
278
304
  const innerProps = useInnerProps(props, scrollAdditionalProps, [
305
+ 'id',
279
306
  'scroll-x',
280
307
  'scroll-y',
281
308
  'enable-back-to-top',
309
+ 'enable-trigger-intersection-observer',
282
310
  'paging-enabled',
283
311
  'show-scrollbar',
284
312
  'upper-threshold',
@@ -315,5 +343,5 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
315
343
  })}
316
344
  </ScrollView>);
317
345
  });
318
- _ScrollView.displayName = 'mpx-scroll-view';
346
+ _ScrollView.displayName = 'MpxScrollView';
319
347
  export default _ScrollView;
@@ -67,6 +67,8 @@ const _Carouse = forwardRef((props, ref) => {
67
67
  const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0);
68
68
  const defaultX = (defaultWidth * initOffsetIndex) || 0;
69
69
  const defaultY = (defaultHeight * initOffsetIndex) || 0;
70
+ // 主动scorllTo时是否要出发onScrollEnd
71
+ const needTriggerScrollEnd = useRef(true);
70
72
  // 内部存储上一次的offset值
71
73
  const autoplayTimerRef = useRef(null);
72
74
  const scrollViewRef = useRef(null);
@@ -77,22 +79,21 @@ const _Carouse = forwardRef((props, ref) => {
77
79
  // 内部存储上一次的偏移量
78
80
  const internalsRef = useRef({
79
81
  offset: {
80
- x: defaultX || 0,
81
- y: defaultY || 0
82
+ x: 0,
83
+ y: 0
82
84
  },
83
85
  isScrolling: false
84
86
  });
85
87
  const isDragRef = useRef(false);
86
88
  const [state, setState] = useState({
87
- children: newChild,
88
89
  width: dir === 'x' && typeof defaultWidth === 'number' ? defaultWidth - previousMargin - nextMargin : defaultWidth,
89
90
  height: dir === 'y' && typeof defaultHeight === 'number' ? defaultHeight - previousMargin - nextMargin : defaultHeight,
90
91
  // 真正的游标索引, 从0开始
91
92
  index: initIndex,
92
93
  total: totalElements,
93
94
  offset: {
94
- x: dir === 'x' ? defaultX : 0,
95
- y: dir === 'y' ? defaultY : 0
95
+ x: 0,
96
+ y: 0
96
97
  },
97
98
  dir
98
99
  });
@@ -113,25 +114,38 @@ const _Carouse = forwardRef((props, ref) => {
113
114
  }, [props.autoplay, props.current, state.index, state.width, state.height]);
114
115
  useEffect(() => {
115
116
  // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
116
- if (!props.autoplay && props.current !== state.index) {
117
+ if (!props.autoplay && props.current !== undefined && props.current !== state.index) {
117
118
  const initIndex = props.current || 0;
118
119
  // 这里要排除超过元素个数的设置
119
- const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0);
120
- const defaultX = (defaultWidth * initOffsetIndex) || 0;
121
- const offset = {
122
- x: dir === 'x' ? defaultX : 0,
123
- y: dir === 'y' ? defaultY : 0
124
- };
125
- state.offset = offset;
126
- internalsRef.current.offset = offset;
127
- setState((preState) => {
128
- return {
129
- ...preState,
130
- offset
131
- };
132
- });
120
+ const { nextIndex, nextOffset } = getMultiNextConfig(props.current);
121
+ // 1. 安卓需要主动更新下内部状态, 2. IOS不能触发完wcrollTo之后立即updateState, 会造成滑动两次
122
+ // 2. setTimeout 是fix 当再渲染过程中触发scrollTo失败的问题
123
+ if (Platform.OS === 'ios') {
124
+ needTriggerScrollEnd.current = false;
125
+ setTimeout(() => {
126
+ scrollViewRef.current?.scrollTo({
127
+ ...nextOffset,
128
+ animated: true
129
+ });
130
+ }, 50);
131
+ }
132
+ else {
133
+ updateState(nextIndex, nextOffset);
134
+ }
133
135
  }
134
- }, [props.current]);
136
+ }, [props.current, state.width, state.height]);
137
+ function getMultiNextConfig(target) {
138
+ const step = state.dir === 'x' ? state.width : state.height;
139
+ const targetPos = step * props.current;
140
+ const targetOffset = {
141
+ x: dir === 'x' ? targetPos : 0,
142
+ y: dir === 'y' ? targetPos : 0
143
+ };
144
+ return {
145
+ nextIndex: target,
146
+ nextOffset: targetOffset
147
+ };
148
+ }
135
149
  /**
136
150
  * @desc: 更新状态: index和offset, 并响应索引变化的事件
137
151
  * scrollViewOffset: 移动到的目标位置
@@ -181,7 +195,6 @@ const _Carouse = forwardRef((props, ref) => {
181
195
  nextIndex = isBack ? nextIndex - 2 : nextIndex;
182
196
  }
183
197
  if (!props.circular) {
184
- // nextIndex = isBack ? nextIndex - 2 : nextIndex
185
198
  nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * nextIndex });
186
199
  }
187
200
  else {
@@ -230,13 +243,12 @@ const _Carouse = forwardRef((props, ref) => {
230
243
  createAutoPlay();
231
244
  return;
232
245
  }
233
- if (!Array.isArray(state.children)) {
246
+ if (!Array.isArray(props.children)) {
234
247
  return;
235
248
  }
236
249
  const step = state.dir === 'x' ? state.width : state.height;
237
250
  const { nextOffset, autoMoveOffset, isAutoEnd } = getNextConfig(state.offset);
238
251
  // 这里可以scroll到下一个元素, 但是把scrollView的偏移量在设置为content,视觉效果就没了吧
239
- // scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
240
252
  if (Platform.OS === 'ios') {
241
253
  if (!isAutoEnd) {
242
254
  scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true });
@@ -266,7 +278,6 @@ const _Carouse = forwardRef((props, ref) => {
266
278
  // 安卓无法实现视觉的无缝连接, 只能回到真正的位置, 且安卓调用scrollTo不能触发onMomentumScrollEnd,还未找到为啥
267
279
  if (state.dir === 'x') {
268
280
  scrollViewRef.current?.scrollTo({ x: step, y: step, animated: true });
269
- // scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.y, animated: true })
270
281
  }
271
282
  else {
272
283
  scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: step, animated: true });
@@ -283,9 +294,15 @@ const _Carouse = forwardRef((props, ref) => {
283
294
  }
284
295
  /**
285
296
  * 当用户开始拖动结束
297
+ * 注意: 当手动调用scrollTo的时候, 安卓不会触发onMomentumScrollEnd, IOS会触发onMomentumScrollEnd
286
298
  */
287
299
  function onScrollEnd(event) {
288
- // 这里安卓好像没有触发onScrollEnd, 调用scrollTo的时候
300
+ if (Platform.OS === 'ios' && !needTriggerScrollEnd.current) {
301
+ const { nextIndex, nextOffset } = getMultiNextConfig(props.current);
302
+ updateState(nextIndex, nextOffset);
303
+ needTriggerScrollEnd.current = true;
304
+ return;
305
+ }
289
306
  if (totalElements === 1) {
290
307
  return;
291
308
  }
@@ -311,58 +328,41 @@ const _Carouse = forwardRef((props, ref) => {
311
328
  * @desc: 水平方向时,获取元素的布局,更新, 其中如果传递100%时需要依赖measure计算元算的宽高
312
329
  */
313
330
  function onWrapperLayout(e) {
314
- if (hasSelfPercent) {
315
- const { width, height } = e?.nativeEvent?.layout || {};
316
- setWidth(width || 0);
317
- setHeight(height || 0);
318
- }
319
- if (props.enableOffset) {
320
- scrollViewRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
321
- layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
322
- const isWDiff = state.width !== width;
323
- const isHDiff = state.height !== height;
324
- if (isWDiff || isHDiff) {
325
- const changeState = {
326
- width: isWDiff ? width : state.width,
327
- height: isHDiff ? height : state.height
331
+ scrollViewRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
332
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
333
+ const isWDiff = state.width !== width;
334
+ const isHDiff = state.height !== height;
335
+ if (isWDiff || isHDiff) {
336
+ const changeState = {
337
+ width: isWDiff ? width : state.width,
338
+ height: isHDiff ? height : state.height
339
+ };
340
+ const attr = state.dir === 'x' ? 'width' : 'height';
341
+ changeState[attr] = changeState[attr] - previousMargin - nextMargin;
342
+ const correctOffset = Object.assign({}, state.offset, {
343
+ [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
344
+ });
345
+ state.width = changeState.width;
346
+ state.height = changeState.height;
347
+ // 这里setState之后,会再触发重新渲染, renderScrollView会再次触发onScrollEnd,
348
+ setState((preState) => {
349
+ return {
350
+ ...preState,
351
+ width: changeState.width,
352
+ height: changeState.height
328
353
  };
329
- const attr = state.dir === 'x' ? 'width' : 'height';
330
- changeState[attr] = changeState[attr] - previousMargin - nextMargin;
331
- const correctOffset = Object.assign({}, state.offset, {
332
- [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
333
- });
334
- state.offset = correctOffset;
335
- state.width = changeState.width;
336
- state.height = changeState.height;
337
- setState((preState) => {
338
- return {
339
- ...preState,
340
- offset: correctOffset,
341
- width: changeState.width,
342
- height: changeState.height
343
- };
344
- });
345
- scrollViewRef.current?.scrollTo({ x: correctOffset.x, y: correctOffset.y, animated: false });
346
- }
347
- props.getInnerLayout && props.getInnerLayout(layoutRef);
348
- });
349
- }
354
+ });
355
+ }
356
+ props.getInnerLayout && props.getInnerLayout(layoutRef);
357
+ });
350
358
  }
351
359
  function getOffset() {
352
360
  const step = state.dir === 'x' ? state.width : state.height;
353
361
  if (!step || Number.isNaN(+step))
354
362
  return [];
355
363
  const offsetArray = [];
356
- if (previousMargin) {
357
- offsetArray.push(0);
358
- for (let i = 1; i < totalElements; i++) {
359
- offsetArray.push(i * step - previousMargin);
360
- }
361
- }
362
- else {
363
- for (let i = 0; i < totalElements; i++) {
364
- offsetArray.push(i * step);
365
- }
364
+ for (let i = 0; i < totalElements; i++) {
365
+ offsetArray.push(i * step);
366
366
  }
367
367
  return offsetArray;
368
368
  }
@@ -371,7 +371,7 @@ const _Carouse = forwardRef((props, ref) => {
371
371
  const scrollElementProps = {
372
372
  ref: scrollViewRef,
373
373
  horizontal: props.horizontal,
374
- pagingEnabled: false,
374
+ pagingEnabled: true,
375
375
  snapToOffsets: offsetsArray,
376
376
  decelerationRate: 0.99,
377
377
  showsHorizontalScrollIndicator: false,
@@ -423,20 +423,21 @@ const _Carouse = forwardRef((props, ref) => {
423
423
  </View>);
424
424
  }
425
425
  function renderPages() {
426
- const { width, height, total, children } = state;
426
+ const { width, height } = state;
427
+ const { children } = props;
427
428
  const { circular } = props;
428
429
  const pageStyle = { width: width, height: height };
429
430
  // 设置了previousMargin或者nextMargin,
430
431
  // 1. 元素的宽度是减去这两个数目之和
431
432
  // 2. previousMargin设置marginLeft正值, nextmargin设置marginRight负值
432
433
  // 3. 第一个元素设置previousMargin 和 nextMargin, 最后一个元素
433
- if (total > 1 && Array.isArray(children)) {
434
+ if (totalElements > 1 && Array.isArray(children)) {
434
435
  let arrElements = [];
435
436
  // pages = ["2", "0", "1", "2", "0"]
436
437
  const pages = Array.isArray(children) ? Object.keys(children) : [];
437
438
  /* 无限循环的时候 */
438
439
  if (circular) {
439
- pages.unshift(total - 1 + '');
440
+ pages.unshift(totalElements - 1 + '');
440
441
  pages.push('0');
441
442
  }
442
443
  arrElements = pages.map((page, i) => {
@@ -447,7 +448,6 @@ const _Carouse = forwardRef((props, ref) => {
447
448
  else if (i === pages.length - 1 && typeof width === 'number') {
448
449
  nextMargin && (extraStyle.marginRight = nextMargin);
449
450
  }
450
- // return (<View style={[pageStyle, styles.slide, extraStyle]} key={ 'page' + i}>{children[+page]}</View>)
451
451
  return (<View style={[pageStyle, styles.slide, extraStyle]} key={'page' + i}>
452
452
  {wrapChildren({
453
453
  children: children[+page]
@@ -474,5 +474,5 @@ const _Carouse = forwardRef((props, ref) => {
474
474
  {props.showsPagination && renderPagination()}
475
475
  </View>);
476
476
  });
477
- _Carouse.displayName = '_Carouse';
477
+ _Carouse.displayName = 'MpxCarouse';
478
478
  export default _Carouse;
@@ -64,5 +64,5 @@ const _SwiperWrapper = forwardRef((props, ref) => {
64
64
  {children}
65
65
  </Carouse>;
66
66
  });
67
- _SwiperWrapper.displayName = 'mpx-swiper';
67
+ _SwiperWrapper.displayName = 'MpxSwiper';
68
68
  export default _SwiperWrapper;
@@ -30,5 +30,5 @@ const _SwiperItem = forwardRef((props, ref) => {
30
30
  })}
31
31
  </View>);
32
32
  });
33
- _SwiperItem.displayName = 'mpx-swiper-item';
33
+ _SwiperItem.displayName = 'MpxSwiperItem';
34
34
  export default _SwiperItem;
@@ -58,6 +58,13 @@ const _Switch = forwardRef((props, ref) => {
58
58
  formValuesMap.set(props.name, { getValue, resetValue });
59
59
  }
60
60
  }
61
+ useEffect(() => {
62
+ return () => {
63
+ if (formValuesMap && props.name) {
64
+ formValuesMap.delete(props.name);
65
+ }
66
+ };
67
+ }, []);
61
68
  const innerProps = useInnerProps(props, {
62
69
  ref: nodeRef,
63
70
  style: { ...normalStyle, ...layoutStyle },
@@ -76,5 +83,5 @@ const _Switch = forwardRef((props, ref) => {
76
83
  }
77
84
  return <Switch {...innerProps} style={normalStyle} value={isChecked} trackColor={{ false: '#FFF', true: color }} thumbColor={isChecked ? '#FFF' : '#f4f3f4'} ios_backgroundColor="#FFF"/>;
78
85
  });
79
- _Switch.displayName = 'mpx-switch';
86
+ _Switch.displayName = 'MpxSwitch';
80
87
  export default _Switch;
@@ -36,5 +36,5 @@ const _Text = forwardRef((props, ref) => {
36
36
  })}
37
37
  </Text>);
38
38
  });
39
- _Text.displayName = 'mpx-text';
39
+ _Text.displayName = 'MpxText';
40
40
  export default _Text;
@@ -23,5 +23,5 @@ const Textarea = forwardRef((props, ref) => {
23
23
  ]);
24
24
  return (<Input ref={ref} multiline confirm-type='next' bindblur={() => Keyboard.dismiss()} {...restProps}/>);
25
25
  });
26
- Textarea.displayName = 'mpx-textarea';
26
+ Textarea.displayName = 'MpxTextarea';
27
27
  export default Textarea;