@mpxjs/webpack-plugin 2.10.7-beta.1 → 2.10.7-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/dependencies/RecordPageConfigsMapDependency.js +1 -1
  2. package/lib/file-loader.js +1 -1
  3. package/lib/index.js +78 -86
  4. package/lib/parser.js +1 -1
  5. package/lib/platform/json/wx/index.js +25 -43
  6. package/lib/platform/style/wx/index.js +7 -0
  7. package/lib/platform/template/wx/component-config/fix-component-name.js +2 -2
  8. package/lib/platform/template/wx/component-config/movable-view.js +1 -10
  9. package/lib/platform/template/wx/index.js +1 -2
  10. package/lib/react/index.js +1 -3
  11. package/lib/react/processJSON.js +11 -66
  12. package/lib/react/processScript.js +3 -4
  13. package/lib/react/script-helper.js +18 -92
  14. package/lib/runtime/components/react/AsyncContainer.tsx +7 -35
  15. package/lib/runtime/components/react/context.ts +12 -2
  16. package/lib/runtime/components/react/dist/AsyncContainer.jsx +4 -23
  17. package/lib/runtime/components/react/dist/context.js +1 -1
  18. package/lib/runtime/components/react/dist/getInnerListeners.js +1 -1
  19. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +63 -9
  20. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +308 -63
  21. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +15 -10
  22. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +3 -1
  23. package/lib/runtime/components/react/dist/mpx-web-view.jsx +28 -14
  24. package/lib/runtime/components/react/dist/useAnimationHooks.js +87 -2
  25. package/lib/runtime/components/react/dist/utils.jsx +2 -13
  26. package/lib/runtime/components/react/getInnerListeners.ts +1 -1
  27. package/lib/runtime/components/react/mpx-movable-area.tsx +98 -11
  28. package/lib/runtime/components/react/mpx-movable-view.tsx +358 -64
  29. package/lib/runtime/components/react/mpx-scroll-view.tsx +16 -9
  30. package/lib/runtime/components/react/mpx-sticky-header.tsx +3 -1
  31. package/lib/runtime/components/react/mpx-web-view.tsx +33 -13
  32. package/lib/runtime/components/react/types/global.d.ts +0 -15
  33. package/lib/runtime/components/react/useAnimationHooks.ts +85 -2
  34. package/lib/runtime/components/react/utils.tsx +2 -13
  35. package/lib/runtime/components/web/mpx-scroll-view.vue +4 -7
  36. package/lib/runtime/components/web/mpx-sticky-header.vue +39 -31
  37. package/lib/runtime/optionProcessor.js +6 -2
  38. package/lib/script-setup-compiler/index.js +27 -5
  39. package/lib/template-compiler/bind-this.js +2 -1
  40. package/lib/template-compiler/compiler.js +4 -3
  41. package/lib/utils/dom-tag-config.js +3 -17
  42. package/lib/web/processTemplate.js +1 -1
  43. package/lib/web/script-helper.js +1 -1
  44. package/package.json +2 -2
  45. package/lib/react/LoadAsyncChunkModule.js +0 -68
  46. package/lib/runtime/components/react/AsyncSuspense.tsx +0 -81
  47. package/lib/runtime/components/react/dist/AsyncSuspense.jsx +0 -68
@@ -1,7 +1,6 @@
1
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
- import { usePreventRemove } from '@react-navigation/native';
5
4
  import { getCustomEvent } from './getInnerListeners';
6
5
  import { promisify, redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy';
7
6
  import { WebView } from 'react-native-webview';
@@ -56,8 +55,8 @@ const _WebView = forwardRef((props, ref) => {
56
55
  const webViewRef = useRef(null);
57
56
  const fristLoaded = useRef(false);
58
57
  const isLoadError = useRef(false);
59
- const isNavigateBack = useRef(false);
60
58
  const statusCode = useRef('');
59
+ const [isLoaded, setIsLoaded] = useState(true);
61
60
  const defaultWebViewStyle = {
62
61
  position: 'absolute',
63
62
  left: 0,
@@ -65,18 +64,27 @@ const _WebView = forwardRef((props, ref) => {
65
64
  top: 0,
66
65
  bottom: 0
67
66
  };
68
- const navigation = useNavigation();
69
- const [isIntercept, setIsIntercept] = useState(false);
70
- usePreventRemove(isIntercept, (event) => {
71
- const { data } = event;
72
- if (isNavigateBack.current) {
73
- navigation?.dispatch(data.action);
74
- }
75
- else {
67
+ const canGoBack = useRef(false);
68
+ const isNavigateBack = useRef(false);
69
+ const beforeRemoveHandle = (e) => {
70
+ if (canGoBack.current && !isNavigateBack.current) {
76
71
  webViewRef.current?.goBack();
72
+ e.preventDefault();
77
73
  }
78
74
  isNavigateBack.current = false;
79
- });
75
+ };
76
+ const navigation = useNavigation();
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
+ // }, [])
80
88
  useNodesRef(props, ref, webViewRef, {
81
89
  style: defaultWebViewStyle
82
90
  });
@@ -123,13 +131,13 @@ const _WebView = forwardRef((props, ref) => {
123
131
  };
124
132
  const _changeUrl = function (navState) {
125
133
  if (navState.navigationType) { // navigationType这个事件在页面开始加载时和页面加载完成时都会被触发所以判断这个避免其他无效触发执行该逻辑
134
+ canGoBack.current = navState.canGoBack;
126
135
  currentPage.__webViewUrl = navState.url;
127
- setIsIntercept(navState.canGoBack);
128
136
  }
129
137
  };
130
138
  const _onLoadProgress = function (event) {
131
139
  if (__mpx_mode__ !== 'ios') {
132
- setIsIntercept(event.nativeEvent.canGoBack);
140
+ canGoBack.current = event.nativeEvent.canGoBack;
133
141
  }
134
142
  };
135
143
  const _message = function (res) {
@@ -219,6 +227,7 @@ const _WebView = forwardRef((props, ref) => {
219
227
  };
220
228
  const onLoadEndHandle = function (res) {
221
229
  fristLoaded.current = true;
230
+ setIsLoaded(true);
222
231
  const src = res.nativeEvent?.url;
223
232
  if (isLoadError.current) {
224
233
  isLoadError.current = false;
@@ -266,13 +275,18 @@ const _WebView = forwardRef((props, ref) => {
266
275
  setPageLoadErr(true);
267
276
  }
268
277
  };
278
+ const onLoadStart = function () {
279
+ if (!fristLoaded.current) {
280
+ setIsLoaded(false);
281
+ }
282
+ };
269
283
  return (<Portal>
270
284
  {pageLoadErr
271
285
  ? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
272
286
  <View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
273
287
  <View style={styles.loadErrorButton} onTouchEnd={_reload}><Text style={{ fontSize: 12, color: '#666666' }}>{currentErrorText.button}</Text></View>
274
288
  </View>)
275
- : (<WebView style={defaultWebViewStyle} source={{ uri: src }} ref={webViewRef} javaScriptEnabled={true} onNavigationStateChange={_changeUrl} onMessage={_message} injectedJavaScript={injectedJavaScript} onLoadProgress={_onLoadProgress} onLoadEnd={onLoadEnd} onHttpError={onHttpError} onError={onError} allowsBackForwardNavigationGestures={true}></WebView>)}
289
+ : (<WebView style={defaultWebViewStyle} pointerEvents={isLoaded ? 'auto' : 'none'} source={{ uri: src }} ref={webViewRef} javaScriptEnabled={true} onNavigationStateChange={_changeUrl} onMessage={_message} injectedJavaScript={injectedJavaScript} onLoadProgress={_onLoadProgress} onLoadEnd={onLoadEnd} onHttpError={onHttpError} onError={onError} onLoadStart={onLoadStart} allowsBackForwardNavigationGestures={true}></WebView>)}
276
290
  </Portal>);
277
291
  });
278
292
  _WebView.displayName = 'MpxWebview';
@@ -48,6 +48,90 @@ const InitialValue = Object.assign({
48
48
  const TransformOrigin = 'transformOrigin';
49
49
  // transform
50
50
  const isTransform = (key) => Object.keys(TransformInitial).includes(key);
51
+ // 多value解析
52
+ const parseValues = (str, char = ' ') => {
53
+ let stack = 0;
54
+ let temp = '';
55
+ const result = [];
56
+ for (let i = 0; i < str.length; i++) {
57
+ if (str[i] === '(') {
58
+ stack++;
59
+ }
60
+ else if (str[i] === ')') {
61
+ stack--;
62
+ }
63
+ // 非括号内 或者 非分隔字符且非空
64
+ if (stack !== 0 || (str[i] !== char && str[i] !== ' ')) {
65
+ temp += str[i];
66
+ }
67
+ if ((stack === 0 && str[i] === char) || i === str.length - 1) {
68
+ result.push(temp);
69
+ temp = '';
70
+ }
71
+ }
72
+ return result;
73
+ };
74
+ // parse string transform, eg: transform: 'rotateX(45deg) rotateZ(0.785398rad)'
75
+ const parseTransform = (transformStr) => {
76
+ const values = parseValues(transformStr);
77
+ const transform = [];
78
+ values.forEach(item => {
79
+ const match = item.match(/([/\w]+)\((.+)\)/);
80
+ if (match && match.length >= 3) {
81
+ let key = match[1];
82
+ const val = match[2];
83
+ switch (key) {
84
+ case 'translateX':
85
+ case 'translateY':
86
+ case 'scaleX':
87
+ case 'scaleY':
88
+ case 'rotateX':
89
+ case 'rotateY':
90
+ case 'rotateZ':
91
+ case 'rotate':
92
+ case 'skewX':
93
+ case 'skewY':
94
+ case 'perspective':
95
+ // rotate 处理成 rotateZ
96
+ key = key === 'rotate' ? 'rotateZ' : key;
97
+ // 单个值处理
98
+ transform.push({ [key]: global.__formatValue(val) });
99
+ break;
100
+ case 'matrix':
101
+ transform.push({ [key]: parseValues(val, ',').map(val => +val) });
102
+ break;
103
+ case 'translate':
104
+ case 'scale':
105
+ case 'skew':
106
+ case 'translate3d': // x y 支持 z不支持
107
+ case 'scale3d': // x y 支持 z不支持
108
+ {
109
+ // 2 个以上的值处理
110
+ key = key.replace('3d', '');
111
+ const vals = parseValues(val, ',').splice(0, 3);
112
+ // scale(.5) === scaleX(.5) scaleY(.5)
113
+ if (vals.length === 1 && key === 'scale') {
114
+ vals.push(vals[0]);
115
+ }
116
+ const xyz = ['X', 'Y', 'Z'];
117
+ transform.push(...vals.map((v, index) => {
118
+ return { [`${key}${xyz[index] || ''}`]: global.__formatValue(v.trim()) };
119
+ }));
120
+ break;
121
+ }
122
+ }
123
+ }
124
+ });
125
+ return transform;
126
+ };
127
+ // format style
128
+ const formatStyle = (style) => {
129
+ if (!style.transform || Array.isArray(style.transform))
130
+ return style;
131
+ return Object.assign({}, style, {
132
+ transform: parseTransform(style.transform)
133
+ });
134
+ };
51
135
  // transform 数组转对象
52
136
  function getTransformObj(transforms) {
53
137
  'worklet';
@@ -56,7 +140,7 @@ function getTransformObj(transforms) {
56
140
  }, {});
57
141
  }
58
142
  export default function useAnimationHooks(props) {
59
- const { style: originalStyle = {}, animation, enableAnimation, transitionend, layoutRef } = props;
143
+ const { style = {}, animation, enableAnimation, transitionend, layoutRef } = props;
60
144
  const enableStyleAnimation = enableAnimation || !!animation;
61
145
  const enableAnimationRef = useRef(enableStyleAnimation);
62
146
  if (enableAnimationRef.current !== enableStyleAnimation) {
@@ -64,6 +148,7 @@ export default function useAnimationHooks(props) {
64
148
  }
65
149
  if (!enableAnimationRef.current)
66
150
  return { enableStyleAnimation: false };
151
+ const originalStyle = formatStyle(style);
67
152
  // id 标识
68
153
  const id = animation?.id || -1;
69
154
  // 有动画样式的 style key
@@ -92,7 +177,7 @@ export default function useAnimationHooks(props) {
92
177
  useEffect(() => {
93
178
  // style 更新后同步更新 lastStyleRef & shareValMap
94
179
  updateStyleVal();
95
- }, [originalStyle]);
180
+ }, [style]);
96
181
  // ** 获取动画样式prop & 驱动动画
97
182
  // eslint-disable-next-line react-hooks/rules-of-hooks
98
183
  useEffect(() => {
@@ -533,19 +533,8 @@ export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout
533
533
  }
534
534
  if (enableOffset) {
535
535
  nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
536
- const { y: navigationY = 0 } = navigation?.layout || {};
537
- layoutRef.current = {
538
- x,
539
- y: y - navigationY,
540
- width,
541
- height,
542
- offsetLeft,
543
- offsetTop: offsetTop - navigationY,
544
- _x: x,
545
- _y: y,
546
- _offsetLeft: offsetLeft,
547
- _offsetTop: offsetTop
548
- };
536
+ const { top: navigationY = 0 } = navigation?.layout || {};
537
+ layoutRef.current = { x, y: y - navigationY, width, height, offsetLeft, offsetTop: offsetTop - navigationY };
549
538
  });
550
539
  }
551
540
  onLayout && onLayout(e);
@@ -24,7 +24,7 @@ const getTouchEvent = (
24
24
  ) => {
25
25
  const { navigation, propsRef, layoutRef } = config
26
26
  const props = propsRef.current
27
- const { top: navigationY = 0 } = navigation?.layout || {}
27
+ const { y: navigationY = 0 } = navigation?.layout || {}
28
28
  const nativeEvent = event.nativeEvent
29
29
  const { timestamp, pageX, pageY, touches, changedTouches } = nativeEvent
30
30
  const { id } = props
@@ -1,12 +1,14 @@
1
1
  /**
2
- * scale-area
2
+ * scale-area
3
3
  */
4
4
 
5
5
  import { View } from 'react-native'
6
- import { JSX, forwardRef, ReactNode, useRef, useMemo, createElement } from 'react'
6
+ import { JSX, forwardRef, ReactNode, useRef, useMemo, useCallback, createElement } from 'react'
7
+ import { GestureDetector, Gesture } from 'react-native-gesture-handler'
8
+ import { useSharedValue } from 'react-native-reanimated'
7
9
  import useNodesRef, { HandlerRef } from './useNodesRef'
8
10
  import useInnerProps from './getInnerListeners'
9
- import { MovableAreaContext } from './context'
11
+ import { MovableAreaContext, MovableAreaContextValue } from './context'
10
12
  import { useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
11
13
  import Portal from './mpx-portal'
12
14
 
@@ -15,6 +17,7 @@ interface MovableAreaProps {
15
17
  children: ReactNode
16
18
  width?: number
17
19
  height?: number
20
+ 'scale-area'?: boolean
18
21
  'enable-offset'?: boolean
19
22
  'enable-var'?: boolean
20
23
  'external-var-context'?: Record<string, any>
@@ -23,8 +26,21 @@ interface MovableAreaProps {
23
26
  'parent-height'?: number
24
27
  }
25
28
 
29
+ interface MovableViewCallbacks {
30
+ onScale: (scaleInfo: {scale: number}) => void
31
+ onScaleEnd?: () => void
32
+ }
33
+
26
34
  const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaProps>((props: MovableAreaProps, ref): JSX.Element => {
27
- const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props
35
+ const {
36
+ style = {},
37
+ 'scale-area': scaleArea = false,
38
+ 'enable-var': enableVar,
39
+ 'external-var-context': externalVarContext,
40
+ 'parent-font-size': parentFontSize,
41
+ 'parent-width': parentWidth,
42
+ 'parent-height': parentHeight
43
+ } = props
28
44
 
29
45
  const {
30
46
  hasSelfPercent,
@@ -36,17 +52,67 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
36
52
  setHeight
37
53
  } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
38
54
 
39
- const movableViewRef = useRef(null)
40
- useNodesRef(props, ref, movableViewRef, {
55
+ const movableAreaRef = useRef(null)
56
+ const movableViewsValue = useSharedValue<Record<string, MovableViewCallbacks>>({})
57
+ useNodesRef(props, ref, movableAreaRef, {
41
58
  style: normalStyle
42
59
  })
43
60
 
44
- const contextValue = useMemo(() => ({
61
+ // 注册/注销 MovableView 的回调
62
+ const registerMovableView = useCallback((id: string, callbacks: { onScale?: (scaleInfo: { scale: number }) => void; onScaleEnd?: () => void }) => {
63
+ movableViewsValue.value = extendObject(movableViewsValue.value, { [id]: callbacks })
64
+ }, [])
65
+
66
+ const unregisterMovableView = useCallback((id: string) => {
67
+ delete movableViewsValue.value[id]
68
+ }, [])
69
+
70
+ // 处理区域缩放手势
71
+ const handleAreaScale = useCallback((scaleInfo: { scale: number }) => {
72
+ 'worklet'
73
+ if (scaleArea) {
74
+ // 将缩放信息广播给所有注册的 MovableView
75
+ Object.values(movableViewsValue.value).forEach((callbacks) => {
76
+ callbacks.onScale && callbacks.onScale(scaleInfo)
77
+ })
78
+ }
79
+ }, [scaleArea])
80
+
81
+ // 处理区域缩放结束
82
+ const handleAreaScaleEnd = useCallback(() => {
83
+ 'worklet'
84
+ if (scaleArea) {
85
+ // 通知所有注册的 MovableView 缩放结束
86
+ Object.values(movableViewsValue.value).forEach((callbacks) => {
87
+ callbacks.onScaleEnd && callbacks.onScaleEnd()
88
+ })
89
+ }
90
+ }, [scaleArea])
91
+
92
+ const contextValue: MovableAreaContextValue = useMemo(() => ({
45
93
  height: normalStyle.height || 10,
46
- width: normalStyle.width || 10
47
- }), [normalStyle.width, normalStyle.height])
94
+ width: normalStyle.width || 10,
95
+ scaleArea,
96
+ registerMovableView,
97
+ unregisterMovableView
98
+ }), [normalStyle.width, normalStyle.height, scaleArea])
48
99
 
49
- const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableViewRef })
100
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableAreaRef })
101
+
102
+ // 创建缩放手势
103
+ const scaleGesture = useMemo(() => {
104
+ if (!scaleArea) return null
105
+
106
+ return Gesture.Pinch()
107
+ .onUpdate((e) => {
108
+ 'worklet'
109
+ handleAreaScale(e)
110
+ })
111
+ .onEnd(() => {
112
+ 'worklet'
113
+ handleAreaScaleEnd()
114
+ })
115
+ }, [scaleArea])
50
116
 
51
117
  const innerProps = useInnerProps(
52
118
  extendObject(
@@ -55,7 +121,7 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
55
121
  layoutProps,
56
122
  {
57
123
  style: extendObject({ height: contextValue.height, width: contextValue.width }, normalStyle, layoutStyle),
58
- ref: movableViewRef
124
+ ref: movableAreaRef
59
125
  }
60
126
  ),
61
127
  [],
@@ -73,9 +139,30 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
73
139
  }
74
140
  )
75
141
  ))
142
+
143
+ // 如果启用了 scale-area,包装一个 GestureDetector
144
+ if (scaleArea && scaleGesture) {
145
+ movableComponent = createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(
146
+ GestureDetector,
147
+ { gesture: scaleGesture },
148
+ createElement(
149
+ View,
150
+ innerProps,
151
+ wrapChildren(
152
+ props,
153
+ {
154
+ hasVarDec,
155
+ varContext: varContextRef.current
156
+ }
157
+ )
158
+ )
159
+ ))
160
+ }
161
+
76
162
  if (hasPositionFixed) {
77
163
  movableComponent = createElement(Portal, null, movableComponent)
78
164
  }
165
+
79
166
  return movableComponent
80
167
  })
81
168