@mpxjs/webpack-plugin 2.9.62 → 2.9.65
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/config.js +38 -10
- package/lib/index.js +1 -3
- package/lib/platform/style/wx/index.js +115 -66
- package/lib/platform/template/wx/index.js +12 -8
- package/lib/react/processStyles.js +1 -0
- package/lib/react/processTemplate.js +2 -3
- package/lib/react/style-helper.js +9 -7
- package/lib/runtime/components/react/context.ts +9 -7
- package/lib/runtime/components/react/dist/context.js +1 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +12 -1
- package/lib/runtime/components/react/dist/mpx-button.jsx +53 -74
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +20 -18
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +30 -42
- package/lib/runtime/components/react/dist/mpx-form.jsx +18 -15
- package/lib/runtime/components/react/dist/mpx-icon.jsx +15 -17
- package/lib/runtime/components/react/dist/mpx-image/index.jsx +36 -34
- package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +36 -31
- package/lib/runtime/components/react/dist/mpx-label.jsx +30 -37
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +15 -19
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +10 -9
- package/lib/runtime/components/react/dist/mpx-picker/date.jsx +2 -1
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -10
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +9 -5
- package/lib/runtime/components/react/dist/mpx-picker/region.jsx +13 -8
- package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +22 -20
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +103 -10
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +149 -54
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +20 -18
- package/lib/runtime/components/react/dist/mpx-radio.jsx +29 -43
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +8 -4
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +36 -27
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +141 -75
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +16 -7
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +20 -11
- package/lib/runtime/components/react/dist/mpx-switch.jsx +18 -14
- package/lib/runtime/components/react/dist/mpx-text.jsx +20 -35
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-view.jsx +296 -210
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +11 -7
- package/lib/runtime/components/react/dist/parser.js +218 -0
- package/lib/runtime/components/react/dist/useNodesRef.js +1 -5
- package/lib/runtime/components/react/dist/utils.jsx +445 -0
- package/lib/runtime/components/react/getInnerListeners.ts +18 -8
- package/lib/runtime/components/react/mpx-button.tsx +83 -91
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +50 -43
- package/lib/runtime/components/react/mpx-checkbox.tsx +56 -64
- package/lib/runtime/components/react/mpx-form.tsx +51 -22
- package/lib/runtime/components/react/mpx-icon.tsx +31 -27
- package/lib/runtime/components/react/mpx-image/index.tsx +54 -47
- package/lib/runtime/components/react/mpx-image/svg.tsx +5 -3
- package/lib/runtime/components/react/mpx-input.tsx +59 -38
- package/lib/runtime/components/react/mpx-label.tsx +55 -59
- package/lib/runtime/components/react/mpx-movable-area.tsx +40 -25
- package/lib/runtime/components/react/mpx-movable-view.tsx +29 -29
- package/lib/runtime/components/react/mpx-navigator.tsx +2 -2
- package/lib/runtime/components/react/mpx-picker/date.tsx +4 -4
- package/lib/runtime/components/react/mpx-picker/index.tsx +12 -11
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +17 -13
- package/lib/runtime/components/react/mpx-picker/region.tsx +23 -19
- package/lib/runtime/components/react/mpx-picker/selector.tsx +7 -7
- package/lib/runtime/components/react/mpx-picker/time.tsx +29 -31
- package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +149 -20
- package/lib/runtime/components/react/mpx-picker-view.tsx +180 -63
- package/lib/runtime/components/react/mpx-radio-group.tsx +51 -47
- package/lib/runtime/components/react/mpx-radio.tsx +57 -72
- package/lib/runtime/components/react/mpx-root-portal.tsx +10 -8
- package/lib/runtime/components/react/mpx-scroll-view.tsx +136 -104
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +175 -96
- package/lib/runtime/components/react/mpx-swiper/index.tsx +21 -9
- package/lib/runtime/components/react/mpx-swiper/type.ts +16 -5
- package/lib/runtime/components/react/mpx-swiper-item.tsx +48 -14
- package/lib/runtime/components/react/mpx-switch.tsx +46 -24
- package/lib/runtime/components/react/mpx-text.tsx +38 -45
- package/lib/runtime/components/react/mpx-textarea.tsx +1 -1
- package/lib/runtime/components/react/mpx-view.tsx +401 -241
- package/lib/runtime/components/react/mpx-web-view.tsx +22 -22
- package/lib/runtime/components/react/parser.ts +245 -0
- package/lib/runtime/components/react/types/common.ts +4 -4
- package/lib/runtime/components/react/types/global.d.ts +24 -2
- package/lib/runtime/components/react/useNodesRef.ts +1 -7
- package/lib/runtime/components/react/utils.tsx +524 -0
- package/lib/runtime/components/web/mpx-scroll-view.vue +25 -5
- package/lib/style-compiler/index.js +5 -4
- package/lib/template-compiler/compiler.js +133 -161
- package/lib/template-compiler/gen-node-react.js +1 -3
- package/lib/utils/const.js +2 -1
- package/lib/web/processStyles.js +2 -1
- package/lib/web/processTemplate.js +2 -3
- package/lib/wxml/loader.js +1 -1
- package/package.json +7 -4
- package/lib/runtime/components/react/dist/utils.js +0 -148
- package/lib/runtime/components/react/utils.ts +0 -170
|
@@ -4,26 +4,74 @@
|
|
|
4
4
|
* ✔ hover-start-time
|
|
5
5
|
* ✔ hover-stay-time
|
|
6
6
|
*/
|
|
7
|
-
import { View,
|
|
7
|
+
import { View, StyleSheet, Image } from 'react-native';
|
|
8
8
|
import { useRef, useState, useEffect, forwardRef } from 'react';
|
|
9
9
|
import useInnerProps from './getInnerListeners';
|
|
10
10
|
import useNodesRef from './useNodesRef';
|
|
11
|
-
import { parseUrl, PERCENT_REGEX,
|
|
11
|
+
import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout } from './utils';
|
|
12
|
+
import LinearGradient from 'react-native-linear-gradient';
|
|
13
|
+
const linearMap = new Map([
|
|
14
|
+
['top', 0],
|
|
15
|
+
['bottom', 180],
|
|
16
|
+
['left', 270],
|
|
17
|
+
['right', 90]
|
|
18
|
+
]);
|
|
19
|
+
// 对角线角度
|
|
20
|
+
const diagonalAngleMap = {
|
|
21
|
+
'top right': (width, height) => {
|
|
22
|
+
return Math.acos((width / 2) /
|
|
23
|
+
(Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) / 2));
|
|
24
|
+
},
|
|
25
|
+
'right top': (width, height) => { return diagonalAngleMap['top right'](width, height); },
|
|
26
|
+
'bottom right': (width, height) => Math.PI - diagonalAngleMap['top right'](width, height),
|
|
27
|
+
'right bottom': (width, height) => { return diagonalAngleMap['bottom right'](width, height); },
|
|
28
|
+
'bottom left': (width, height) => Math.PI + diagonalAngleMap['top right'](width, height),
|
|
29
|
+
'left bottom': (width, height) => { return diagonalAngleMap['bottom left'](width, height); },
|
|
30
|
+
'top left': (width, height) => (2 * Math.PI) - diagonalAngleMap['top right'](width, height),
|
|
31
|
+
'left top': (width, height) => { return diagonalAngleMap['top left'](width, height); }
|
|
32
|
+
};
|
|
33
|
+
// 弧度转化为角度的公式
|
|
34
|
+
function radToAngle(r) {
|
|
35
|
+
return r * 180 / Math.PI;
|
|
36
|
+
}
|
|
12
37
|
const applyHandlers = (handlers, args) => {
|
|
13
|
-
for (
|
|
38
|
+
for (const handler of handlers) {
|
|
14
39
|
handler(...args);
|
|
15
40
|
}
|
|
16
41
|
};
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
42
|
+
const normalizeStyle = (style = {}) => {
|
|
43
|
+
['backgroundSize', 'backgroundPosition'].forEach(name => {
|
|
44
|
+
if (style[name] && typeof style[name] === 'string') {
|
|
45
|
+
if (style[name].trim()) {
|
|
46
|
+
style[name] = style[name].split(' ');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return style;
|
|
51
|
+
};
|
|
52
|
+
const isPercent = (val) => typeof val === 'string' && PERCENT_REGEX.test(val);
|
|
53
|
+
const isBackgroundSizeKeyword = (val) => typeof val === 'string' && /^cover|contain$/.test(val);
|
|
54
|
+
const isNeedLayout = (preImageInfo) => {
|
|
55
|
+
const { sizeList, backgroundPosition, linearInfo } = preImageInfo;
|
|
56
|
+
const [width, height] = sizeList;
|
|
57
|
+
const bp = backgroundPosition;
|
|
20
58
|
// 含有百分号,center 需计算布局
|
|
21
|
-
|
|
59
|
+
return isBackgroundSizeKeyword(width) ||
|
|
60
|
+
(isPercent(height) && width === 'auto') ||
|
|
61
|
+
(isPercent(width) && height === 'auto') ||
|
|
62
|
+
isPercent(bp[1]) ||
|
|
63
|
+
isPercent(bp[3]) ||
|
|
64
|
+
isDiagonalAngle(linearInfo);
|
|
65
|
+
};
|
|
66
|
+
const checkNeedLayout = (preImageInfo) => {
|
|
67
|
+
const { sizeList } = preImageInfo;
|
|
68
|
+
const [width] = sizeList;
|
|
69
|
+
// 在渐变的时候,background-size的cover,contain, auto属性值,转化为100%, needLayout计算逻辑和原来保持一致,needImageSize始终为false
|
|
22
70
|
return {
|
|
23
71
|
// 是否开启layout的计算
|
|
24
|
-
needLayout:
|
|
72
|
+
needLayout: isNeedLayout(preImageInfo),
|
|
25
73
|
// 是否开启原始宽度的计算
|
|
26
|
-
needImageSize:
|
|
74
|
+
needImageSize: isBackgroundSizeKeyword(width) || sizeList.includes('auto')
|
|
27
75
|
};
|
|
28
76
|
};
|
|
29
77
|
/**
|
|
@@ -32,11 +80,12 @@ const checkNeedLayout = (style) => {
|
|
|
32
80
|
* ratio - 原始图片的宽高比
|
|
33
81
|
* **/
|
|
34
82
|
function calculateSize(h, ratio, lh, reverse = false) {
|
|
35
|
-
let height = 0
|
|
83
|
+
let height = 0;
|
|
84
|
+
let width = 0;
|
|
36
85
|
if (typeof lh === 'boolean') {
|
|
37
86
|
reverse = lh;
|
|
38
87
|
}
|
|
39
|
-
if (
|
|
88
|
+
if (isPercent(h)) { // auto px/rpx
|
|
40
89
|
if (!lh)
|
|
41
90
|
return null;
|
|
42
91
|
height = (parseFloat(h) / 100) * lh;
|
|
@@ -61,22 +110,31 @@ function calculateSizePosition(h, ch, val) {
|
|
|
61
110
|
if (!h || !ch)
|
|
62
111
|
return 0;
|
|
63
112
|
// 百分比需要单独的计算
|
|
64
|
-
if (
|
|
113
|
+
if (isPercent(h)) {
|
|
65
114
|
h = ch * parseFloat(h) / 100;
|
|
66
115
|
}
|
|
67
116
|
// (container width - image width) * (position x%) = (x offset value)
|
|
68
117
|
return (ch - h) * parseFloat(val) / 100;
|
|
69
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* 获取图片的展示宽高
|
|
121
|
+
* h - 用户设置的高度
|
|
122
|
+
* lh - 容器的高度
|
|
123
|
+
* **/
|
|
124
|
+
const calcPercent = (h, lh) => {
|
|
125
|
+
return isPercent(h) ? parseFloat(h) / 100 * lh : +h;
|
|
126
|
+
};
|
|
70
127
|
function backgroundPosition(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
71
128
|
const bps = preImageInfo.backgroundPosition;
|
|
72
129
|
if (bps.length === 0)
|
|
73
130
|
return;
|
|
74
|
-
|
|
75
|
-
|
|
131
|
+
const style = {};
|
|
132
|
+
const imageStyle = imageProps.style || {};
|
|
76
133
|
for (let i = 0; i < bps.length; i += 2) {
|
|
77
|
-
|
|
134
|
+
const key = bps[i];
|
|
135
|
+
const val = bps[i + 1];
|
|
78
136
|
// 需要获取 图片宽度 和 容器的宽度 进行计算
|
|
79
|
-
if (
|
|
137
|
+
if (isPercent(val)) {
|
|
80
138
|
if (i === 0) {
|
|
81
139
|
style[key] = calculateSizePosition(imageStyle.width, layoutInfo?.width, val);
|
|
82
140
|
}
|
|
@@ -95,7 +153,7 @@ function backgroundPosition(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
|
95
153
|
}
|
|
96
154
|
// background-size 转换
|
|
97
155
|
function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
98
|
-
|
|
156
|
+
const sizeList = preImageInfo.sizeList;
|
|
99
157
|
if (!sizeList)
|
|
100
158
|
return;
|
|
101
159
|
const { width: layoutWidth, height: layoutHeight } = layoutInfo || {};
|
|
@@ -105,13 +163,13 @@ function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
|
105
163
|
// 枚举值
|
|
106
164
|
if (typeof width === 'string' && ['cover', 'contain'].includes(width)) {
|
|
107
165
|
if (layoutInfo && imageSize) {
|
|
108
|
-
|
|
109
|
-
|
|
166
|
+
const layoutRatio = layoutWidth / imageSizeWidth;
|
|
167
|
+
const eleRatio = imageSizeWidth / imageSizeHeight;
|
|
110
168
|
// 容器宽高比 大于 图片的宽高比,依据宽度作为基准,否则以高度为基准
|
|
111
|
-
if (layoutRatio <= eleRatio && width === 'contain' || layoutRatio >= eleRatio && width === 'cover') {
|
|
169
|
+
if ((layoutRatio <= eleRatio && width === 'contain') || (layoutRatio >= eleRatio && width === 'cover')) {
|
|
112
170
|
dimensions = calculateSize(layoutWidth, imageSizeHeight / imageSizeWidth, true);
|
|
113
171
|
}
|
|
114
|
-
else if (layoutRatio > eleRatio && width === 'contain' || layoutRatio < eleRatio && width === 'cover') {
|
|
172
|
+
else if ((layoutRatio > eleRatio && width === 'contain') || (layoutRatio < eleRatio && width === 'cover')) {
|
|
115
173
|
dimensions = calculateSize(layoutHeight, imageSizeWidth / imageSizeHeight);
|
|
116
174
|
}
|
|
117
175
|
}
|
|
@@ -143,8 +201,8 @@ function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
|
143
201
|
// 数值类型设置为 stretch
|
|
144
202
|
imageProps.style.resizeMode = 'stretch';
|
|
145
203
|
dimensions = {
|
|
146
|
-
width:
|
|
147
|
-
height:
|
|
204
|
+
width: isPercent(width) ? width : +width,
|
|
205
|
+
height: isPercent(height) ? height : +height
|
|
148
206
|
};
|
|
149
207
|
}
|
|
150
208
|
}
|
|
@@ -156,7 +214,27 @@ function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
|
156
214
|
}
|
|
157
215
|
// background-image转换为source
|
|
158
216
|
function backgroundImage(imageProps, preImageInfo) {
|
|
159
|
-
|
|
217
|
+
if (preImageInfo.src) {
|
|
218
|
+
imageProps.src = preImageInfo.src;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// 渐变的转换
|
|
222
|
+
function linearGradient(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
223
|
+
const { type, linearInfo } = preImageInfo;
|
|
224
|
+
const { colors = [], locations, direction = '' } = linearInfo || {};
|
|
225
|
+
const { width, height } = imageSize || {};
|
|
226
|
+
if (type !== 'linear')
|
|
227
|
+
return;
|
|
228
|
+
// 角度计算
|
|
229
|
+
let angle = +(linearMap.get(direction) || direction.match(/(-?\d+(\.\d+)?)deg/)?.[1] || 180) % 360;
|
|
230
|
+
// 对角线角度计算
|
|
231
|
+
if (layoutInfo && diagonalAngleMap[direction] && imageSize && linearInfo) {
|
|
232
|
+
angle = radToAngle(diagonalAngleMap[direction](width, height)) || 180;
|
|
233
|
+
}
|
|
234
|
+
// 赋值
|
|
235
|
+
imageProps.colors = colors;
|
|
236
|
+
imageProps.locations = locations;
|
|
237
|
+
imageProps.angle = angle;
|
|
160
238
|
}
|
|
161
239
|
const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => {
|
|
162
240
|
// 初始化
|
|
@@ -165,11 +243,10 @@ const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => {
|
|
|
165
243
|
resizeMode: 'cover',
|
|
166
244
|
position: 'absolute'
|
|
167
245
|
// ...StyleSheet.absoluteFillObject
|
|
168
|
-
}
|
|
246
|
+
},
|
|
247
|
+
colors: []
|
|
169
248
|
};
|
|
170
|
-
applyHandlers([backgroundSize, backgroundImage, backgroundPosition], [imageProps, preImageInfo, imageSize, layoutInfo]);
|
|
171
|
-
if (!imageProps?.src)
|
|
172
|
-
return null;
|
|
249
|
+
applyHandlers([backgroundSize, backgroundImage, backgroundPosition, linearGradient], [imageProps, preImageInfo, imageSize, layoutInfo]);
|
|
173
250
|
return imageProps;
|
|
174
251
|
};
|
|
175
252
|
function isHorizontal(val) {
|
|
@@ -246,59 +323,162 @@ function normalizeBackgroundPosition(parts) {
|
|
|
246
323
|
}
|
|
247
324
|
return [hStart, hOffset, vStart, vOffset];
|
|
248
325
|
}
|
|
326
|
+
/**
|
|
327
|
+
*
|
|
328
|
+
* calcSteps - 计算起始位置和终点位置之间的差值
|
|
329
|
+
* startVal - 起始位置距离
|
|
330
|
+
* endVal - 终点位置距离
|
|
331
|
+
* len - 数量
|
|
332
|
+
* **/
|
|
333
|
+
function calcSteps(startVal, endVal, len) {
|
|
334
|
+
const diffVal = endVal - startVal;
|
|
335
|
+
const step = diffVal / len;
|
|
336
|
+
const newArr = [];
|
|
337
|
+
for (let i = 1; i < len; i++) {
|
|
338
|
+
const val = startVal + step * i;
|
|
339
|
+
newArr.push(+val.toFixed(2));
|
|
340
|
+
}
|
|
341
|
+
return newArr;
|
|
342
|
+
}
|
|
343
|
+
function parseLinearGradient(text) {
|
|
344
|
+
let linearText = text.trim().match(/linear-gradient\((.*)\)/)?.[1];
|
|
345
|
+
if (!linearText)
|
|
346
|
+
return;
|
|
347
|
+
// 添加默认的角度
|
|
348
|
+
if (!/^to|^-?\d+deg/.test(linearText)) {
|
|
349
|
+
linearText = '180deg ,' + linearText;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
linearText = linearText.replace('to', '');
|
|
353
|
+
}
|
|
354
|
+
// 把 0deg, red 10%, blue 20% 解析为 ['0deg', 'red, 10%', 'blue, 20%']
|
|
355
|
+
const [direction, ...colorList] = linearText.split(/,(?![^(#]*\))/);
|
|
356
|
+
// 记录需要填充起点的起始位置
|
|
357
|
+
let startIdx = 0;
|
|
358
|
+
let startVal = 0;
|
|
359
|
+
// 把 ['red, 10%', 'blue, 20%']解析为 [[red, 10%], [blue, 20%]]
|
|
360
|
+
const linearInfo = colorList.map(item => item.trim().split(/(?<!,)\s+/))
|
|
361
|
+
.reduce((prev, cur, idx, self) => {
|
|
362
|
+
const { colors, locations } = prev;
|
|
363
|
+
const [color, val] = cur;
|
|
364
|
+
let numberVal = parseFloat(val) / 100;
|
|
365
|
+
// 处理渐变默认值
|
|
366
|
+
if (idx === 0) {
|
|
367
|
+
numberVal = numberVal || 0;
|
|
368
|
+
}
|
|
369
|
+
else if (self.length - 1 === idx) {
|
|
370
|
+
numberVal = numberVal || 1;
|
|
371
|
+
}
|
|
372
|
+
// 出现缺省值时进行填充
|
|
373
|
+
if (idx - startIdx > 1 && !isNaN(numberVal)) {
|
|
374
|
+
locations.push(...calcSteps(startVal, numberVal, idx - startIdx));
|
|
375
|
+
}
|
|
376
|
+
if (!isNaN(numberVal)) {
|
|
377
|
+
startIdx = idx;
|
|
378
|
+
startVal = numberVal;
|
|
379
|
+
}
|
|
380
|
+
// 添加color的数组
|
|
381
|
+
colors.push(color.trim());
|
|
382
|
+
!isNaN(numberVal) && locations.push(numberVal);
|
|
383
|
+
return prev;
|
|
384
|
+
}, { colors: [], locations: [] });
|
|
385
|
+
return {
|
|
386
|
+
...linearInfo,
|
|
387
|
+
direction: direction.trim()
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function parseBgImage(text) {
|
|
391
|
+
if (!text)
|
|
392
|
+
return {};
|
|
393
|
+
const src = parseUrl(text);
|
|
394
|
+
if (src)
|
|
395
|
+
return { src, type: 'image' };
|
|
396
|
+
const linearInfo = parseLinearGradient(text);
|
|
397
|
+
if (!linearInfo)
|
|
398
|
+
return {};
|
|
399
|
+
return {
|
|
400
|
+
linearInfo,
|
|
401
|
+
type: 'linear'
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function normalizeBackgroundSize(backgroundSize, type) {
|
|
405
|
+
const sizeList = backgroundSize.slice();
|
|
406
|
+
if (sizeList.length === 1)
|
|
407
|
+
sizeList.push('auto');
|
|
408
|
+
if (type === 'linear') {
|
|
409
|
+
// 处理当使用渐变的时候,background-size出现cover, contain, auto,当作100%处理
|
|
410
|
+
for (const i in sizeList) {
|
|
411
|
+
const val = sizeList[i];
|
|
412
|
+
sizeList[i] = /^cover|contain|auto$/.test(val) ? '100%' : val;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return sizeList;
|
|
416
|
+
}
|
|
249
417
|
function preParseImage(imageStyle) {
|
|
250
|
-
const { backgroundImage, backgroundSize = ['auto'], backgroundPosition = [0, 0] } = imageStyle || {};
|
|
251
|
-
const src =
|
|
252
|
-
let sizeList = backgroundSize.slice();
|
|
253
|
-
sizeList.length === 1 && sizeList.push('auto');
|
|
418
|
+
const { backgroundImage = '', backgroundSize = ['auto'], backgroundPosition = [0, 0] } = normalizeStyle(imageStyle) || {};
|
|
419
|
+
const { type, src, linearInfo } = parseBgImage(backgroundImage);
|
|
254
420
|
return {
|
|
255
421
|
src,
|
|
256
|
-
|
|
422
|
+
linearInfo,
|
|
423
|
+
type,
|
|
424
|
+
sizeList: normalizeBackgroundSize(backgroundSize, type),
|
|
257
425
|
backgroundPosition: normalizeBackgroundPosition(backgroundPosition)
|
|
258
426
|
};
|
|
259
427
|
}
|
|
428
|
+
function isDiagonalAngle(linearInfo) {
|
|
429
|
+
return !!(linearInfo?.direction && diagonalAngleMap[linearInfo.direction]);
|
|
430
|
+
}
|
|
260
431
|
function wrapImage(imageStyle) {
|
|
261
|
-
|
|
432
|
+
// 预处理数据
|
|
433
|
+
const preImageInfo = preParseImage(imageStyle);
|
|
434
|
+
// 预解析
|
|
435
|
+
const { src, sizeList, type } = preImageInfo;
|
|
436
|
+
// 判断是否可挂载onLayout
|
|
437
|
+
const { needLayout, needImageSize } = checkNeedLayout(preImageInfo);
|
|
438
|
+
const [show, setShow] = useState(((type === 'image' && !!src) || type === 'linear') && !needLayout && !needImageSize);
|
|
262
439
|
const [, setImageSizeWidth] = useState(null);
|
|
263
440
|
const [, setImageSizeHeight] = useState(null);
|
|
264
441
|
const [, setLayoutInfoWidth] = useState(null);
|
|
265
442
|
const [, setLayoutInfoHeight] = useState(null);
|
|
266
443
|
const sizeInfo = useRef(null);
|
|
267
444
|
const layoutInfo = useRef(null);
|
|
268
|
-
// 预解析
|
|
269
|
-
const preImageInfo = preParseImage(imageStyle);
|
|
270
|
-
// 判断是否可挂载onLayout
|
|
271
|
-
const { needLayout, needImageSize } = checkNeedLayout(preImageInfo);
|
|
272
|
-
const { src } = preImageInfo;
|
|
273
445
|
useEffect(() => {
|
|
446
|
+
sizeInfo.current = null;
|
|
447
|
+
if (type === 'linear') {
|
|
448
|
+
if (!needLayout)
|
|
449
|
+
setShow(true);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
274
452
|
if (!src) {
|
|
275
453
|
setShow(false);
|
|
276
|
-
sizeInfo.current = null;
|
|
277
|
-
layoutInfo.current = null;
|
|
278
454
|
return;
|
|
455
|
+
// 一开始未出现,数据改变时出现
|
|
279
456
|
}
|
|
280
|
-
if (!needImageSize) {
|
|
457
|
+
else if (!(needLayout || needImageSize)) {
|
|
281
458
|
setShow(true);
|
|
282
459
|
return;
|
|
283
460
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
461
|
+
if (needImageSize) {
|
|
462
|
+
Image.getSize(src, (width, height) => {
|
|
463
|
+
sizeInfo.current = {
|
|
464
|
+
width,
|
|
465
|
+
height
|
|
466
|
+
};
|
|
467
|
+
// 1. 当需要绑定onLayout 2. 获取到布局信息
|
|
468
|
+
if (!needLayout || layoutInfo.current) {
|
|
469
|
+
setImageSizeWidth(width);
|
|
470
|
+
setImageSizeHeight(height);
|
|
471
|
+
if (layoutInfo.current) {
|
|
472
|
+
setLayoutInfoWidth(layoutInfo.current.width);
|
|
473
|
+
setLayoutInfoHeight(layoutInfo.current.height);
|
|
474
|
+
}
|
|
475
|
+
setShow(true);
|
|
296
476
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}, [
|
|
301
|
-
if (!
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
// type 添加type 处理无渐变 有渐变的场景
|
|
480
|
+
}, [src, type]);
|
|
481
|
+
if (!type)
|
|
302
482
|
return null;
|
|
303
483
|
const onLayout = (res) => {
|
|
304
484
|
const { width, height } = res?.nativeEvent?.layout || {};
|
|
@@ -309,6 +489,16 @@ function wrapImage(imageStyle) {
|
|
|
309
489
|
if (!needImageSize) {
|
|
310
490
|
setLayoutInfoWidth(width);
|
|
311
491
|
setLayoutInfoHeight(height);
|
|
492
|
+
// 有渐变角度的时候,才触发渲染组件
|
|
493
|
+
if (type === 'linear') {
|
|
494
|
+
sizeInfo.current = {
|
|
495
|
+
width: calcPercent(sizeList[0], width),
|
|
496
|
+
height: calcPercent(sizeList[1], height)
|
|
497
|
+
};
|
|
498
|
+
setImageSizeWidth(sizeInfo.current.width);
|
|
499
|
+
setImageSizeHeight(sizeInfo.current.height);
|
|
500
|
+
}
|
|
501
|
+
setShow(true);
|
|
312
502
|
}
|
|
313
503
|
else if (sizeInfo.current) {
|
|
314
504
|
setLayoutInfoWidth(width);
|
|
@@ -318,92 +508,57 @@ function wrapImage(imageStyle) {
|
|
|
318
508
|
setShow(true);
|
|
319
509
|
}
|
|
320
510
|
};
|
|
321
|
-
return <View key='
|
|
322
|
-
{show && <
|
|
511
|
+
return <View key='backgroundImage' {...needLayout ? { onLayout } : null} style={{ ...StyleSheet.absoluteFillObject, overflow: 'hidden' }}>
|
|
512
|
+
{show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current, layoutInfo.current)}/>}
|
|
513
|
+
{show && type === 'image' && <Image {...imageStyleToProps(preImageInfo, sizeInfo.current, layoutInfo.current)}/>}
|
|
323
514
|
</View>;
|
|
324
515
|
}
|
|
325
|
-
function
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
if (textStyle)
|
|
336
|
-
throwReactWarning('[Mpx runtime warn]: Text style will be ignored unless every child of the view is Text node!');
|
|
337
|
-
}
|
|
516
|
+
function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backgroundStyle, varContext, textProps }) {
|
|
517
|
+
const children = wrapChildren(props, {
|
|
518
|
+
hasVarDec,
|
|
519
|
+
varContext,
|
|
520
|
+
textStyle,
|
|
521
|
+
textProps
|
|
522
|
+
});
|
|
338
523
|
return [
|
|
339
|
-
|
|
524
|
+
enableBackground ? wrapImage(backgroundStyle) : null,
|
|
340
525
|
children
|
|
341
526
|
];
|
|
342
527
|
}
|
|
343
|
-
const _View = forwardRef((
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
rules: {
|
|
347
|
-
width: 'translateX',
|
|
348
|
-
height: 'translateY'
|
|
349
|
-
}
|
|
350
|
-
}, {
|
|
351
|
-
key: 'borderTopLeftRadius',
|
|
352
|
-
rules: {
|
|
353
|
-
width: 'borderTopLeftRadius'
|
|
354
|
-
}
|
|
355
|
-
}, {
|
|
356
|
-
key: 'borderBottomLeftRadius',
|
|
357
|
-
rules: {
|
|
358
|
-
width: 'borderBottomLeftRadius'
|
|
359
|
-
}
|
|
360
|
-
}, {
|
|
361
|
-
key: 'borderBottomRightRadius',
|
|
362
|
-
rules: {
|
|
363
|
-
height: 'borderBottomRightRadius'
|
|
364
|
-
}
|
|
365
|
-
}, {
|
|
366
|
-
key: 'borderTopRightRadius',
|
|
367
|
-
rules: {
|
|
368
|
-
height: 'borderTopRightRadius'
|
|
369
|
-
}
|
|
370
|
-
}];
|
|
371
|
-
const { style = {}, children, hoverStyle, 'hover-start-time': hoverStartTime = 50, 'hover-stay-time': hoverStayTime = 400, 'enable-offset': enableOffset, } = props;
|
|
528
|
+
const _View = forwardRef((viewProps, ref) => {
|
|
529
|
+
const { textProps, innerProps: props = {} } = splitProps(viewProps);
|
|
530
|
+
let { style = {}, 'hover-style': hoverStyle, 'hover-start-time': hoverStartTime = 50, 'hover-stay-time': hoverStayTime = 400, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'enable-background': enableBackground, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
372
531
|
const [isHover, setIsHover] = useState(false);
|
|
373
|
-
let transformStyle = {};
|
|
374
|
-
const [containerWidth, setContainerWidth] = useState(0);
|
|
375
|
-
const [containerHeight, setContainerHeight] = useState(0);
|
|
376
|
-
const layoutRef = useRef({});
|
|
377
|
-
// 打平 style 数组
|
|
378
|
-
const styleObj = normalizeStyle(style);
|
|
379
532
|
// 默认样式
|
|
380
533
|
const defaultStyle = {
|
|
381
534
|
// flex 布局相关的默认样式
|
|
382
|
-
...
|
|
535
|
+
...style.display === 'flex' && {
|
|
383
536
|
flexDirection: 'row',
|
|
384
537
|
flexBasis: 'auto',
|
|
385
538
|
flexShrink: 1,
|
|
386
539
|
flexWrap: 'nowrap'
|
|
387
540
|
}
|
|
388
541
|
};
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
});
|
|
542
|
+
const styleObj = {
|
|
543
|
+
...defaultStyle,
|
|
544
|
+
...style,
|
|
545
|
+
...(isHover ? hoverStyle : null)
|
|
546
|
+
};
|
|
547
|
+
const { normalStyle, hasSelfPercent, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
|
|
548
|
+
enableVar,
|
|
549
|
+
externalVarContext,
|
|
550
|
+
parentFontSize,
|
|
551
|
+
parentWidth,
|
|
552
|
+
parentHeight
|
|
402
553
|
});
|
|
403
|
-
|
|
404
|
-
|
|
554
|
+
const { textStyle, backgroundStyle, innerStyle } = splitStyle(normalStyle);
|
|
555
|
+
enableBackground = enableBackground || !!backgroundStyle;
|
|
556
|
+
const enableBackgroundRef = useRef(enableBackground);
|
|
557
|
+
if (enableBackgroundRef.current !== enableBackground) {
|
|
558
|
+
throw new Error('[Mpx runtime error]: background use should be stable in the component lifecycle, or you can set [enable-background] with true.');
|
|
405
559
|
}
|
|
406
|
-
const
|
|
560
|
+
const nodeRef = useRef(null);
|
|
561
|
+
useNodesRef(props, ref, nodeRef, {
|
|
407
562
|
defaultStyle
|
|
408
563
|
});
|
|
409
564
|
const dataRef = useRef({});
|
|
@@ -436,101 +591,32 @@ const _View = forwardRef((props, ref) => {
|
|
|
436
591
|
bindtouchend && bindtouchend(e);
|
|
437
592
|
setStayTimer();
|
|
438
593
|
}
|
|
439
|
-
|
|
440
|
-
const styleMap = {};
|
|
441
|
-
style.forEach((styleItem) => {
|
|
442
|
-
const transformItemValue = styleObj[styleItem.key];
|
|
443
|
-
if (Array.isArray(transformItemValue)) {
|
|
444
|
-
const transformStyle = [];
|
|
445
|
-
styleObj[styleItem.key].forEach((transformItem) => {
|
|
446
|
-
const rules = styleItem.rules;
|
|
447
|
-
for (const type in rules) {
|
|
448
|
-
const value = transformItem[rules[type]];
|
|
449
|
-
if (value !== undefined) {
|
|
450
|
-
if (PERCENT_REGEX.test(value)) {
|
|
451
|
-
const percentage = parseFloat(value) / 100;
|
|
452
|
-
if (type === 'height' && height) {
|
|
453
|
-
transformStyle.push({ [rules[type]]: percentage * height });
|
|
454
|
-
}
|
|
455
|
-
else if (type === 'width' && width) {
|
|
456
|
-
transformStyle.push({ [rules[type]]: percentage * width });
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
transformStyle.push({ [rules[type]]: 0 });
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
transformStyle.push(transformItem);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
styleMap[styleItem.key] = transformStyle;
|
|
469
|
-
}
|
|
470
|
-
else if (typeof transformItemValue === 'string') {
|
|
471
|
-
const rules = styleItem.rules;
|
|
472
|
-
for (const type in rules) {
|
|
473
|
-
if (transformItemValue) {
|
|
474
|
-
if (PERCENT_REGEX.test(transformItemValue)) {
|
|
475
|
-
const percentage = parseFloat(transformItemValue) / 100;
|
|
476
|
-
if (type === 'height' && height) {
|
|
477
|
-
styleMap[styleItem.key] = percentage * height;
|
|
478
|
-
}
|
|
479
|
-
else if (type === 'width' && width) {
|
|
480
|
-
styleMap[styleItem.key] = percentage * width;
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
styleMap[styleItem.key] = 0;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
styleMap[styleItem.key] = transformItemValue;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
});
|
|
493
|
-
return styleMap;
|
|
494
|
-
}
|
|
495
|
-
const onLayout = (res) => {
|
|
496
|
-
if (hasPercentStyle) {
|
|
497
|
-
const { width, height } = res?.nativeEvent?.layout || {};
|
|
498
|
-
setContainerWidth(width || 0);
|
|
499
|
-
setContainerHeight(height || 0);
|
|
500
|
-
}
|
|
501
|
-
if (enableOffset) {
|
|
502
|
-
nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
|
|
503
|
-
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
};
|
|
507
|
-
const { textStyle, imageStyle, innerStyle } = splitStyle({
|
|
508
|
-
...defaultStyle,
|
|
509
|
-
...styleObj,
|
|
510
|
-
...(isHover ? hoverStyle : null)
|
|
511
|
-
});
|
|
512
|
-
const needLayout = enableOffset || hasPercentStyle;
|
|
594
|
+
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
513
595
|
const innerProps = useInnerProps(props, {
|
|
514
596
|
ref: nodeRef,
|
|
515
|
-
|
|
597
|
+
style: { ...innerStyle, ...layoutStyle },
|
|
598
|
+
...layoutProps,
|
|
516
599
|
...(hoverStyle && {
|
|
517
600
|
bindtouchstart: onTouchStart,
|
|
518
601
|
bindtouchend: onTouchEnd
|
|
519
602
|
})
|
|
520
603
|
}, [
|
|
521
|
-
'style',
|
|
522
|
-
'children',
|
|
523
604
|
'hover-start-time',
|
|
524
605
|
'hover-stay-time',
|
|
525
|
-
'
|
|
526
|
-
'hover-class'
|
|
527
|
-
'enable-offset',
|
|
528
|
-
'enable-background-image'
|
|
606
|
+
'hover-style',
|
|
607
|
+
'hover-class'
|
|
529
608
|
], {
|
|
530
609
|
layoutRef
|
|
531
610
|
});
|
|
532
|
-
return (<View {...innerProps}
|
|
533
|
-
{
|
|
611
|
+
return (<View {...innerProps}>
|
|
612
|
+
{wrapWithChildren(props, {
|
|
613
|
+
hasVarDec,
|
|
614
|
+
enableBackground: enableBackgroundRef.current,
|
|
615
|
+
textStyle,
|
|
616
|
+
backgroundStyle,
|
|
617
|
+
varContext: varContextRef.current,
|
|
618
|
+
textProps
|
|
619
|
+
})}
|
|
534
620
|
</View>);
|
|
535
621
|
});
|
|
536
622
|
_View.displayName = 'mpx-view';
|