@mpxjs/webpack-plugin 2.10.7-beta.9 → 2.10.8

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 (42) hide show
  1. package/LICENSE +433 -0
  2. package/lib/dependencies/RequireExternalDependency.js +61 -0
  3. package/lib/file-loader.js +3 -2
  4. package/lib/index.js +60 -15
  5. package/lib/json-compiler/index.js +1 -0
  6. package/lib/parser.js +1 -1
  7. package/lib/platform/json/wx/index.js +43 -25
  8. package/lib/platform/template/wx/component-config/fix-component-name.js +2 -2
  9. package/lib/platform/template/wx/component-config/movable-view.js +10 -1
  10. package/lib/platform/template/wx/index.js +2 -1
  11. package/lib/react/LoadAsyncChunkModule.js +74 -0
  12. package/lib/react/index.js +3 -1
  13. package/lib/react/processJSON.js +74 -13
  14. package/lib/react/processScript.js +6 -6
  15. package/lib/react/script-helper.js +100 -41
  16. package/lib/runtime/components/react/context.ts +2 -12
  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-async-suspense.jsx +135 -0
  20. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +9 -63
  21. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +58 -301
  22. package/lib/runtime/components/react/dist/mpx-swiper.jsx +27 -53
  23. package/lib/runtime/components/react/dist/mpx-web-view.jsx +14 -28
  24. package/lib/runtime/components/react/dist/useAnimationHooks.js +2 -87
  25. package/lib/runtime/components/react/getInnerListeners.ts +1 -1
  26. package/lib/runtime/components/react/mpx-async-suspense.tsx +180 -0
  27. package/lib/runtime/components/react/mpx-movable-area.tsx +11 -98
  28. package/lib/runtime/components/react/mpx-movable-view.tsx +60 -350
  29. package/lib/runtime/components/react/mpx-swiper.tsx +25 -53
  30. package/lib/runtime/components/react/mpx-web-view.tsx +13 -33
  31. package/lib/runtime/components/react/types/global.d.ts +15 -0
  32. package/lib/runtime/components/react/useAnimationHooks.ts +2 -85
  33. package/lib/runtime/optionProcessorReact.d.ts +18 -0
  34. package/lib/runtime/optionProcessorReact.js +30 -0
  35. package/lib/script-setup-compiler/index.js +27 -5
  36. package/lib/template-compiler/compiler.js +4 -3
  37. package/lib/utils/dom-tag-config.js +17 -3
  38. package/lib/utils/trans-async-sub-rules.js +19 -0
  39. package/lib/web/script-helper.js +1 -1
  40. package/package.json +4 -4
  41. package/lib/runtime/components/react/AsyncContainer.tsx +0 -189
  42. package/lib/runtime/components/react/dist/AsyncContainer.jsx +0 -141
@@ -1,6 +1,7 @@
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';
4
5
  import { getCustomEvent } from './getInnerListeners';
5
6
  import { promisify, redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy';
6
7
  import { WebView } from 'react-native-webview';
@@ -55,8 +56,8 @@ const _WebView = forwardRef((props, ref) => {
55
56
  const webViewRef = useRef(null);
56
57
  const fristLoaded = useRef(false);
57
58
  const isLoadError = useRef(false);
59
+ const isNavigateBack = useRef(false);
58
60
  const statusCode = useRef('');
59
- const [isLoaded, setIsLoaded] = useState(true);
60
61
  const defaultWebViewStyle = {
61
62
  position: 'absolute',
62
63
  left: 0,
@@ -64,27 +65,18 @@ const _WebView = forwardRef((props, ref) => {
64
65
  top: 0,
65
66
  bottom: 0
66
67
  };
67
- const canGoBack = useRef(false);
68
- const isNavigateBack = useRef(false);
69
- const beforeRemoveHandle = (e) => {
70
- if (canGoBack.current && !isNavigateBack.current) {
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 {
71
76
  webViewRef.current?.goBack();
72
- e.preventDefault();
73
77
  }
74
78
  isNavigateBack.current = false;
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
- // }, [])
79
+ });
88
80
  useNodesRef(props, ref, webViewRef, {
89
81
  style: defaultWebViewStyle
90
82
  });
@@ -131,13 +123,13 @@ const _WebView = forwardRef((props, ref) => {
131
123
  };
132
124
  const _changeUrl = function (navState) {
133
125
  if (navState.navigationType) { // navigationType这个事件在页面开始加载时和页面加载完成时都会被触发所以判断这个避免其他无效触发执行该逻辑
134
- canGoBack.current = navState.canGoBack;
135
126
  currentPage.__webViewUrl = navState.url;
127
+ setIsIntercept(navState.canGoBack);
136
128
  }
137
129
  };
138
130
  const _onLoadProgress = function (event) {
139
131
  if (__mpx_mode__ !== 'ios') {
140
- canGoBack.current = event.nativeEvent.canGoBack;
132
+ setIsIntercept(event.nativeEvent.canGoBack);
141
133
  }
142
134
  };
143
135
  const _message = function (res) {
@@ -227,7 +219,6 @@ const _WebView = forwardRef((props, ref) => {
227
219
  };
228
220
  const onLoadEndHandle = function (res) {
229
221
  fristLoaded.current = true;
230
- setIsLoaded(true);
231
222
  const src = res.nativeEvent?.url;
232
223
  if (isLoadError.current) {
233
224
  isLoadError.current = false;
@@ -275,18 +266,13 @@ const _WebView = forwardRef((props, ref) => {
275
266
  setPageLoadErr(true);
276
267
  }
277
268
  };
278
- const onLoadStart = function () {
279
- if (!fristLoaded.current) {
280
- setIsLoaded(false);
281
- }
282
- };
283
269
  return (<Portal>
284
270
  {pageLoadErr
285
271
  ? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
286
272
  <View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
287
273
  <View style={styles.loadErrorButton} onTouchEnd={_reload}><Text style={{ fontSize: 12, color: '#666666' }}>{currentErrorText.button}</Text></View>
288
274
  </View>)
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>)}
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>)}
290
276
  </Portal>);
291
277
  });
292
278
  _WebView.displayName = 'MpxWebview';
@@ -48,90 +48,6 @@ 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
- };
135
51
  // transform 数组转对象
136
52
  function getTransformObj(transforms) {
137
53
  'worklet';
@@ -140,7 +56,7 @@ function getTransformObj(transforms) {
140
56
  }, {});
141
57
  }
142
58
  export default function useAnimationHooks(props) {
143
- const { style = {}, animation, enableAnimation, transitionend, layoutRef } = props;
59
+ const { style: originalStyle = {}, animation, enableAnimation, transitionend, layoutRef } = props;
144
60
  const enableStyleAnimation = enableAnimation || !!animation;
145
61
  const enableAnimationRef = useRef(enableStyleAnimation);
146
62
  if (enableAnimationRef.current !== enableStyleAnimation) {
@@ -148,7 +64,6 @@ export default function useAnimationHooks(props) {
148
64
  }
149
65
  if (!enableAnimationRef.current)
150
66
  return { enableStyleAnimation: false };
151
- const originalStyle = formatStyle(style);
152
67
  // id 标识
153
68
  const id = animation?.id || -1;
154
69
  // 有动画样式的 style key
@@ -177,7 +92,7 @@ export default function useAnimationHooks(props) {
177
92
  useEffect(() => {
178
93
  // style 更新后同步更新 lastStyleRef & shareValMap
179
94
  updateStyleVal();
180
- }, [style]);
95
+ }, [originalStyle]);
181
96
  // ** 获取动画样式prop & 驱动动画
182
97
  // eslint-disable-next-line react-hooks/rules-of-hooks
183
98
  useEffect(() => {
@@ -24,7 +24,7 @@ const getTouchEvent = (
24
24
  ) => {
25
25
  const { navigation, propsRef, layoutRef } = config
26
26
  const props = propsRef.current
27
- const { y: navigationY = 0 } = navigation?.layout || {}
27
+ const { top: navigationY = 0 } = navigation?.layout || {}
28
28
  const nativeEvent = event.nativeEvent
29
29
  const { timestamp, pageX, pageY, touches, changedTouches } = nativeEvent
30
30
  const { id } = props
@@ -0,0 +1,180 @@
1
+ import { useState, ComponentType, useEffect, useCallback, useRef, ReactNode, createElement } from 'react'
2
+ import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native'
3
+ import FastImage from '@d11/react-native-fast-image'
4
+
5
+ const asyncChunkMap = new Map()
6
+
7
+ const styles = StyleSheet.create({
8
+ container: {
9
+ flex: 1,
10
+ padding: 20,
11
+ backgroundColor: '#fff'
12
+ },
13
+ loadingImage: {
14
+ width: 100,
15
+ height: 100,
16
+ marginTop: 220,
17
+ alignSelf: 'center'
18
+ },
19
+ buttonText: {
20
+ color: '#fff',
21
+ fontSize: 16,
22
+ fontWeight: '500',
23
+ textAlign: 'center'
24
+ },
25
+ errorImage: {
26
+ marginTop: 80,
27
+ width: 220,
28
+ aspectRatio: 1,
29
+ alignSelf: 'center'
30
+ },
31
+ errorText: {
32
+ fontSize: 16,
33
+ textAlign: 'center',
34
+ color: '#333',
35
+ marginBottom: 20
36
+ },
37
+ retryButton: {
38
+ position: 'absolute',
39
+ bottom: 54,
40
+ left: 20,
41
+ right: 20,
42
+ backgroundColor: '#fff',
43
+ paddingVertical: 15,
44
+ borderRadius: 30,
45
+ marginTop: 40,
46
+ borderWidth: 1,
47
+ borderColor: '#FF5F00'
48
+ },
49
+ retryButtonText: {
50
+ color: '#FF5F00',
51
+ fontSize: 16,
52
+ fontWeight: '500',
53
+ textAlign: 'center'
54
+ }
55
+ })
56
+
57
+ interface DefaultFallbackProps {
58
+ onReload: () => void
59
+ }
60
+
61
+ const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
62
+ return (
63
+ <View style={styles.container}>
64
+ <Image
65
+ source={{
66
+ uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
67
+ }}
68
+ style={styles.errorImage}
69
+ resizeMode="contain"
70
+ />
71
+ <Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
72
+ <TouchableOpacity
73
+ style={styles.retryButton}
74
+ onPress={onReload}
75
+ activeOpacity={0.7}
76
+ >
77
+ <Text style={styles.retryButtonText}>点击重试</Text>
78
+ </TouchableOpacity>
79
+ </View>
80
+ )
81
+ }
82
+
83
+ const DefaultLoading = () => {
84
+ return (
85
+ <View style={styles.container}>
86
+ <FastImage
87
+ style={styles.loadingImage}
88
+ source={{
89
+ uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
90
+ }}
91
+ resizeMode={FastImage.resizeMode.contain}
92
+ ></FastImage>
93
+ </View>
94
+ )
95
+ }
96
+
97
+ interface AsyncSuspenseProps {
98
+ type: 'component' | 'page'
99
+ chunkName: string
100
+ moduleId: string
101
+ innerProps: any,
102
+ loading?: ComponentType<unknown>
103
+ fallback?: ComponentType<unknown>
104
+ getChildren: () => Promise<ReactNode>
105
+ }
106
+
107
+ type ComponentStauts = 'pending' | 'error' | 'loaded'
108
+
109
+ const AsyncSuspense: React.FC<AsyncSuspenseProps> = ({
110
+ type,
111
+ innerProps,
112
+ chunkName,
113
+ moduleId,
114
+ loading,
115
+ fallback,
116
+ getChildren
117
+ }) => {
118
+ const [status, setStatus] = useState<ComponentStauts>('pending')
119
+ const chunkLoaded = asyncChunkMap.has(moduleId)
120
+ const loadChunkPromise = useRef<null | Promise<ReactNode>>(null)
121
+
122
+ const reloadPage = useCallback(() => {
123
+ setStatus('pending')
124
+ }, [])
125
+
126
+ useEffect(() => {
127
+ let cancelled = false
128
+ if (!chunkLoaded && status === 'pending') {
129
+ if (loadChunkPromise.current) {
130
+ loadChunkPromise
131
+ .current.then((res: ReactNode) => {
132
+ if (cancelled) return
133
+ asyncChunkMap.set(moduleId, res)
134
+ setStatus('loaded')
135
+ })
136
+ .catch((e) => {
137
+ if (cancelled) return
138
+ if (type === 'component') {
139
+ global.onLazyLoadError({
140
+ type: 'subpackage',
141
+ subpackage: [chunkName],
142
+ errMsg: `loadSubpackage: ${e.type}`
143
+ })
144
+ }
145
+ loadChunkPromise.current = null
146
+ setStatus('error')
147
+ })
148
+ }
149
+ }
150
+
151
+ return () => {
152
+ cancelled = true
153
+ }
154
+ }, [status])
155
+
156
+ if (chunkLoaded) {
157
+ const Comp = asyncChunkMap.get(moduleId)
158
+ return createElement(Comp, innerProps)
159
+ } else if (status === 'error') {
160
+ if (type === 'page') {
161
+ fallback = fallback || DefaultFallback
162
+ return createElement(fallback as ComponentType<DefaultFallbackProps>, { onReload: reloadPage })
163
+ } else {
164
+ return fallback ? createElement(fallback, innerProps) : null
165
+ }
166
+ } else {
167
+ if (!loadChunkPromise.current) {
168
+ loadChunkPromise.current = getChildren()
169
+ }
170
+ if (type === 'page') {
171
+ return createElement(loading || DefaultLoading)
172
+ } else {
173
+ return fallback ? createElement(fallback, innerProps) : null
174
+ }
175
+ }
176
+ }
177
+
178
+ AsyncSuspense.displayName = 'MpxAsyncSuspense'
179
+
180
+ export default AsyncSuspense
@@ -1,14 +1,12 @@
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, useCallback, createElement } from 'react'
7
- import { GestureDetector, Gesture } from 'react-native-gesture-handler'
8
- import { useSharedValue } from 'react-native-reanimated'
6
+ import { JSX, forwardRef, ReactNode, useRef, useMemo, createElement } from 'react'
9
7
  import useNodesRef, { HandlerRef } from './useNodesRef'
10
8
  import useInnerProps from './getInnerListeners'
11
- import { MovableAreaContext, MovableAreaContextValue } from './context'
9
+ import { MovableAreaContext } from './context'
12
10
  import { useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
13
11
  import Portal from './mpx-portal'
14
12
 
@@ -17,7 +15,6 @@ interface MovableAreaProps {
17
15
  children: ReactNode
18
16
  width?: number
19
17
  height?: number
20
- 'scale-area'?: boolean
21
18
  'enable-offset'?: boolean
22
19
  'enable-var'?: boolean
23
20
  'external-var-context'?: Record<string, any>
@@ -26,21 +23,8 @@ interface MovableAreaProps {
26
23
  'parent-height'?: number
27
24
  }
28
25
 
29
- interface MovableViewCallbacks {
30
- onScale: (scaleInfo: {scale: number}) => void
31
- onScaleEnd?: () => void
32
- }
33
-
34
26
  const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaProps>((props: MovableAreaProps, ref): JSX.Element => {
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
27
+ const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props
44
28
 
45
29
  const {
46
30
  hasSelfPercent,
@@ -52,67 +36,17 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
52
36
  setHeight
53
37
  } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
54
38
 
55
- const movableAreaRef = useRef(null)
56
- const movableViewsValue = useSharedValue<Record<string, MovableViewCallbacks>>({})
57
- useNodesRef(props, ref, movableAreaRef, {
39
+ const movableViewRef = useRef(null)
40
+ useNodesRef(props, ref, movableViewRef, {
58
41
  style: normalStyle
59
42
  })
60
43
 
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(() => ({
44
+ const contextValue = useMemo(() => ({
93
45
  height: normalStyle.height || 10,
94
- width: normalStyle.width || 10,
95
- scaleArea,
96
- registerMovableView,
97
- unregisterMovableView
98
- }), [normalStyle.width, normalStyle.height, scaleArea])
46
+ width: normalStyle.width || 10
47
+ }), [normalStyle.width, normalStyle.height])
99
48
 
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])
49
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableViewRef })
116
50
 
117
51
  const innerProps = useInnerProps(
118
52
  extendObject(
@@ -121,7 +55,7 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
121
55
  layoutProps,
122
56
  {
123
57
  style: extendObject({ height: contextValue.height, width: contextValue.width }, normalStyle, layoutStyle),
124
- ref: movableAreaRef
58
+ ref: movableViewRef
125
59
  }
126
60
  ),
127
61
  [],
@@ -139,30 +73,9 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
139
73
  }
140
74
  )
141
75
  ))
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
-
162
76
  if (hasPositionFixed) {
163
77
  movableComponent = createElement(Portal, null, movableComponent)
164
78
  }
165
-
166
79
  return movableComponent
167
80
  })
168
81