@mpxjs/webpack-plugin 2.10.4-beta.18 → 2.10.4-beta.19-input
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/runtime/components/react/dist/getInnerListeners.js +36 -22
- package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +145 -0
- package/lib/runtime/components/react/dist/mpx-button.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-canvas/Image.js +2 -4
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +20 -17
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-image.jsx +33 -20
- package/lib/runtime/components/react/dist/mpx-input.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-label.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +8 -3
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +205 -79
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -13
- package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +8 -7
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +29 -11
- package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +3 -5
- package/lib/runtime/components/react/dist/mpx-progress.jsx +163 -0
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +9 -2
- package/lib/runtime/components/react/dist/mpx-radio.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +104 -51
- package/lib/runtime/components/react/dist/mpx-slider.jsx +321 -0
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +3 -1
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +11 -9
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +203 -141
- package/lib/runtime/components/react/dist/mpx-switch.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-text.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-video.jsx +7 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +28 -26
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +34 -29
- package/lib/runtime/components/react/dist/useAnimationHooks.js +12 -89
- package/lib/runtime/components/react/dist/utils.jsx +199 -114
- package/lib/runtime/components/react/mpx-input.tsx +6 -6
- package/lib/template-compiler/compiler.js +1 -1
- package/package.json +1 -1
|
@@ -3,12 +3,13 @@ import { collectDataset } from '@mpxjs/utils';
|
|
|
3
3
|
import { omit, extendObject, useNavigation } from './utils';
|
|
4
4
|
import eventConfigMap from './event.config';
|
|
5
5
|
const globalEventState = {
|
|
6
|
-
needPress: true
|
|
6
|
+
needPress: true,
|
|
7
|
+
identifier: null
|
|
7
8
|
};
|
|
8
9
|
const getTouchEvent = (type, event, config) => {
|
|
9
10
|
const { navigation, propsRef, layoutRef } = config;
|
|
10
11
|
const props = propsRef.current;
|
|
11
|
-
const {
|
|
12
|
+
const { top: navigationY = 0 } = navigation?.layout || {};
|
|
12
13
|
const nativeEvent = event.nativeEvent;
|
|
13
14
|
const { timestamp, pageX, pageY, touches, changedTouches } = nativeEvent;
|
|
14
15
|
const { id } = props;
|
|
@@ -94,36 +95,48 @@ function checkIsNeedPress(e, type, ref) {
|
|
|
94
95
|
ref.current.startTimer[type] = null;
|
|
95
96
|
}
|
|
96
97
|
}
|
|
98
|
+
function shouldHandleTapEvent(e, eventConfig) {
|
|
99
|
+
const { identifier } = e.nativeEvent.changedTouches[0];
|
|
100
|
+
return eventConfig.tap && globalEventState.identifier === identifier;
|
|
101
|
+
}
|
|
97
102
|
function handleTouchstart(e, type, eventConfig) {
|
|
98
|
-
// 阻止事件被释放放回对象池,导致对象复用 _stoppedEventTypes 状态被保留
|
|
99
103
|
e.persist();
|
|
100
104
|
const { innerRef } = eventConfig;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
const touch = e.nativeEvent.changedTouches[0];
|
|
106
|
+
const { identifier } = touch;
|
|
107
|
+
const isSingle = e.nativeEvent.touches.length <= 1;
|
|
108
|
+
if (isSingle) {
|
|
109
|
+
// 仅在 touchstart 记录第一个单指触摸点
|
|
110
|
+
globalEventState.identifier = identifier;
|
|
111
|
+
globalEventState.needPress = true;
|
|
112
|
+
innerRef.current.mpxPressInfo.detail = {
|
|
113
|
+
x: touch.pageX,
|
|
114
|
+
y: touch.pageY
|
|
115
|
+
};
|
|
116
|
+
}
|
|
106
117
|
handleEmitEvent('touchstart', e, type, eventConfig);
|
|
107
118
|
if (eventConfig.longpress) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
// 只有单指触摸时才启动长按定时器
|
|
120
|
+
if (isSingle) {
|
|
121
|
+
if (e._stoppedEventTypes?.has('longpress')) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (eventConfig.longpress.hasCatch) {
|
|
125
|
+
e._stoppedEventTypes = e._stoppedEventTypes || new Set();
|
|
126
|
+
e._stoppedEventTypes.add('longpress');
|
|
127
|
+
}
|
|
128
|
+
innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type]);
|
|
129
|
+
innerRef.current.startTimer[type] = setTimeout(() => {
|
|
130
|
+
globalEventState.needPress = false;
|
|
131
|
+
handleEmitEvent('longpress', e, type, eventConfig);
|
|
132
|
+
}, 350);
|
|
114
133
|
}
|
|
115
|
-
innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type]);
|
|
116
|
-
innerRef.current.startTimer[type] = setTimeout(() => {
|
|
117
|
-
// 只要触发过longpress, 全局就不再触发tap
|
|
118
|
-
globalEventState.needPress = false;
|
|
119
|
-
handleEmitEvent('longpress', e, type, eventConfig);
|
|
120
|
-
}, 350);
|
|
121
134
|
}
|
|
122
135
|
}
|
|
123
136
|
function handleTouchmove(e, type, eventConfig) {
|
|
124
137
|
const { innerRef } = eventConfig;
|
|
125
138
|
handleEmitEvent('touchmove', e, type, eventConfig);
|
|
126
|
-
if (eventConfig
|
|
139
|
+
if (shouldHandleTapEvent(e, eventConfig)) {
|
|
127
140
|
checkIsNeedPress(e, type, innerRef);
|
|
128
141
|
}
|
|
129
142
|
}
|
|
@@ -131,7 +144,8 @@ function handleTouchend(e, type, eventConfig) {
|
|
|
131
144
|
const { innerRef, disableTap } = eventConfig;
|
|
132
145
|
handleEmitEvent('touchend', e, type, eventConfig);
|
|
133
146
|
innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type]);
|
|
134
|
-
|
|
147
|
+
// 只有单指触摸结束时才触发 tap
|
|
148
|
+
if (shouldHandleTapEvent(e, eventConfig)) {
|
|
135
149
|
checkIsNeedPress(e, type, innerRef);
|
|
136
150
|
if (!globalEventState.needPress || (type === 'bubble' && disableTap) || e._stoppedEventTypes?.has('tap')) {
|
|
137
151
|
return;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback, useRef, createElement } from 'react';
|
|
2
|
+
import { View, Image, StyleSheet, Text, TouchableOpacity } from 'react-native';
|
|
3
|
+
import FastImage from '@d11/react-native-fast-image';
|
|
4
|
+
const asyncChunkMap = new Map();
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
container: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
padding: 20,
|
|
9
|
+
backgroundColor: '#fff'
|
|
10
|
+
},
|
|
11
|
+
loadingImage: {
|
|
12
|
+
width: 100,
|
|
13
|
+
height: 100,
|
|
14
|
+
marginTop: 220,
|
|
15
|
+
alignSelf: 'center'
|
|
16
|
+
},
|
|
17
|
+
buttonText: {
|
|
18
|
+
color: '#fff',
|
|
19
|
+
fontSize: 16,
|
|
20
|
+
fontWeight: '500',
|
|
21
|
+
textAlign: 'center'
|
|
22
|
+
},
|
|
23
|
+
errorImage: {
|
|
24
|
+
marginTop: 80,
|
|
25
|
+
width: 220,
|
|
26
|
+
aspectRatio: 1,
|
|
27
|
+
alignSelf: 'center'
|
|
28
|
+
},
|
|
29
|
+
errorText: {
|
|
30
|
+
fontSize: 16,
|
|
31
|
+
textAlign: 'center',
|
|
32
|
+
color: '#333',
|
|
33
|
+
marginBottom: 20
|
|
34
|
+
},
|
|
35
|
+
retryButton: {
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
bottom: 54,
|
|
38
|
+
left: 20,
|
|
39
|
+
right: 20,
|
|
40
|
+
backgroundColor: '#fff',
|
|
41
|
+
paddingVertical: 15,
|
|
42
|
+
borderRadius: 30,
|
|
43
|
+
marginTop: 40,
|
|
44
|
+
borderWidth: 1,
|
|
45
|
+
borderColor: '#FF5F00'
|
|
46
|
+
},
|
|
47
|
+
retryButtonText: {
|
|
48
|
+
color: '#FF5F00',
|
|
49
|
+
fontSize: 16,
|
|
50
|
+
fontWeight: '500',
|
|
51
|
+
textAlign: 'center'
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const DefaultFallback = ({ onReload }) => {
|
|
55
|
+
return (<View style={styles.container}>
|
|
56
|
+
<Image source={{
|
|
57
|
+
uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
|
|
58
|
+
}} style={styles.errorImage} resizeMode="contain"/>
|
|
59
|
+
<Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
|
|
60
|
+
<TouchableOpacity style={styles.retryButton} onPress={onReload} activeOpacity={0.7}>
|
|
61
|
+
<Text style={styles.retryButtonText}>点击重试</Text>
|
|
62
|
+
</TouchableOpacity>
|
|
63
|
+
</View>);
|
|
64
|
+
};
|
|
65
|
+
const DefaultLoading = () => {
|
|
66
|
+
return (<View style={styles.container}>
|
|
67
|
+
<FastImage style={styles.loadingImage} source={{
|
|
68
|
+
uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
|
|
69
|
+
}} resizeMode={FastImage.resizeMode.contain}></FastImage>
|
|
70
|
+
</View>);
|
|
71
|
+
};
|
|
72
|
+
const AsyncSuspense = ({ type, chunkName, moduleId, innerProps, getLoading, getFallback, getChildren }) => {
|
|
73
|
+
const [status, setStatus] = useState('pending');
|
|
74
|
+
const chunkLoaded = asyncChunkMap.has(moduleId);
|
|
75
|
+
const loadChunkPromise = useRef(null);
|
|
76
|
+
const reloadPage = useCallback(() => {
|
|
77
|
+
setStatus('pending');
|
|
78
|
+
}, []);
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
let cancelled = false;
|
|
81
|
+
if (!chunkLoaded && status === 'pending') {
|
|
82
|
+
if (loadChunkPromise.current) {
|
|
83
|
+
loadChunkPromise
|
|
84
|
+
.current.then((res) => {
|
|
85
|
+
if (cancelled)
|
|
86
|
+
return;
|
|
87
|
+
asyncChunkMap.set(moduleId, res);
|
|
88
|
+
setStatus('loaded');
|
|
89
|
+
})
|
|
90
|
+
.catch((e) => {
|
|
91
|
+
if (cancelled)
|
|
92
|
+
return;
|
|
93
|
+
if (type === 'component') {
|
|
94
|
+
global.__mpxAppCbs.lazyLoad.forEach((cb) => {
|
|
95
|
+
// eslint-disable-next-line node/no-callback-literal
|
|
96
|
+
cb({
|
|
97
|
+
type: 'subpackage',
|
|
98
|
+
subpackage: [chunkName],
|
|
99
|
+
errMsg: `loadSubpackage: ${e.type}`
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (type === 'page' && typeof mpxGlobal.__mpx.config?.rnConfig?.onLazyLoadPageError === 'function') {
|
|
104
|
+
mpxGlobal.__mpx.config.rnConfig.onLazyLoadPageError({
|
|
105
|
+
subpackage: chunkName,
|
|
106
|
+
errType: e.type
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
loadChunkPromise.current = null;
|
|
110
|
+
setStatus('error');
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return () => {
|
|
115
|
+
cancelled = true;
|
|
116
|
+
};
|
|
117
|
+
}, [status]);
|
|
118
|
+
if (chunkLoaded) {
|
|
119
|
+
const Comp = asyncChunkMap.get(moduleId);
|
|
120
|
+
return createElement(Comp, innerProps);
|
|
121
|
+
}
|
|
122
|
+
else if (status === 'error') {
|
|
123
|
+
if (type === 'page') {
|
|
124
|
+
const fallback = getFallback ? getFallback() : DefaultFallback;
|
|
125
|
+
return createElement(fallback, { onReload: reloadPage });
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
return getFallback ? createElement(getFallback(), innerProps) : null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
if (!loadChunkPromise.current) {
|
|
133
|
+
loadChunkPromise.current = getChildren();
|
|
134
|
+
}
|
|
135
|
+
if (type === 'page') {
|
|
136
|
+
const loading = getLoading ? getLoading() : DefaultLoading;
|
|
137
|
+
return createElement(loading);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return getFallback ? createElement(getFallback(), innerProps) : null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
AsyncSuspense.displayName = 'MpxAsyncSuspense';
|
|
145
|
+
export default AsyncSuspense;
|
|
@@ -42,6 +42,7 @@ import { getCurrentPage, splitProps, splitStyle, useLayout, useTransformStyle, w
|
|
|
42
42
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
43
43
|
import useNodesRef from './useNodesRef';
|
|
44
44
|
import { RouteContext, FormContext } from './context';
|
|
45
|
+
import Portal from './mpx-portal';
|
|
45
46
|
const LOADING_IMAGE_URI = 'data:image/png;base64,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';
|
|
46
47
|
const TypeColorMap = {
|
|
47
48
|
default: ['#F8F8F8', '#DEDEDE', '35,35,35', '#F7F7F7'],
|
|
@@ -167,7 +168,7 @@ const Button = forwardRef((buttonProps, ref) => {
|
|
|
167
168
|
const defaultTextStyle = extendObject({}, styles.text, isMiniSize ? styles.textMini : {}, { color: plain ? plainTextColor : normalTextColor });
|
|
168
169
|
const defaultStyle = extendObject({}, defaultViewStyle, defaultTextStyle);
|
|
169
170
|
const styleObj = extendObject({}, defaultStyle, style, isHover ? hoverStyle : {});
|
|
170
|
-
const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
171
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
171
172
|
const nodeRef = useRef(null);
|
|
172
173
|
useNodesRef(props, ref, nodeRef, { style: normalStyle });
|
|
173
174
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
@@ -262,9 +263,13 @@ const Button = forwardRef((buttonProps, ref) => {
|
|
|
262
263
|
textStyle,
|
|
263
264
|
textProps
|
|
264
265
|
}));
|
|
265
|
-
|
|
266
|
+
const finalComponent = enableHover
|
|
266
267
|
? createElement(GestureDetector, { gesture: gesture }, baseButton)
|
|
267
268
|
: baseButton;
|
|
269
|
+
if (hasPositionFixed) {
|
|
270
|
+
return createElement(Portal, null, finalComponent);
|
|
271
|
+
}
|
|
272
|
+
return finalComponent;
|
|
268
273
|
});
|
|
269
274
|
Button.displayName = 'MpxButton';
|
|
270
275
|
export default Button;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WEBVIEW_TARGET, registerWebviewProperties } from './utils';
|
|
2
|
+
import { extendObject } from '../utils';
|
|
2
3
|
const PROPERTIES = {
|
|
3
4
|
crossOrigin: undefined,
|
|
4
5
|
height: undefined,
|
|
@@ -50,10 +51,7 @@ export class Image {
|
|
|
50
51
|
this[key] = value;
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
|
-
callbackFn({
|
|
54
|
-
...message.payload,
|
|
55
|
-
target: this
|
|
56
|
-
});
|
|
54
|
+
callbackFn(extendObject({}, message.payload, { target: this }));
|
|
57
55
|
}
|
|
58
56
|
});
|
|
59
57
|
}
|
|
@@ -23,6 +23,7 @@ import './CanvasGradient';
|
|
|
23
23
|
import { createImage as canvasCreateImage } from './Image';
|
|
24
24
|
import { createImageData as canvasCreateImageData } from './ImageData';
|
|
25
25
|
import { useConstructorsRegistry } from './constructorsRegistry';
|
|
26
|
+
import Portal from '../mpx-portal';
|
|
26
27
|
const stylesheet = StyleSheet.create({
|
|
27
28
|
container: { overflow: 'hidden', flex: 0 },
|
|
28
29
|
webview: {
|
|
@@ -41,7 +42,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
41
42
|
const { style = {}, originWhitelist = ['*'], 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
42
43
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
43
44
|
const nodeRef = useRef(null);
|
|
44
|
-
const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(extendObject({}, style, stylesheet.container), {
|
|
45
|
+
const { normalStyle, hasSelfPercent, hasPositionFixed, setWidth, setHeight } = useTransformStyle(extendObject({}, style, stylesheet.container), {
|
|
45
46
|
enableVar,
|
|
46
47
|
externalVarContext,
|
|
47
48
|
parentFontSize,
|
|
@@ -110,10 +111,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
110
111
|
const postMessage = useCallback(async (message) => {
|
|
111
112
|
if (!canvasRef.current?.bus)
|
|
112
113
|
return;
|
|
113
|
-
const { type, payload } = await canvasRef.current.bus.post({
|
|
114
|
-
id: ID(),
|
|
115
|
-
...message
|
|
116
|
-
});
|
|
114
|
+
const { type, payload } = await canvasRef.current.bus.post(extendObject({ id: ID() }, message));
|
|
117
115
|
switch (type) {
|
|
118
116
|
case 'error': {
|
|
119
117
|
const { binderror } = props;
|
|
@@ -142,7 +140,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
142
140
|
canvasRef.current.listeners.splice(canvasRef.current.listeners.indexOf(listener), 1);
|
|
143
141
|
};
|
|
144
142
|
const onMessage = useCallback((e) => {
|
|
145
|
-
|
|
143
|
+
const data = JSON.parse(e.nativeEvent.data);
|
|
146
144
|
switch (data.type) {
|
|
147
145
|
case 'error': {
|
|
148
146
|
const { binderror } = props;
|
|
@@ -156,27 +154,27 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
156
154
|
break;
|
|
157
155
|
}
|
|
158
156
|
default: {
|
|
157
|
+
const newData = {};
|
|
158
|
+
// createLinearGradient 方法调用需要在 constructors 中需要注册 CanvasGradient
|
|
159
|
+
const constructor = constructors[data.meta.constructor];
|
|
159
160
|
if (data.payload) {
|
|
160
|
-
// createLinearGradient 方法调用需要在 constructors 中需要注册 CanvasGradient
|
|
161
|
-
const constructor = constructors[data.meta.constructor];
|
|
162
161
|
if (constructor) {
|
|
163
162
|
const { args, payload } = data;
|
|
164
163
|
// RN 端同步生成一个 CanvasGradient 的实例
|
|
165
164
|
const object = constructor.constructLocally(canvasRef.current, ...args);
|
|
166
|
-
|
|
165
|
+
extendObject(object, payload, {
|
|
167
166
|
[WEBVIEW_TARGET]: data.meta.target
|
|
168
167
|
});
|
|
169
|
-
data
|
|
170
|
-
...data,
|
|
168
|
+
extendObject(newData, data, {
|
|
171
169
|
payload: object
|
|
172
|
-
};
|
|
170
|
+
});
|
|
173
171
|
}
|
|
174
172
|
for (const listener of canvasRef.current.listeners) {
|
|
175
|
-
listener(data.payload);
|
|
173
|
+
listener(constructor ? newData.payload : data.payload);
|
|
176
174
|
}
|
|
177
175
|
}
|
|
178
176
|
if (canvasRef.current.bus) {
|
|
179
|
-
canvasRef.current.bus.handle(data);
|
|
177
|
+
canvasRef.current.bus.handle(constructor && data.payload ? newData : data);
|
|
180
178
|
}
|
|
181
179
|
}
|
|
182
180
|
}
|
|
@@ -192,9 +190,10 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
192
190
|
node: canvasRef.current,
|
|
193
191
|
context: context2D
|
|
194
192
|
});
|
|
195
|
-
|
|
193
|
+
let canvasComponent;
|
|
194
|
+
if (__mpx_mode__ === 'android') {
|
|
196
195
|
const isAndroid9 = Platform.Version >= 28;
|
|
197
|
-
|
|
196
|
+
canvasComponent = createElement(View, innerProps, createElement(WebView, {
|
|
198
197
|
ref: (element) => {
|
|
199
198
|
if (canvasRef.current) {
|
|
200
199
|
canvasRef.current.webview = element;
|
|
@@ -217,7 +216,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
217
216
|
allowUniversalAccessFromFileURLs: true
|
|
218
217
|
}));
|
|
219
218
|
}
|
|
220
|
-
|
|
219
|
+
canvasComponent = createElement(View, innerProps, createElement(WebView, {
|
|
221
220
|
ref: (element) => {
|
|
222
221
|
if (canvasRef.current) {
|
|
223
222
|
canvasRef.current.webview = element;
|
|
@@ -230,6 +229,10 @@ const _Canvas = forwardRef((props = {}, ref) => {
|
|
|
230
229
|
onLoad: onLoad,
|
|
231
230
|
scrollEnabled: false
|
|
232
231
|
}));
|
|
232
|
+
if (hasPositionFixed) {
|
|
233
|
+
canvasComponent = createElement(Portal, null, canvasComponent);
|
|
234
|
+
}
|
|
235
|
+
return canvasComponent;
|
|
233
236
|
});
|
|
234
237
|
_Canvas.displayName = 'mpxCanvas';
|
|
235
238
|
export default _Canvas;
|
|
@@ -8,6 +8,7 @@ import { FormContext, CheckboxGroupContext } from './context';
|
|
|
8
8
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
9
9
|
import useNodesRef from './useNodesRef';
|
|
10
10
|
import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
|
|
11
|
+
import Portal from './mpx-portal';
|
|
11
12
|
const CheckboxGroup = forwardRef((props, ref) => {
|
|
12
13
|
const propsRef = useRef({});
|
|
13
14
|
propsRef.current = props;
|
|
@@ -23,7 +24,7 @@ const CheckboxGroup = forwardRef((props, ref) => {
|
|
|
23
24
|
flexWrap: 'wrap'
|
|
24
25
|
};
|
|
25
26
|
const styleObj = extendObject({}, defaultStyle, style);
|
|
26
|
-
const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
27
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
27
28
|
const nodeRef = useRef(null);
|
|
28
29
|
useNodesRef(props, ref, nodeRef, { style: normalStyle });
|
|
29
30
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
@@ -81,10 +82,14 @@ const CheckboxGroup = forwardRef((props, ref) => {
|
|
|
81
82
|
notifyChange
|
|
82
83
|
};
|
|
83
84
|
}, []);
|
|
84
|
-
|
|
85
|
+
const finalComponent = createElement(View, innerProps, createElement(CheckboxGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
|
|
85
86
|
hasVarDec,
|
|
86
87
|
varContext: varContextRef.current
|
|
87
88
|
})));
|
|
89
|
+
if (hasPositionFixed) {
|
|
90
|
+
return createElement(Portal, null, finalComponent);
|
|
91
|
+
}
|
|
92
|
+
return finalComponent;
|
|
88
93
|
});
|
|
89
94
|
CheckboxGroup.displayName = 'MpxCheckboxGroup';
|
|
90
95
|
export default CheckboxGroup;
|
|
@@ -12,6 +12,7 @@ import useNodesRef from './useNodesRef';
|
|
|
12
12
|
import Icon from './mpx-icon';
|
|
13
13
|
import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
|
|
14
14
|
import { CheckboxGroupContext, LabelContext } from './context';
|
|
15
|
+
import Portal from './mpx-portal';
|
|
15
16
|
const styles = StyleSheet.create({
|
|
16
17
|
container: {
|
|
17
18
|
flexDirection: 'row',
|
|
@@ -63,7 +64,7 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
|
|
|
63
64
|
bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props));
|
|
64
65
|
onChange(evt);
|
|
65
66
|
};
|
|
66
|
-
const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
67
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
67
68
|
const nodeRef = useRef(null);
|
|
68
69
|
useNodesRef(props, ref, nodeRef, {
|
|
69
70
|
style: extendObject({}, defaultStyle, normalStyle),
|
|
@@ -114,7 +115,7 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
|
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
}, [checked]);
|
|
117
|
-
|
|
118
|
+
const finalComponent = createElement(View, innerProps, createElement(View, { style: defaultStyle }, createElement(Icon, {
|
|
118
119
|
type: 'success_no_circle',
|
|
119
120
|
size: 18,
|
|
120
121
|
color: disabled ? '#ADADAD' : color,
|
|
@@ -125,6 +126,10 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
|
|
|
125
126
|
textStyle,
|
|
126
127
|
textProps
|
|
127
128
|
}));
|
|
129
|
+
if (hasPositionFixed) {
|
|
130
|
+
return createElement(Portal, null, finalComponent);
|
|
131
|
+
}
|
|
132
|
+
return finalComponent;
|
|
128
133
|
});
|
|
129
134
|
Checkbox.displayName = 'MpxCheckbox';
|
|
130
135
|
export default Checkbox;
|
|
@@ -17,6 +17,7 @@ import Cancel from './icons/cancel.png';
|
|
|
17
17
|
import Download from './icons/download.png';
|
|
18
18
|
import Search from './icons/search.png';
|
|
19
19
|
import Clear from './icons/clear.png';
|
|
20
|
+
import Portal from '../mpx-portal';
|
|
20
21
|
const IconTypeMap = new Map([
|
|
21
22
|
['success', Success],
|
|
22
23
|
['success_no_circle', SuccessNoCircle],
|
|
@@ -33,7 +34,7 @@ const Icon = forwardRef((props, ref) => {
|
|
|
33
34
|
const source = IconTypeMap.get(type);
|
|
34
35
|
const defaultStyle = { width: ~~size, height: ~~size };
|
|
35
36
|
const styleObj = extendObject({}, defaultStyle, style);
|
|
36
|
-
const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
37
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
37
38
|
const nodeRef = useRef(null);
|
|
38
39
|
useNodesRef(props, ref, nodeRef, { style: normalStyle });
|
|
39
40
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
@@ -44,7 +45,11 @@ const Icon = forwardRef((props, ref) => {
|
|
|
44
45
|
}), [], {
|
|
45
46
|
layoutRef
|
|
46
47
|
});
|
|
47
|
-
|
|
48
|
+
const finalComponent = createElement(Image, innerProps);
|
|
49
|
+
if (hasPositionFixed) {
|
|
50
|
+
return createElement(Portal, null, finalComponent);
|
|
51
|
+
}
|
|
52
|
+
return finalComponent;
|
|
48
53
|
});
|
|
49
54
|
Icon.displayName = 'MpxIcon';
|
|
50
55
|
export default Icon;
|
|
@@ -17,6 +17,7 @@ import { SvgCssUri } from 'react-native-svg/css';
|
|
|
17
17
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
18
18
|
import useNodesRef from './useNodesRef';
|
|
19
19
|
import { SVG_REGEXP, useLayout, useTransformStyle, renderImage, extendObject } from './utils';
|
|
20
|
+
import Portal from './mpx-portal';
|
|
20
21
|
const DEFAULT_IMAGE_WIDTH = 320;
|
|
21
22
|
const DEFAULT_IMAGE_HEIGHT = 240;
|
|
22
23
|
const cropMode = [
|
|
@@ -79,7 +80,7 @@ const Image = forwardRef((props, ref) => {
|
|
|
79
80
|
setLoaded(true);
|
|
80
81
|
}
|
|
81
82
|
};
|
|
82
|
-
const {
|
|
83
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
83
84
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({
|
|
84
85
|
props,
|
|
85
86
|
hasSelfPercent,
|
|
@@ -255,6 +256,8 @@ const Image = forwardRef((props, ref) => {
|
|
|
255
256
|
state.current = {};
|
|
256
257
|
setLoaded(true);
|
|
257
258
|
}
|
|
259
|
+
}, () => {
|
|
260
|
+
setLoaded(true);
|
|
258
261
|
});
|
|
259
262
|
}
|
|
260
263
|
}, [src, isSvg, isLayoutMode]);
|
|
@@ -268,25 +271,35 @@ const Image = forwardRef((props, ref) => {
|
|
|
268
271
|
], {
|
|
269
272
|
layoutRef
|
|
270
273
|
});
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
274
|
+
function renderSvgImage() {
|
|
275
|
+
return createElement(View, innerProps, createElement(SvgCssUri, {
|
|
276
|
+
uri: src,
|
|
277
|
+
onLayout: onSvgLoad,
|
|
278
|
+
onError: binderror && onSvgError,
|
|
279
|
+
style: extendObject({ transformOrigin: 'left top' }, modeStyle)
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
function renderBaseImage() {
|
|
283
|
+
return renderImage(extendObject({
|
|
284
|
+
source: { uri: src },
|
|
285
|
+
resizeMode: resizeMode,
|
|
286
|
+
onLoad: bindload && onImageLoad,
|
|
287
|
+
onError: binderror && onImageError,
|
|
288
|
+
style: extendObject({
|
|
289
|
+
transformOrigin: 'left top',
|
|
290
|
+
width: isCropMode ? imageWidth : '100%',
|
|
291
|
+
height: isCropMode ? imageHeight : '100%'
|
|
292
|
+
}, isCropMode ? modeStyle : {})
|
|
293
|
+
}, isLayoutMode ? {} : innerProps), enableFastImage);
|
|
294
|
+
}
|
|
295
|
+
function renderLayoutImage() {
|
|
296
|
+
return createElement(View, innerProps, loaded && renderBaseImage());
|
|
297
|
+
}
|
|
298
|
+
const finalComponent = isSvg ? renderSvgImage() : isLayoutMode ? renderLayoutImage() : renderBaseImage();
|
|
299
|
+
if (hasPositionFixed) {
|
|
300
|
+
return createElement(Portal, null, finalComponent);
|
|
301
|
+
}
|
|
302
|
+
return finalComponent;
|
|
290
303
|
});
|
|
291
304
|
Image.displayName = 'mpx-image';
|
|
292
305
|
export default Image;
|
|
@@ -44,6 +44,7 @@ import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isIOS } fr
|
|
|
44
44
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
45
45
|
import useNodesRef from './useNodesRef';
|
|
46
46
|
import { FormContext, KeyboardAvoidContext } from './context';
|
|
47
|
+
import Portal from './mpx-portal';
|
|
47
48
|
const keyboardTypeMap = {
|
|
48
49
|
text: 'default',
|
|
49
50
|
number: 'numeric',
|
|
@@ -83,7 +84,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
83
84
|
const styleObj = extendObject({ padding: 0, backgroundColor: '#fff' }, style, multiline && autoHeight
|
|
84
85
|
? { height: 'auto', minHeight: Math.max(style?.minHeight || 35, contentHeight) }
|
|
85
86
|
: {});
|
|
86
|
-
const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
87
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
87
88
|
const nodeRef = useRef(null);
|
|
88
89
|
useNodesRef(props, ref, nodeRef, {
|
|
89
90
|
style: normalStyle
|
|
@@ -289,7 +290,11 @@ const Input = forwardRef((props, ref) => {
|
|
|
289
290
|
], {
|
|
290
291
|
layoutRef
|
|
291
292
|
});
|
|
292
|
-
|
|
293
|
+
const finalComponent = createElement(TextInput, innerProps);
|
|
294
|
+
if (hasPositionFixed) {
|
|
295
|
+
return createElement(Portal, null, finalComponent);
|
|
296
|
+
}
|
|
297
|
+
return finalComponent;
|
|
293
298
|
});
|
|
294
299
|
Input.displayName = 'MpxInput';
|
|
295
300
|
export default Input;
|
|
@@ -8,6 +8,7 @@ import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
|
8
8
|
import useNodesRef from './useNodesRef';
|
|
9
9
|
import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
|
|
10
10
|
import { LabelContext } from './context';
|
|
11
|
+
import Portal from './mpx-portal';
|
|
11
12
|
const Label = forwardRef((labelProps, ref) => {
|
|
12
13
|
const { textProps, innerProps: props = {} } = splitProps(labelProps);
|
|
13
14
|
const propsRef = useRef({});
|
|
@@ -17,7 +18,7 @@ const Label = forwardRef((labelProps, ref) => {
|
|
|
17
18
|
flexDirection: 'row'
|
|
18
19
|
};
|
|
19
20
|
const styleObj = extendObject({}, defaultStyle, style);
|
|
20
|
-
const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
21
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
21
22
|
const nodeRef = useRef(null);
|
|
22
23
|
useNodesRef(props, ref, nodeRef, { style: normalStyle });
|
|
23
24
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
@@ -40,12 +41,16 @@ const Label = forwardRef((labelProps, ref) => {
|
|
|
40
41
|
}), [], {
|
|
41
42
|
layoutRef
|
|
42
43
|
});
|
|
43
|
-
|
|
44
|
+
const finalComponent = createElement(View, innerProps, createElement(LabelContext.Provider, { value: contextRef }, wrapChildren(props, {
|
|
44
45
|
hasVarDec,
|
|
45
46
|
varContext: varContextRef.current,
|
|
46
47
|
textStyle,
|
|
47
48
|
textProps
|
|
48
49
|
})));
|
|
50
|
+
if (hasPositionFixed) {
|
|
51
|
+
return createElement(Portal, null, finalComponent);
|
|
52
|
+
}
|
|
53
|
+
return finalComponent;
|
|
49
54
|
});
|
|
50
55
|
Label.displayName = 'MpxLabel';
|
|
51
56
|
export default Label;
|