@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.
- package/lib/dependencies/RecordPageConfigsMapDependency.js +1 -1
- package/lib/file-loader.js +1 -1
- package/lib/index.js +78 -86
- package/lib/parser.js +1 -1
- package/lib/platform/json/wx/index.js +25 -43
- package/lib/platform/style/wx/index.js +7 -0
- package/lib/platform/template/wx/component-config/fix-component-name.js +2 -2
- package/lib/platform/template/wx/component-config/movable-view.js +1 -10
- package/lib/platform/template/wx/index.js +1 -2
- package/lib/react/index.js +1 -3
- package/lib/react/processJSON.js +11 -66
- package/lib/react/processScript.js +3 -4
- package/lib/react/script-helper.js +18 -92
- package/lib/runtime/components/react/AsyncContainer.tsx +7 -35
- package/lib/runtime/components/react/context.ts +12 -2
- package/lib/runtime/components/react/dist/AsyncContainer.jsx +4 -23
- package/lib/runtime/components/react/dist/context.js +1 -1
- package/lib/runtime/components/react/dist/getInnerListeners.js +1 -1
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +63 -9
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +308 -63
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +15 -10
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +3 -1
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +28 -14
- package/lib/runtime/components/react/dist/useAnimationHooks.js +87 -2
- package/lib/runtime/components/react/dist/utils.jsx +2 -13
- package/lib/runtime/components/react/getInnerListeners.ts +1 -1
- package/lib/runtime/components/react/mpx-movable-area.tsx +98 -11
- package/lib/runtime/components/react/mpx-movable-view.tsx +358 -64
- package/lib/runtime/components/react/mpx-scroll-view.tsx +16 -9
- package/lib/runtime/components/react/mpx-sticky-header.tsx +3 -1
- package/lib/runtime/components/react/mpx-web-view.tsx +33 -13
- package/lib/runtime/components/react/types/global.d.ts +0 -15
- package/lib/runtime/components/react/useAnimationHooks.ts +85 -2
- package/lib/runtime/components/react/utils.tsx +2 -13
- package/lib/runtime/components/web/mpx-scroll-view.vue +4 -7
- package/lib/runtime/components/web/mpx-sticky-header.vue +39 -31
- package/lib/runtime/optionProcessor.js +6 -2
- package/lib/script-setup-compiler/index.js +27 -5
- package/lib/template-compiler/bind-this.js +2 -1
- package/lib/template-compiler/compiler.js +4 -3
- package/lib/utils/dom-tag-config.js +3 -17
- package/lib/web/processTemplate.js +1 -1
- package/lib/web/script-helper.js +1 -1
- package/package.json +2 -2
- package/lib/react/LoadAsyncChunkModule.js +0 -68
- package/lib/runtime/components/react/AsyncSuspense.tsx +0 -81
- package/lib/runtime/components/react/dist/AsyncSuspense.jsx +0 -68
|
@@ -3,74 +3,30 @@ const createHelpers = require('../helpers')
|
|
|
3
3
|
const parseRequest = require('../utils/parse-request')
|
|
4
4
|
const shallowStringify = require('../utils/shallow-stringify')
|
|
5
5
|
const normalize = require('../utils/normalize')
|
|
6
|
-
const addQuery = require('../utils/add-query')
|
|
7
|
-
const path = require('path')
|
|
8
|
-
const { isBuildInReactTag } = require('../utils/dom-tag-config')
|
|
9
6
|
|
|
10
7
|
function stringifyRequest (loaderContext, request) {
|
|
11
8
|
return loaderUtils.stringifyRequest(loaderContext, request)
|
|
12
9
|
}
|
|
13
10
|
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
function getAsyncChunkName (chunkName) {
|
|
21
|
-
if (chunkName && typeof chunkName !== 'boolean') {
|
|
22
|
-
return `/* webpackChunkName: "${chunkName}/index" */`
|
|
23
|
-
}
|
|
24
|
-
return ''
|
|
25
|
-
}
|
|
11
|
+
// function getAsyncChunkName (chunkName) {
|
|
12
|
+
// if (chunkName && typeof chunkName !== 'boolean') {
|
|
13
|
+
// return `/* webpackChunkName: "${chunkName}" */`
|
|
14
|
+
// }
|
|
15
|
+
// return ''
|
|
16
|
+
// }
|
|
26
17
|
|
|
27
|
-
function
|
|
28
|
-
return `getComponent(memo(forwardRef(function(props, ref) {
|
|
29
|
-
return createElement(
|
|
30
|
-
getComponent(require(${mpxAsyncSuspense})),
|
|
31
|
-
{
|
|
32
|
-
type: 'component',
|
|
33
|
-
props: Object.assign({}, props, { ref }),
|
|
34
|
-
chunkName: ${JSON.stringify(chunkName)},
|
|
35
|
-
request: ${JSON.stringify(componentRequest)},
|
|
36
|
-
loading: getComponent(require(${fallback})),
|
|
37
|
-
getChildren: () => import(${getAsyncChunkName(chunkName)}${componentRequest})
|
|
38
|
-
}
|
|
39
|
-
)
|
|
40
|
-
})))`
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function getAsyncPage (componentName, componentRequest, chunkName, fallback, loading) {
|
|
44
|
-
fallback = fallback && `getComponent(require('${fallback}?isComponent=true'))`
|
|
45
|
-
loading = loading && `getComponent(require('${loading}?isComponent=true'))`
|
|
46
|
-
return `getComponent(function(props) {
|
|
47
|
-
return createElement(
|
|
48
|
-
getComponent(require(${mpxAsyncSuspense})),
|
|
49
|
-
{
|
|
50
|
-
type: 'page',
|
|
51
|
-
props: props,
|
|
52
|
-
chunkName: ${JSON.stringify(chunkName)},
|
|
53
|
-
request: ${JSON.stringify(componentRequest)},
|
|
54
|
-
fallback: ${fallback},
|
|
55
|
-
loading: ${loading},
|
|
56
|
-
getChildren: () => import(${getAsyncChunkName(chunkName)}${componentRequest})
|
|
57
|
-
}
|
|
58
|
-
)
|
|
59
|
-
})`
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig, rnConfig }) {
|
|
18
|
+
function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig }) {
|
|
63
19
|
let firstPage = ''
|
|
64
20
|
const pagesMap = {}
|
|
65
21
|
Object.keys(localPagesMap).forEach((pagePath) => {
|
|
66
22
|
const pageCfg = localPagesMap[pagePath]
|
|
67
23
|
const pageRequest = stringifyRequest(loaderContext, pageCfg.resource)
|
|
68
|
-
if (pageCfg.async) {
|
|
69
|
-
|
|
70
|
-
} else {
|
|
24
|
+
// if (pageCfg.async) {
|
|
25
|
+
// pagesMap[pagePath] = `lazy(function(){return import(${getAsyncChunkName(pageCfg.async)} ${pageRequest}).then(function(res){return getComponent(res, {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})})})`
|
|
26
|
+
// } else {
|
|
71
27
|
// 为了保持小程序中app->page->component的js执行顺序,所有的page和component都改为require引入
|
|
72
|
-
|
|
73
|
-
}
|
|
28
|
+
pagesMap[pagePath] = `getComponent(require(${pageRequest}), {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})`
|
|
29
|
+
// }
|
|
74
30
|
if (pagePath === jsonConfig.entryPagePath) {
|
|
75
31
|
firstPage = pagePath
|
|
76
32
|
}
|
|
@@ -86,45 +42,16 @@ function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig, rnConfig })
|
|
|
86
42
|
|
|
87
43
|
function buildComponentsMap ({ localComponentsMap, builtInComponentsMap, loaderContext, jsonConfig }) {
|
|
88
44
|
const componentsMap = {}
|
|
89
|
-
const mpx = loaderContext.getMpx()
|
|
90
45
|
if (localComponentsMap) {
|
|
91
46
|
Object.keys(localComponentsMap).forEach((componentName) => {
|
|
92
47
|
const componentCfg = localComponentsMap[componentName]
|
|
93
48
|
const componentRequest = stringifyRequest(loaderContext, componentCfg.resource)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (placeholderCfg.async) {
|
|
101
|
-
loaderContext.emitWarning(
|
|
102
|
-
new Error(`[json processor][${loaderContext.resource}]: componentPlaceholder ${placeholder} should not be a async component, please check!`)
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, placeholderRequest)
|
|
106
|
-
} else if (mpx.globalComponents[placeholder]) {
|
|
107
|
-
const { queryObj, rawResourcePath } = parseRequest(mpx.globalComponents[placeholder])
|
|
108
|
-
const placeholderRequest = JSON.stringify(path.resolve(queryObj.context, rawResourcePath))
|
|
109
|
-
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, placeholderRequest)
|
|
110
|
-
} else {
|
|
111
|
-
const tag = `mpx-${placeholder}`
|
|
112
|
-
if (!isBuildInReactTag(tag)) {
|
|
113
|
-
loaderContext.emitError(
|
|
114
|
-
new Error(`[json processor][${loaderContext.resource}]: componentPlaceholder ${placeholder} is not built-in component, please check!`)
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, getMpxComponentRequest(tag))
|
|
118
|
-
}
|
|
119
|
-
} else {
|
|
120
|
-
loaderContext.emitError(
|
|
121
|
-
new Error(`[json processor][${loaderContext.resource}]: ${componentName} has no componentPlaceholder, please check!`)
|
|
122
|
-
)
|
|
123
|
-
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async)
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
componentsMap[componentName] = `getComponent(require(${componentRequest}), {displayName: ${JSON.stringify(componentName)}})`
|
|
127
|
-
}
|
|
49
|
+
// RN中暂不支持异步加载
|
|
50
|
+
// if (componentCfg.async) {
|
|
51
|
+
// componentsMap[componentName] = `lazy(function(){return import(${getAsyncChunkName(componentCfg.async)}${componentRequest}).then(function(res){return getComponent(res, {displayName: ${JSON.stringify(componentName)}})})})`
|
|
52
|
+
// } else {
|
|
53
|
+
componentsMap[componentName] = `getComponent(require(${componentRequest}), {displayName: ${JSON.stringify(componentName)}})`
|
|
54
|
+
// }
|
|
128
55
|
})
|
|
129
56
|
}
|
|
130
57
|
if (builtInComponentsMap) {
|
|
@@ -180,7 +107,6 @@ global.__mpxPageConfig = ${JSON.stringify(jsonConfig.window)}
|
|
|
180
107
|
global.__getAppComponents = function () {
|
|
181
108
|
return ${shallowStringify(componentsMap)}
|
|
182
109
|
}
|
|
183
|
-
global.__preloadRule = ${JSON.stringify(jsonConfig.preloadRule)}
|
|
184
110
|
global.currentInject.getPages = function () {
|
|
185
111
|
return ${shallowStringify(pagesMap)}
|
|
186
112
|
}
|
|
@@ -1,29 +1,6 @@
|
|
|
1
|
-
import { ComponentType, ReactNode, Component, Suspense } from 'react'
|
|
1
|
+
import { ComponentType, ReactNode, Component, Fragment, Suspense } from 'react'
|
|
2
2
|
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native'
|
|
3
3
|
import FastImage from '@d11/react-native-fast-image'
|
|
4
|
-
import Animated, { useAnimatedStyle } from 'react-native-reanimated'
|
|
5
|
-
|
|
6
|
-
type PageWrapper = {
|
|
7
|
-
children: ReactNode
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const PageWrapper = ({ children }: PageWrapper) => {
|
|
11
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
12
|
-
transform: [{ translateY: -0 }],
|
|
13
|
-
flexBasis: 'auto',
|
|
14
|
-
flex: 1
|
|
15
|
-
}))
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<Animated.View
|
|
19
|
-
style={[
|
|
20
|
-
animatedStyle
|
|
21
|
-
]}
|
|
22
|
-
>
|
|
23
|
-
{children}
|
|
24
|
-
</Animated.View>
|
|
25
|
-
)
|
|
26
|
-
}
|
|
27
4
|
|
|
28
5
|
const styles = StyleSheet.create({
|
|
29
6
|
container: {
|
|
@@ -82,7 +59,7 @@ interface PropsType<T extends AsyncType> {
|
|
|
82
59
|
props: object
|
|
83
60
|
loading: ComponentType<unknown>
|
|
84
61
|
fallback: ComponentType<unknown>
|
|
85
|
-
children: (props:
|
|
62
|
+
children: (props: unknown) => ReactNode
|
|
86
63
|
}
|
|
87
64
|
|
|
88
65
|
interface StateType {
|
|
@@ -95,7 +72,7 @@ interface ComponentError extends Error {
|
|
|
95
72
|
type: 'timeout' | 'fail'
|
|
96
73
|
}
|
|
97
74
|
|
|
98
|
-
|
|
75
|
+
const DefaultLoading = () => {
|
|
99
76
|
return (
|
|
100
77
|
<View style={styles.container}>
|
|
101
78
|
<FastImage
|
|
@@ -106,11 +83,11 @@ export const DefaultLoading = () => {
|
|
|
106
83
|
)
|
|
107
84
|
}
|
|
108
85
|
|
|
109
|
-
|
|
86
|
+
interface DefaultFallbackProps {
|
|
110
87
|
onReload: () => void
|
|
111
88
|
}
|
|
112
89
|
|
|
113
|
-
|
|
90
|
+
const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
|
|
114
91
|
return (
|
|
115
92
|
<View style={styles.container}>
|
|
116
93
|
<Image
|
|
@@ -200,16 +177,11 @@ export default class AsyncContainer extends Component<PropsType<AsyncType>, Stat
|
|
|
200
177
|
|
|
201
178
|
render () {
|
|
202
179
|
if (this.state.hasError) {
|
|
203
|
-
|
|
204
|
-
return this.errorFallback
|
|
205
|
-
} else {
|
|
206
|
-
return (<PageWrapper>{this.errorFallback}</PageWrapper>)
|
|
207
|
-
}
|
|
180
|
+
return this.errorFallback
|
|
208
181
|
} else {
|
|
209
182
|
return (
|
|
210
183
|
<Suspense fallback={this.suspenseFallback} key={this.state.key}>
|
|
211
|
-
{
|
|
212
|
-
{/* {this.props.children(this.props.props)} */}
|
|
184
|
+
{this.props.children(this.props.props)}
|
|
213
185
|
</Suspense>
|
|
214
186
|
)
|
|
215
187
|
}
|
|
@@ -51,14 +51,24 @@ export interface RouteContextValue {
|
|
|
51
51
|
pageId: number
|
|
52
52
|
navigation: Record<string, any>
|
|
53
53
|
}
|
|
54
|
+
export interface MovableAreaContextValue {
|
|
55
|
+
width: number
|
|
56
|
+
height: number
|
|
57
|
+
scaleArea: boolean
|
|
58
|
+
onAreaScale?: (scaleInfo: { scale: number }) => void
|
|
59
|
+
registerMovableView?: (id: string, callbacks: {
|
|
60
|
+
onScale: (scaleInfo: { scale: number }) => void
|
|
61
|
+
onScaleEnd?: () => void
|
|
62
|
+
}) => void
|
|
63
|
+
unregisterMovableView?: (id: string) => void
|
|
64
|
+
}
|
|
54
65
|
|
|
66
|
+
export const MovableAreaContext = createContext<MovableAreaContextValue>({ width: 0, height: 0, scaleArea: false })
|
|
55
67
|
export interface StickyContextValue {
|
|
56
68
|
registerStickyHeader: Function,
|
|
57
69
|
unregisterStickyHeader: Function
|
|
58
70
|
}
|
|
59
71
|
|
|
60
|
-
export const MovableAreaContext = createContext({ width: 0, height: 0 })
|
|
61
|
-
|
|
62
72
|
export const FormContext = createContext<FormContextValue | null>(null)
|
|
63
73
|
|
|
64
74
|
export const CheckboxGroupContext = createContext<GroupContextValue | null>(null)
|
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import { Component, Suspense } from 'react';
|
|
2
2
|
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
3
|
import FastImage from '@d11/react-native-fast-image';
|
|
4
|
-
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
5
|
-
export const PageWrapper = ({ children }) => {
|
|
6
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
7
|
-
transform: [{ translateY: -0 }],
|
|
8
|
-
flexBasis: 'auto',
|
|
9
|
-
flex: 1
|
|
10
|
-
}));
|
|
11
|
-
return (<Animated.View style={[
|
|
12
|
-
animatedStyle
|
|
13
|
-
]}>
|
|
14
|
-
{children}
|
|
15
|
-
</Animated.View>);
|
|
16
|
-
};
|
|
17
4
|
const styles = StyleSheet.create({
|
|
18
5
|
container: {
|
|
19
6
|
flex: 1,
|
|
@@ -63,12 +50,12 @@ const styles = StyleSheet.create({
|
|
|
63
50
|
textAlign: 'center'
|
|
64
51
|
}
|
|
65
52
|
});
|
|
66
|
-
|
|
53
|
+
const DefaultLoading = () => {
|
|
67
54
|
return (<View style={styles.container}>
|
|
68
55
|
<FastImage style={styles.loadingImage} source={{ uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif' }} resizeMode={FastImage.resizeMode.contain}></FastImage>
|
|
69
56
|
</View>);
|
|
70
57
|
};
|
|
71
|
-
|
|
58
|
+
const DefaultFallback = ({ onReload }) => {
|
|
72
59
|
return (<View style={styles.container}>
|
|
73
60
|
<Image source={{ uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png' }} style={styles.errorImage} resizeMode="contain"/>
|
|
74
61
|
<Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
|
|
@@ -143,17 +130,11 @@ export default class AsyncContainer extends Component {
|
|
|
143
130
|
}
|
|
144
131
|
render() {
|
|
145
132
|
if (this.state.hasError) {
|
|
146
|
-
|
|
147
|
-
return this.errorFallback;
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
return (<PageWrapper>{this.errorFallback}</PageWrapper>);
|
|
151
|
-
}
|
|
133
|
+
return this.errorFallback;
|
|
152
134
|
}
|
|
153
135
|
else {
|
|
154
136
|
return (<Suspense fallback={this.suspenseFallback} key={this.state.key}>
|
|
155
|
-
{
|
|
156
|
-
{/* {this.props.children(this.props.props)} */}
|
|
137
|
+
{this.props.children(this.props.props)}
|
|
157
138
|
</Suspense>);
|
|
158
139
|
}
|
|
159
140
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createContext } from 'react';
|
|
2
2
|
import { Animated } from 'react-native';
|
|
3
3
|
import { noop } from '@mpxjs/utils';
|
|
4
|
-
export const MovableAreaContext = createContext({ width: 0, height: 0 });
|
|
4
|
+
export const MovableAreaContext = createContext({ width: 0, height: 0, scaleArea: false });
|
|
5
5
|
export const FormContext = createContext(null);
|
|
6
6
|
export const CheckboxGroupContext = createContext(null);
|
|
7
7
|
export const RadioGroupContext = createContext(null);
|
|
@@ -8,7 +8,7 @@ const globalEventState = {
|
|
|
8
8
|
const getTouchEvent = (type, event, config) => {
|
|
9
9
|
const { navigation, propsRef, layoutRef } = config;
|
|
10
10
|
const props = propsRef.current;
|
|
11
|
-
const {
|
|
11
|
+
const { y: navigationY = 0 } = navigation?.layout || {};
|
|
12
12
|
const nativeEvent = event.nativeEvent;
|
|
13
13
|
const { timestamp, pageX, pageY, touches, changedTouches } = nativeEvent;
|
|
14
14
|
const { id } = props;
|
|
@@ -1,33 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* ✔ scale-area
|
|
3
3
|
*/
|
|
4
4
|
import { View } from 'react-native';
|
|
5
|
-
import { forwardRef, useRef, useMemo, createElement } from 'react';
|
|
5
|
+
import { forwardRef, useRef, useMemo, useCallback, createElement } from 'react';
|
|
6
|
+
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
7
|
+
import { useSharedValue } from 'react-native-reanimated';
|
|
6
8
|
import useNodesRef from './useNodesRef';
|
|
7
9
|
import useInnerProps from './getInnerListeners';
|
|
8
10
|
import { MovableAreaContext } from './context';
|
|
9
11
|
import { useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
|
|
10
12
|
import Portal from './mpx-portal';
|
|
11
13
|
const _MovableArea = forwardRef((props, ref) => {
|
|
12
|
-
const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
14
|
+
const { style = {}, 'scale-area': scaleArea = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
13
15
|
const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, hasPositionFixed, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
+
const movableAreaRef = useRef(null);
|
|
17
|
+
const movableViewsValue = useSharedValue({});
|
|
18
|
+
useNodesRef(props, ref, movableAreaRef, {
|
|
16
19
|
style: normalStyle
|
|
17
20
|
});
|
|
21
|
+
// 注册/注销 MovableView 的回调
|
|
22
|
+
const registerMovableView = useCallback((id, callbacks) => {
|
|
23
|
+
movableViewsValue.value = extendObject(movableViewsValue.value, { [id]: callbacks });
|
|
24
|
+
}, []);
|
|
25
|
+
const unregisterMovableView = useCallback((id) => {
|
|
26
|
+
delete movableViewsValue.value[id];
|
|
27
|
+
}, []);
|
|
28
|
+
// 处理区域缩放手势
|
|
29
|
+
const handleAreaScale = useCallback((scaleInfo) => {
|
|
30
|
+
'worklet';
|
|
31
|
+
if (scaleArea) {
|
|
32
|
+
// 将缩放信息广播给所有注册的 MovableView
|
|
33
|
+
Object.values(movableViewsValue.value).forEach((callbacks) => {
|
|
34
|
+
callbacks.onScale && callbacks.onScale(scaleInfo);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}, [scaleArea]);
|
|
38
|
+
// 处理区域缩放结束
|
|
39
|
+
const handleAreaScaleEnd = useCallback(() => {
|
|
40
|
+
'worklet';
|
|
41
|
+
if (scaleArea) {
|
|
42
|
+
// 通知所有注册的 MovableView 缩放结束
|
|
43
|
+
Object.values(movableViewsValue.value).forEach((callbacks) => {
|
|
44
|
+
callbacks.onScaleEnd && callbacks.onScaleEnd();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}, [scaleArea]);
|
|
18
48
|
const contextValue = useMemo(() => ({
|
|
19
49
|
height: normalStyle.height || 10,
|
|
20
|
-
width: normalStyle.width || 10
|
|
21
|
-
|
|
22
|
-
|
|
50
|
+
width: normalStyle.width || 10,
|
|
51
|
+
scaleArea,
|
|
52
|
+
registerMovableView,
|
|
53
|
+
unregisterMovableView
|
|
54
|
+
}), [normalStyle.width, normalStyle.height, scaleArea]);
|
|
55
|
+
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: movableAreaRef });
|
|
56
|
+
// 创建缩放手势
|
|
57
|
+
const scaleGesture = useMemo(() => {
|
|
58
|
+
if (!scaleArea)
|
|
59
|
+
return null;
|
|
60
|
+
return Gesture.Pinch()
|
|
61
|
+
.onUpdate((e) => {
|
|
62
|
+
'worklet';
|
|
63
|
+
handleAreaScale(e);
|
|
64
|
+
})
|
|
65
|
+
.onEnd(() => {
|
|
66
|
+
'worklet';
|
|
67
|
+
handleAreaScaleEnd();
|
|
68
|
+
});
|
|
69
|
+
}, [scaleArea]);
|
|
23
70
|
const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
|
|
24
71
|
style: extendObject({ height: contextValue.height, width: contextValue.width }, normalStyle, layoutStyle),
|
|
25
|
-
ref:
|
|
72
|
+
ref: movableAreaRef
|
|
26
73
|
}), [], { layoutRef });
|
|
27
74
|
let movableComponent = createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(View, innerProps, wrapChildren(props, {
|
|
28
75
|
hasVarDec,
|
|
29
76
|
varContext: varContextRef.current
|
|
30
77
|
})));
|
|
78
|
+
// 如果启用了 scale-area,包装一个 GestureDetector
|
|
79
|
+
if (scaleArea && scaleGesture) {
|
|
80
|
+
movableComponent = createElement(MovableAreaContext.Provider, { value: contextValue }, createElement(GestureDetector, { gesture: scaleGesture }, createElement(View, innerProps, wrapChildren(props, {
|
|
81
|
+
hasVarDec,
|
|
82
|
+
varContext: varContextRef.current
|
|
83
|
+
}))));
|
|
84
|
+
}
|
|
31
85
|
if (hasPositionFixed) {
|
|
32
86
|
movableComponent = createElement(Portal, null, movableComponent);
|
|
33
87
|
}
|