@mpxjs/webpack-plugin 2.10.2 → 2.10.3-beta.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 (76) hide show
  1. package/lib/config.js +2 -1
  2. package/lib/dependencies/RecordPageConfigsMapDependency.js +45 -0
  3. package/lib/index.js +13 -1
  4. package/lib/platform/json/wx/index.js +6 -3
  5. package/lib/platform/style/wx/index.js +29 -16
  6. package/lib/platform/template/wx/component-config/button.js +19 -2
  7. package/lib/platform/template/wx/component-config/canvas.js +4 -0
  8. package/lib/platform/template/wx/component-config/checkbox-group.js +4 -0
  9. package/lib/platform/template/wx/component-config/checkbox.js +4 -0
  10. package/lib/platform/template/wx/component-config/cover-image.js +7 -1
  11. package/lib/platform/template/wx/component-config/cover-view.js +4 -0
  12. package/lib/platform/template/wx/component-config/fix-component-name.js +3 -2
  13. package/lib/platform/template/wx/component-config/form.js +7 -1
  14. package/lib/platform/template/wx/component-config/icon.js +4 -0
  15. package/lib/platform/template/wx/component-config/image.js +7 -1
  16. package/lib/platform/template/wx/component-config/input.js +17 -2
  17. package/lib/platform/template/wx/component-config/label.js +4 -0
  18. package/lib/platform/template/wx/component-config/movable-area.js +7 -1
  19. package/lib/platform/template/wx/component-config/movable-view.js +12 -3
  20. package/lib/platform/template/wx/component-config/navigator.js +4 -0
  21. package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
  22. package/lib/platform/template/wx/component-config/picker-view.js +7 -1
  23. package/lib/platform/template/wx/component-config/picker.js +7 -1
  24. package/lib/platform/template/wx/component-config/radio-group.js +4 -0
  25. package/lib/platform/template/wx/component-config/radio.js +4 -0
  26. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  27. package/lib/platform/template/wx/component-config/root-portal.js +4 -0
  28. package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
  29. package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
  30. package/lib/platform/template/wx/component-config/swiper.js +12 -3
  31. package/lib/platform/template/wx/component-config/switch.js +4 -0
  32. package/lib/platform/template/wx/component-config/text.js +7 -1
  33. package/lib/platform/template/wx/component-config/textarea.js +17 -2
  34. package/lib/platform/template/wx/component-config/unsupported.js +7 -0
  35. package/lib/platform/template/wx/component-config/video.js +10 -2
  36. package/lib/platform/template/wx/component-config/view.js +24 -2
  37. package/lib/platform/template/wx/component-config/web-view.js +4 -0
  38. package/lib/platform/template/wx/index.js +32 -13
  39. package/lib/react/index.js +0 -1
  40. package/lib/react/processJSON.js +13 -2
  41. package/lib/react/processScript.js +5 -3
  42. package/lib/react/processTemplate.js +18 -3
  43. package/lib/react/script-helper.js +18 -4
  44. package/lib/runtime/components/react/dist/mpx-input.jsx +1 -11
  45. package/lib/runtime/components/react/dist/{KeyboardAvoidingView.jsx → mpx-keyboard-avoiding-view.jsx} +4 -3
  46. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +2 -2
  47. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +1 -2
  48. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +10 -5
  49. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +22 -0
  50. package/lib/runtime/components/react/dist/mpx-swiper.jsx +2 -2
  51. package/lib/runtime/components/react/dist/mpx-view.jsx +10 -5
  52. package/lib/runtime/components/react/dist/mpx-web-view.jsx +10 -7
  53. package/lib/runtime/components/react/dist/useAnimationHooks.js +46 -48
  54. package/lib/runtime/components/react/dist/utils.jsx +18 -7
  55. package/lib/runtime/components/react/mpx-input.tsx +1 -19
  56. package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx} +4 -2
  57. package/lib/runtime/components/react/mpx-picker-view-column.tsx +2 -2
  58. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +1 -2
  59. package/lib/runtime/components/react/mpx-scroll-view.tsx +13 -4
  60. package/lib/runtime/components/react/mpx-simple-view.tsx +32 -0
  61. package/lib/runtime/components/react/mpx-swiper.tsx +4 -2
  62. package/lib/runtime/components/react/mpx-view.tsx +17 -10
  63. package/lib/runtime/components/react/mpx-web-view.tsx +15 -12
  64. package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
  65. package/lib/runtime/components/react/types/global.d.ts +1 -1
  66. package/lib/runtime/components/react/useAnimationHooks.ts +46 -48
  67. package/lib/runtime/components/react/utils.tsx +23 -11
  68. package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
  69. package/lib/runtime/optionProcessor.js +3 -2
  70. package/lib/style-compiler/index.js +8 -6
  71. package/lib/template-compiler/compiler.js +21 -13
  72. package/lib/utils/env.js +1 -1
  73. package/lib/utils/match-condition.js +14 -8
  74. package/lib/web/processJSON.js +1 -3
  75. package/package.json +3 -3
  76. package/LICENSE +0 -433
@@ -89,7 +89,8 @@ function buildGlobalParams ({
89
89
  componentsMap,
90
90
  pagesMap,
91
91
  firstPage,
92
- outputPath
92
+ outputPath,
93
+ genericsInfo
93
94
  }) {
94
95
  let content = ''
95
96
  if (ctorType === 'app') {
@@ -115,9 +116,22 @@ global.currentInject.firstPage = ${JSON.stringify(firstPage)}\n`
115
116
  delete pageConfig.usingComponents
116
117
  content += `global.currentInject.pageConfig = ${JSON.stringify(pageConfig)}\n`
117
118
  }
118
- content += `global.currentInject.getComponents = function () {
119
- return ${shallowStringify(componentsMap)}
120
- }\n`
119
+
120
+ content += `
121
+
122
+ function getComponents() {
123
+ return ${shallowStringify(componentsMap)}
124
+ }
125
+
126
+ global.currentInject.getComponents = getComponents\n`
127
+ if (genericsInfo) {
128
+ content += `
129
+ const genericHash = ${JSON.stringify(genericsInfo.hash)}\n
130
+ global.__mpxGenericsMap[genericHash] = function (name) {
131
+ return getComponents()[name]
132
+ }
133
+ \n`
134
+ }
121
135
  if (ctorType === 'component') {
122
136
  content += `global.currentInject.componentPath = '/' + ${JSON.stringify(outputPath)}\n`
123
137
  }
@@ -170,15 +170,6 @@ const Input = forwardRef((props, ref) => {
170
170
  layoutRef
171
171
  }, props));
172
172
  };
173
- const onKeyPress = (evt) => {
174
- evt.nativeEvent.key === 'Enter' &&
175
- bindconfirm(getCustomEvent('confirm', evt, {
176
- detail: {
177
- value: tmpValue.current || ''
178
- },
179
- layoutRef
180
- }, props));
181
- };
182
173
  const onSubmitEditing = (evt) => {
183
174
  bindconfirm(getCustomEvent('confirm', evt, {
184
175
  detail: {
@@ -278,8 +269,7 @@ const Input = forwardRef((props, ref) => {
278
269
  onChange,
279
270
  onSelectionChange,
280
271
  onContentSizeChange,
281
- onKeyPress: bindconfirm && onKeyPress,
282
- onSubmitEditing: bindconfirm && multiline && onSubmitEditing
272
+ onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
283
273
  }), [
284
274
  'type',
285
275
  'password',
@@ -1,6 +1,6 @@
1
1
  import React, { useContext, useEffect, useMemo } from 'react';
2
2
  import { Keyboard, Platform, View } from 'react-native';
3
- import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, runOnJS } from 'react-native-reanimated';
3
+ import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
4
4
  import { GestureDetector, Gesture } from 'react-native-gesture-handler';
5
5
  import { KeyboardAvoidContext } from './context';
6
6
  const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
@@ -16,8 +16,8 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
16
16
  const gesture = useMemo(() => {
17
17
  return Gesture.Tap()
18
18
  .onEnd(() => {
19
- runOnJS(dismiss)();
20
- });
19
+ dismiss();
20
+ }).runOnJS(true);
21
21
  }, []);
22
22
  const animatedStyle = useAnimatedStyle(() => {
23
23
  return Object.assign({
@@ -96,4 +96,5 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
96
96
  </View>
97
97
  </GestureDetector>);
98
98
  };
99
+ KeyboardAvoidingView.displayName = 'MpxKeyboardAvoidingView';
99
100
  export default KeyboardAvoidingView;
@@ -1,7 +1,7 @@
1
1
  import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
  import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
4
- import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS } from './utils';
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, isHarmony } from './utils';
5
5
  import useNodesRef from './useNodesRef';
6
6
  import PickerIndicator from './pickerViewIndicator';
7
7
  import PickerMask from './pickerViewMask';
@@ -81,7 +81,7 @@ const _PickerViewColumn = forwardRef((props, ref) => {
81
81
  y: initialIndex * itemRawH,
82
82
  animated: false
83
83
  });
84
- }, isAndroid ? 200 : 0);
84
+ }, isAndroid || isHarmony ? 200 : 0);
85
85
  activeIndex.current = initialIndex;
86
86
  }, [itemRawH, maxIndex, initialIndex]);
87
87
  const onContentSizeChange = useCallback((_w, h) => {
@@ -1,6 +1,5 @@
1
1
  import { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
- import { extendObject } from '../utils';
4
3
  const _PortalManager = forwardRef((props, ref) => {
5
4
  const [state, setState] = useState({
6
5
  portals: []
@@ -14,7 +13,7 @@ const _PortalManager = forwardRef((props, ref) => {
14
13
  setState((prevState) => ({
15
14
  portals: prevState.portals.map((item) => {
16
15
  if (item.key === key) {
17
- return extendObject({}, item, { children });
16
+ return Object.assign({}, item, { children });
18
17
  }
19
18
  return item;
20
19
  })
@@ -41,7 +41,7 @@ import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, ext
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, __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, '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
47
  const [refreshing, setRefreshing] = useState(true);
@@ -54,7 +54,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
54
54
  scrollTop: 0,
55
55
  visibleLength: 0
56
56
  });
57
- const scrollEventThrottle = 50;
58
57
  const hasCallScrollToUpper = useRef(true);
59
58
  const hasCallScrollToLower = useRef(false);
60
59
  const initialTimeout = useRef(null);
@@ -83,6 +82,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
83
82
  };
84
83
  }, []);
85
84
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
85
+ const lastOffset = useRef(0);
86
86
  if (scrollX && scrollY) {
87
87
  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');
88
88
  }
@@ -133,7 +133,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
133
133
  function onStartReached(e) {
134
134
  const { bindscrolltoupper } = props;
135
135
  const { offset } = scrollOptions.current;
136
- if (bindscrolltoupper && (offset <= upperThreshold)) {
136
+ const isScrollingBackward = offset < lastOffset.current;
137
+ if (bindscrolltoupper && (offset <= upperThreshold) && isScrollingBackward) {
137
138
  if (!hasCallScrollToUpper.current) {
138
139
  bindscrolltoupper(getCustomEvent('scrolltoupper', e, {
139
140
  detail: {
@@ -152,12 +153,13 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
152
153
  const { bindscrolltolower } = props;
153
154
  const { contentLength, visibleLength, offset } = scrollOptions.current;
154
155
  const distanceFromEnd = contentLength - visibleLength - offset;
155
- if (bindscrolltolower && (distanceFromEnd < lowerThreshold)) {
156
+ const isScrollingForward = offset > lastOffset.current;
157
+ if (bindscrolltolower && (distanceFromEnd < lowerThreshold) && isScrollingForward) {
156
158
  if (!hasCallScrollToLower.current) {
157
159
  hasCallScrollToLower.current = true;
158
160
  bindscrolltolower(getCustomEvent('scrolltolower', e, {
159
161
  detail: {
160
- direction: scrollX ? 'right' : 'botttom'
162
+ direction: scrollX ? 'right' : 'bottom'
161
163
  },
162
164
  layoutRef
163
165
  }, props));
@@ -206,6 +208,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
206
208
  onStartReached(e);
207
209
  onEndReached(e);
208
210
  updateIntersection();
211
+ // 在 onStartReached、onEndReached 执行完后更新 lastOffset
212
+ lastOffset.current = scrollOptions.current.offset;
209
213
  }
210
214
  function onScrollEnd(e) {
211
215
  const { bindscrollend } = props;
@@ -225,6 +229,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
225
229
  onStartReached(e);
226
230
  onEndReached(e);
227
231
  updateIntersection();
232
+ lastOffset.current = scrollOptions.current.offset;
228
233
  }
229
234
  function updateIntersection() {
230
235
  if (enableTriggerIntersectionObserver && intersectionObservers) {
@@ -0,0 +1,22 @@
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);
7
+ const { textProps, innerProps: props = {} } = splitProps(simpleViewProps);
8
+ 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, {
16
+ hasVarDec: false,
17
+ textStyle: textStyle,
18
+ textProps
19
+ }));
20
+ });
21
+ _View2.displayName = 'MpxSimpleView';
22
+ export default _View2;
@@ -70,7 +70,7 @@ 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, 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;
@@ -658,7 +658,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
658
658
  {showsPagination && renderPagination()}
659
659
  </View>);
660
660
  }
661
- if (children.length === 1) {
661
+ if (children.length === 1 || disableGesture) {
662
662
  return renderSwiper();
663
663
  }
664
664
  else {
@@ -14,6 +14,7 @@ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wra
14
14
  import { error } from '@mpxjs/utils';
15
15
  import LinearGradient from 'react-native-linear-gradient';
16
16
  import { GestureDetector } from 'react-native-gesture-handler';
17
+ import Portal from './mpx-portal';
17
18
  const linearMap = new Map([
18
19
  ['top', 0],
19
20
  ['bottom', 180],
@@ -555,7 +556,7 @@ const _View = forwardRef((viewProps, ref) => {
555
556
  const enableHover = !!hoverStyle;
556
557
  const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime });
557
558
  const styleObj = extendObject({}, defaultStyle, style, isHover ? hoverStyle : {});
558
- const { normalStyle, hasSelfPercent, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
559
+ const { normalStyle, hasSelfPercent, hasPositionFixed, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
559
560
  enableVar,
560
561
  externalVarContext,
561
562
  parentFontSize,
@@ -600,12 +601,16 @@ const _View = forwardRef((viewProps, ref) => {
600
601
  innerStyle,
601
602
  enableFastImage
602
603
  });
603
- const BaseComponent = enableStyleAnimation
604
+ let finalComponent = enableStyleAnimation
604
605
  ? createElement(Animated.View, innerProps, childNode)
605
606
  : createElement(View, innerProps, childNode);
606
- return enableHover
607
- ? createElement(GestureDetector, { gesture: gesture }, BaseComponent)
608
- : BaseComponent;
607
+ if (enableHover) {
608
+ finalComponent = createElement(GestureDetector, { gesture: gesture }, finalComponent);
609
+ }
610
+ if (hasPositionFixed) {
611
+ finalComponent = createElement(Portal, null, finalComponent);
612
+ }
613
+ return finalComponent;
609
614
  });
610
615
  _View.displayName = 'MpxView';
611
616
  export default _View;
@@ -45,7 +45,7 @@ const _WebView = forwardRef((props, ref) => {
45
45
  button: 'Reload'
46
46
  }
47
47
  };
48
- const currentErrorText = errorText[mpx.i18n.locale || 'zh-CN'];
48
+ const currentErrorText = errorText[mpx.i18n?.locale || 'zh-CN'];
49
49
  if (props.style) {
50
50
  warn('The web-view component does not support the style prop.');
51
51
  }
@@ -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__ === 'android' || __mpx_mode__ === 'harmony') {
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__ === 'android' || __mpx_mode__ === 'harmony') {
137
140
  canGoBack.current = event.nativeEvent.canGoBack;
138
141
  }
139
142
  };
@@ -251,8 +254,8 @@ const _WebView = forwardRef((props, ref) => {
251
254
  }
252
255
  };
253
256
  const onLoadEnd = function (res) {
254
- if (__mpx_mode__ === 'android') {
255
- res.persist();
257
+ res.persist();
258
+ if (__mpx_mode__ === 'android' || __mpx_mode__ === 'harmony') {
256
259
  setTimeout(() => {
257
260
  onLoadEndHandle(res);
258
261
  }, 0);
@@ -277,7 +280,7 @@ const _WebView = forwardRef((props, ref) => {
277
280
  setIsLoaded(false);
278
281
  }
279
282
  };
280
- return (<Portal key={pageLoadErr ? 'error' : 'webview'}>
283
+ return (<Portal>
281
284
  {pageLoadErr
282
285
  ? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
283
286
  <View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useMemo, useRef } from 'react';
2
2
  import { Easing, useSharedValue, withTiming, useAnimatedStyle, withSequence, withDelay, makeMutable, cancelAnimation } from 'react-native-reanimated';
3
- import { error } from '@mpxjs/utils';
3
+ import { error, hasOwn } from '@mpxjs/utils';
4
4
  // 微信 timingFunction 和 RN Easing 对应关系
5
5
  const EasingKey = {
6
6
  linear: Easing.linear,
@@ -14,20 +14,20 @@ const EasingKey = {
14
14
  const TransformInitial = {
15
15
  // matrix: 0,
16
16
  // matrix3d: 0,
17
- rotate: '0deg',
17
+ // rotate: '0deg',
18
18
  rotateX: '0deg',
19
19
  rotateY: '0deg',
20
20
  rotateZ: '0deg',
21
21
  // rotate3d:[0,0,0]
22
- scale: 1,
22
+ // scale: 1,
23
23
  // scale3d: [1, 1, 1],
24
24
  scaleX: 1,
25
25
  scaleY: 1,
26
26
  // scaleZ: 1,
27
- skew: 0,
27
+ // skew: 0,
28
28
  skewX: '0deg',
29
29
  skewY: '0deg',
30
- translate: 0,
30
+ // translate: 0,
31
31
  // translate3d: 0,
32
32
  translateX: 0,
33
33
  translateY: 0
@@ -92,23 +92,23 @@ const parseTransform = (transformStr) => {
92
92
  case 'skewX':
93
93
  case 'skewY':
94
94
  case 'perspective':
95
+ // rotate 处理成 rotateZ
96
+ key = key === 'rotate' ? 'rotateZ' : key;
95
97
  // 单个值处理
96
98
  transform.push({ [key]: global.__formatValue(val) });
97
99
  break;
98
100
  case 'matrix':
99
- case 'matrix3d':
100
101
  transform.push({ [key]: parseValues(val, ',').map(val => +val) });
101
102
  break;
102
103
  case 'translate':
103
104
  case 'scale':
104
105
  case 'skew':
105
- case 'rotate3d': // x y z angle
106
106
  case 'translate3d': // x y 支持 z不支持
107
107
  case 'scale3d': // x y 支持 z不支持
108
108
  {
109
109
  // 2 个以上的值处理
110
110
  key = key.replace('3d', '');
111
- const vals = parseValues(val, ',').splice(0, key === 'rotate' ? 4 : 3);
111
+ const vals = parseValues(val, ',').splice(0, 3);
112
112
  // scale(.5) === scaleX(.5) scaleY(.5)
113
113
  if (vals.length === 1 && key === 'scale') {
114
114
  vals.push(vals[0]);
@@ -132,6 +132,13 @@ const formatStyle = (style) => {
132
132
  transform: parseTransform(style.transform)
133
133
  });
134
134
  };
135
+ // transform 数组转对象
136
+ function getTransformObj(transforms) {
137
+ 'worklet';
138
+ return transforms.reduce((transformObj, item) => {
139
+ return Object.assign(transformObj, item);
140
+ }, {});
141
+ }
135
142
  export default function useAnimationHooks(props) {
136
143
  const { style = {}, animation, enableAnimation } = props;
137
144
  const enableStyleAnimation = enableAnimation || !!animation;
@@ -150,7 +157,9 @@ export default function useAnimationHooks(props) {
150
157
  // 记录动画key的style样式值 没有的话设置为false
151
158
  // eslint-disable-next-line react-hooks/rules-of-hooks
152
159
  const animatedKeys = useRef({});
153
- // const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean|number|string})
160
+ // 记录上次style map
161
+ // eslint-disable-next-line react-hooks/rules-of-hooks
162
+ const lastStyleRef = useRef({});
154
163
  // ** 全量 style prop sharedValue
155
164
  // 不能做增量的原因:
156
165
  // 1 尝试用 useRef,但 useAnimatedStyle 访问后的 ref 不能在增加新的值,被冻结
@@ -163,6 +172,12 @@ export default function useAnimationHooks(props) {
163
172
  return valMap;
164
173
  }, {});
165
174
  }, []);
175
+ // ** style更新同步
176
+ // eslint-disable-next-line react-hooks/rules-of-hooks
177
+ useEffect(() => {
178
+ // style 更新后同步更新 lastStyleRef & shareValMap
179
+ updateStyleVal();
180
+ }, [style]);
166
181
  // ** 获取动画样式prop & 驱动动画
167
182
  // eslint-disable-next-line react-hooks/rules-of-hooks
168
183
  useEffect(() => {
@@ -175,16 +190,6 @@ export default function useAnimationHooks(props) {
175
190
  // 驱动动画
176
191
  createAnimation(keys);
177
192
  }, [id]);
178
- // 同步style更新
179
- // useEffect(() => {
180
- // Object.keys(animatedKeys.current).forEach(key => {
181
- // const originVal = getOriginalStyleVal(key, isTransform(key))
182
- // if (originVal && animatedKeys.current[key] !== originVal) {
183
- // animatedKeys.current[key] = originVal
184
- // shareValMap[key].value = originVal
185
- // }
186
- // })
187
- // }, [style])
188
193
  // ** 清空动画
189
194
  // eslint-disable-next-line react-hooks/rules-of-hooks
190
195
  useEffect(() => {
@@ -194,7 +199,7 @@ export default function useAnimationHooks(props) {
194
199
  });
195
200
  };
196
201
  }, []);
197
- // 根据 animation action 创建&驱动动画 key => wi
202
+ // 根据 animation action 创建&驱动动画
198
203
  function createAnimation(animatedKeys = []) {
199
204
  const actions = animation?.actions || [];
200
205
  const sequence = {};
@@ -251,6 +256,7 @@ export default function useAnimationHooks(props) {
251
256
  : withTiming(value, { duration, easing });
252
257
  return delay ? withDelay(delay, animation) : animation;
253
258
  }
259
+ // 获取样式初始值(prop style or 默认值)
254
260
  function getInitialVal(key, isTransform = false) {
255
261
  if (isTransform && Array.isArray(originalStyle.transform)) {
256
262
  let initialVal = InitialValue[key];
@@ -263,31 +269,12 @@ export default function useAnimationHooks(props) {
263
269
  }
264
270
  return originalStyle[key] === undefined ? InitialValue[key] : originalStyle[key];
265
271
  }
266
- // 从 prop style 中获取样式初始值 没有为undefined
267
- // function getOriginalStyleVal (key: keyof ExtendedViewStyle, isTransform = false) {
268
- // if (isTransform && Array.isArray(originalStyle.transform)) {
269
- // let initialVal = undefined // InitialValue[key]
270
- // // 仅支持 { transform: [{rotateX: '45deg'}, {rotateZ: '0.785398rad'}] } 格式的初始样式
271
- // originalStyle.transform.forEach(item => {
272
- // if (item[key] !== undefined) initialVal = item[key]
273
- // })
274
- // return initialVal
275
- // }
276
- // return originalStyle[key] // === undefined ? InitialValue[key] : originalStyle[key]
277
- // }
278
- // 获取动画shareVal初始值(prop style or 默认值)
279
- // function getInitialVal (key: keyof ExtendedViewStyle, isTransform = false) {
280
- // const originalVal = getOriginalStyleVal(key, isTransform)
281
- // return originalVal === undefined ? InitialValue[key] : originalStyle[key]
282
- // }
283
272
  // 循环 animation actions 获取所有有动画的 style prop name
284
273
  function getAnimatedStyleKeys() {
285
274
  return (animation?.actions || []).reduce((keyMap, action) => {
286
275
  const { rules, transform } = action;
287
276
  const ruleArr = [...rules.keys(), ...transform.keys()];
288
277
  ruleArr.forEach(key => {
289
- // const originalVal = getOriginalStyleVal(key, isTransform(key))
290
- // if (!keyMap[key]) keyMap[key] = originalVal === undefined ? false : originalVal
291
278
  if (!keyMap[key])
292
279
  keyMap[key] = true;
293
280
  });
@@ -295,7 +282,7 @@ export default function useAnimationHooks(props) {
295
282
  }, animatedKeys.current);
296
283
  }
297
284
  // animated key transform 格式化
298
- function formatAnimatedKeys(keys = []) {
285
+ function formatAnimatedKeys(keys) {
299
286
  const animatedKeys = [];
300
287
  const transforms = [];
301
288
  keys.forEach(key => {
@@ -310,13 +297,24 @@ export default function useAnimationHooks(props) {
310
297
  animatedKeys.push(transforms);
311
298
  return animatedKeys;
312
299
  }
313
- // transform 数组转对象
314
- function getTransformObj() {
315
- 'worklet';
316
- const transforms = originalStyle.transform || [];
317
- return transforms.reduce((transformObj, item) => {
318
- return Object.assign(transformObj, item);
319
- }, {});
300
+ // 设置 lastShareValRef & shareValMap
301
+ function updateStyleVal() {
302
+ Object.entries(originalStyle).forEach(([key, value]) => {
303
+ if (key === 'transform') {
304
+ Object.entries(getTransformObj(value)).forEach(([key, value]) => {
305
+ if (value !== lastStyleRef.current[key]) {
306
+ lastStyleRef.current[key] = value;
307
+ shareValMap[key].value = value;
308
+ }
309
+ });
310
+ }
311
+ else if (hasOwn(shareValMap, key)) {
312
+ if (value !== lastStyleRef.current[key]) {
313
+ lastStyleRef.current[key] = value;
314
+ shareValMap[key].value = value;
315
+ }
316
+ }
317
+ });
320
318
  }
321
319
  // ** 生成动画样式
322
320
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -325,7 +323,7 @@ export default function useAnimationHooks(props) {
325
323
  return animatedStyleKeys.value.reduce((styles, key) => {
326
324
  // console.info('getAnimationStyles', key, shareValMap[key].value)
327
325
  if (Array.isArray(key)) {
328
- const transformStyle = getTransformObj();
326
+ const transformStyle = getTransformObj(originalStyle.transform || []);
329
327
  key.forEach((transformKey) => {
330
328
  transformStyle[transformKey] = shareValMap[transformKey].value;
331
329
  });
@@ -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-/;
@@ -239,12 +240,8 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
239
240
  const normalStyleChangedRef = useRef(false);
240
241
  let hasVarDec = false;
241
242
  let hasVarUse = false;
242
- let hasSelfPercent = false;
243
243
  const varKeyPaths = [];
244
244
  const unoVarKeyPaths = [];
245
- const percentKeyPaths = [];
246
- const calcKeyPaths = [];
247
- const envKeyPaths = [];
248
245
  const [width, setWidth] = useState(0);
249
246
  const [height, setHeight] = useState(0);
250
247
  const navigation = useNavigation();
@@ -304,6 +301,11 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
304
301
  normalStyleChangedRef.current = !normalStyleChangedRef.current;
305
302
  }
306
303
  const memoResult = useMemo(() => {
304
+ let hasSelfPercent = false;
305
+ let hasPositionFixed = false;
306
+ const percentKeyPaths = [];
307
+ const calcKeyPaths = [];
308
+ const envKeyPaths = [];
307
309
  // transform can be memoized
308
310
  function envVisitor({ value, keyPath }) {
309
311
  if (envUseRegExp.test(value)) {
@@ -324,6 +326,12 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
324
326
  percentKeyPaths.push(keyPath.slice());
325
327
  }
326
328
  }
329
+ function transformPosition(styleObj) {
330
+ if (styleObj.position === 'fixed') {
331
+ hasPositionFixed = true;
332
+ styleObj.position = 'absolute';
333
+ }
334
+ }
327
335
  // traverse env & calc & percent
328
336
  traverseStyle(normalStyle, [envVisitor, percentVisitor, calcVisitor]);
329
337
  const percentConfig = {
@@ -355,11 +363,14 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
355
363
  }
356
364
  }
357
365
  });
366
+ // apply position
367
+ transformPosition(normalStyle);
358
368
  // transform number enum stringify
359
369
  transformStringify(normalStyle);
360
370
  return {
361
371
  normalStyle,
362
- hasSelfPercent
372
+ hasSelfPercent,
373
+ hasPositionFixed
363
374
  };
364
375
  }, [normalStyleChangedRef.current, width, height, parentWidth, parentHeight, parentFontSize]);
365
376
  return extendObject({
@@ -434,8 +445,8 @@ export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout
434
445
  hasLayoutRef.current = true;
435
446
  if (hasSelfPercent) {
436
447
  const { width, height } = e?.nativeEvent?.layout || {};
437
- setWidth(width || 0);
438
- setHeight(height || 0);
448
+ setWidth && setWidth(width || 0);
449
+ setHeight && setHeight(height || 0);
439
450
  }
440
451
  if (enableOffset) {
441
452
  nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
@@ -324,23 +324,6 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
324
324
  )
325
325
  }
326
326
 
327
- const onKeyPress = (evt: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
328
- evt.nativeEvent.key === 'Enter' &&
329
- bindconfirm!(
330
- getCustomEvent(
331
- 'confirm',
332
- evt,
333
- {
334
- detail: {
335
- value: tmpValue.current || ''
336
- },
337
- layoutRef
338
- },
339
- props
340
- )
341
- )
342
- }
343
-
344
327
  const onSubmitEditing = (evt: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => {
345
328
  bindconfirm!(
346
329
  getCustomEvent(
@@ -474,8 +457,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
474
457
  onChange,
475
458
  onSelectionChange,
476
459
  onContentSizeChange,
477
- onKeyPress: bindconfirm && onKeyPress,
478
- onSubmitEditing: bindconfirm && multiline && onSubmitEditing
460
+ onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
479
461
  }
480
462
  ),
481
463
  [