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