@mpxjs/webpack-plugin 2.9.59 → 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 +344 -270
- package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
- package/lib/platform/template/wx/component-config/checkbox.js +8 -0
- package/lib/platform/template/wx/component-config/cover-image.js +15 -0
- package/lib/platform/template/wx/component-config/cover-view.js +9 -0
- package/lib/platform/template/wx/component-config/form.js +13 -1
- package/lib/platform/template/wx/component-config/icon.js +8 -0
- package/lib/platform/template/wx/component-config/index.js +5 -1
- package/lib/platform/template/wx/component-config/label.js +15 -0
- package/lib/platform/template/wx/component-config/movable-area.js +18 -1
- package/lib/platform/template/wx/component-config/movable-view.js +18 -1
- package/lib/platform/template/wx/component-config/navigator.js +8 -0
- package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
- package/lib/platform/template/wx/component-config/picker-view.js +18 -2
- package/lib/platform/template/wx/component-config/picker.js +14 -1
- package/lib/platform/template/wx/component-config/radio-group.js +8 -0
- package/lib/platform/template/wx/component-config/radio.js +8 -0
- package/lib/platform/template/wx/component-config/root-portal.js +15 -0
- package/lib/platform/template/wx/component-config/switch.js +8 -0
- package/lib/platform/template/wx/component-config/unsupported.js +1 -3
- package/lib/react/processScript.js +2 -0
- 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 +40 -0
- package/lib/runtime/components/react/dist/context.js +8 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +34 -12
- package/lib/runtime/components/react/dist/mpx-button.jsx +88 -88
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +82 -0
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +139 -0
- package/lib/runtime/components/react/dist/mpx-form.jsx +61 -0
- package/lib/runtime/components/react/dist/mpx-icon.jsx +48 -0
- package/lib/runtime/components/react/dist/mpx-image/index.jsx +39 -43
- package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-input.jsx +63 -37
- package/lib/runtime/components/react/dist/mpx-label.jsx +55 -0
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +41 -0
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
- package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +142 -0
- package/lib/runtime/components/react/dist/mpx-picker/region.jsx +94 -0
- package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
- package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
- package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +107 -0
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +162 -0
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +80 -0
- package/lib/runtime/components/react/dist/mpx-radio.jsx +154 -0
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +15 -0
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +93 -70
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +281 -157
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +21 -11
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +19 -11
- package/lib/runtime/components/react/dist/mpx-switch.jsx +79 -0
- package/lib/runtime/components/react/dist/mpx-text.jsx +21 -49
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +451 -146
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +17 -20
- package/lib/runtime/components/react/dist/parser.js +218 -0
- package/lib/runtime/components/react/dist/types/common.js +1 -0
- package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
- package/lib/runtime/components/react/dist/utils.jsx +433 -0
- package/lib/runtime/components/react/getInnerListeners.ts +43 -21
- package/lib/runtime/components/react/mpx-button.tsx +129 -119
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +152 -0
- package/lib/runtime/components/react/mpx-checkbox.tsx +234 -0
- package/lib/runtime/components/react/mpx-form.tsx +117 -0
- package/lib/runtime/components/react/mpx-icon.tsx +106 -0
- package/lib/runtime/components/react/mpx-image/index.tsx +62 -68
- package/lib/runtime/components/react/mpx-image/svg.tsx +7 -5
- package/lib/runtime/components/react/mpx-input.tsx +90 -42
- package/lib/runtime/components/react/mpx-label.tsx +110 -0
- package/lib/runtime/components/react/mpx-movable-area.tsx +81 -0
- package/lib/runtime/components/react/mpx-movable-view.tsx +424 -0
- package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
- package/lib/runtime/components/react/mpx-picker/date.tsx +82 -0
- package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +156 -0
- package/lib/runtime/components/react/mpx-picker/region.tsx +107 -0
- package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
- package/lib/runtime/components/react/mpx-picker/selector.tsx +91 -0
- package/lib/runtime/components/react/mpx-picker/time.tsx +270 -0
- package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +156 -0
- package/lib/runtime/components/react/mpx-picker-view.tsx +220 -0
- package/lib/runtime/components/react/mpx-radio-group.tsx +150 -0
- package/lib/runtime/components/react/mpx-radio.tsx +230 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +27 -0
- package/lib/runtime/components/react/mpx-scroll-view.tsx +184 -130
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +308 -183
- package/lib/runtime/components/react/mpx-swiper/index.tsx +27 -19
- package/lib/runtime/components/react/mpx-swiper/type.ts +23 -5
- package/lib/runtime/components/react/mpx-swiper-item.tsx +49 -14
- package/lib/runtime/components/react/mpx-switch.tsx +148 -0
- package/lib/runtime/components/react/mpx-text.tsx +53 -77
- package/lib/runtime/components/react/mpx-textarea.tsx +3 -3
- package/lib/runtime/components/react/mpx-view.tsx +576 -195
- package/lib/runtime/components/react/mpx-web-view.tsx +34 -39
- package/lib/runtime/components/react/parser.ts +245 -0
- package/lib/runtime/components/react/types/common.ts +12 -0
- package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
- package/lib/runtime/components/react/types/global.d.ts +17 -1
- package/lib/runtime/components/react/useNodesRef.ts +4 -10
- package/lib/runtime/components/react/utils.tsx +505 -0
- package/lib/runtime/optionProcessor.js +19 -17
- package/lib/template-compiler/compiler.js +84 -61
- package/lib/template-compiler/gen-node-react.js +7 -9
- package/lib/web/processStyles.js +2 -5
- package/package.json +8 -3
- package/lib/runtime/components/react/dist/utils.js +0 -80
- package/lib/runtime/components/react/utils.ts +0 -92
|
@@ -4,48 +4,81 @@
|
|
|
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
|
-
// @ts-ignore
|
|
10
9
|
import useInnerProps from './getInnerListeners';
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
10
|
+
import useNodesRef from './useNodesRef';
|
|
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;
|
|
28
36
|
}
|
|
29
37
|
const applyHandlers = (handlers, args) => {
|
|
30
|
-
for (
|
|
38
|
+
for (const handler of handlers) {
|
|
31
39
|
handler(...args);
|
|
32
40
|
}
|
|
33
41
|
};
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
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;
|
|
48
|
+
// 含有百分号,center 需计算布局
|
|
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
|
|
60
|
+
return {
|
|
61
|
+
// 是否开启layout的计算
|
|
62
|
+
needLayout: isNeedLayout(preImageInfo),
|
|
63
|
+
// 是否开启原始宽度的计算
|
|
64
|
+
needImageSize: isBackgroundSizeKeyword(width) || sizeList.includes('auto')
|
|
65
|
+
};
|
|
37
66
|
};
|
|
38
67
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
function calculateSize(h, lh,
|
|
44
|
-
let height
|
|
45
|
-
|
|
68
|
+
* h - 用户设置的高度
|
|
69
|
+
* lh - 容器的高度
|
|
70
|
+
* ratio - 原始图片的宽高比
|
|
71
|
+
* **/
|
|
72
|
+
function calculateSize(h, ratio, lh, reverse = false) {
|
|
73
|
+
let height = 0;
|
|
74
|
+
let width = 0;
|
|
75
|
+
if (typeof lh === 'boolean') {
|
|
76
|
+
reverse = lh;
|
|
77
|
+
}
|
|
78
|
+
if (isPercent(h)) { // auto px/rpx
|
|
46
79
|
if (!lh)
|
|
47
80
|
return null;
|
|
48
|
-
height = (parseFloat(
|
|
81
|
+
height = (parseFloat(h) / 100) * lh;
|
|
49
82
|
width = height * ratio;
|
|
50
83
|
}
|
|
51
84
|
else { // 2. auto px/rpx - 根据比例计算
|
|
@@ -53,130 +86,389 @@ function calculateSize(h, lh, ratio) {
|
|
|
53
86
|
width = height * ratio;
|
|
54
87
|
}
|
|
55
88
|
return {
|
|
56
|
-
width,
|
|
57
|
-
height
|
|
89
|
+
width: reverse ? height : width,
|
|
90
|
+
height: reverse ? width : height
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 用户设置百分比后,转换为偏移量
|
|
95
|
+
* h - 用户设置图片的高度
|
|
96
|
+
* ch - 容器的高度
|
|
97
|
+
* val - 用户设置的百分比
|
|
98
|
+
* **/
|
|
99
|
+
function calculateSizePosition(h, ch, val) {
|
|
100
|
+
if (!h || !ch)
|
|
101
|
+
return 0;
|
|
102
|
+
// 百分比需要单独的计算
|
|
103
|
+
if (isPercent(h)) {
|
|
104
|
+
h = ch * parseFloat(h) / 100;
|
|
105
|
+
}
|
|
106
|
+
// (container width - image width) * (position x%) = (x offset value)
|
|
107
|
+
return (ch - h) * parseFloat(val) / 100;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 获取图片的展示宽高
|
|
111
|
+
* h - 用户设置的高度
|
|
112
|
+
* lh - 容器的高度
|
|
113
|
+
* **/
|
|
114
|
+
const calcPercent = (h, lh) => {
|
|
115
|
+
return isPercent(h) ? parseFloat(h) / 100 * lh : +h;
|
|
116
|
+
};
|
|
117
|
+
function backgroundPosition(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
118
|
+
const bps = preImageInfo.backgroundPosition;
|
|
119
|
+
if (bps.length === 0)
|
|
120
|
+
return;
|
|
121
|
+
const style = {};
|
|
122
|
+
const imageStyle = imageProps.style || {};
|
|
123
|
+
for (let i = 0; i < bps.length; i += 2) {
|
|
124
|
+
const key = bps[i];
|
|
125
|
+
const val = bps[i + 1];
|
|
126
|
+
// 需要获取 图片宽度 和 容器的宽度 进行计算
|
|
127
|
+
if (isPercent(val)) {
|
|
128
|
+
if (i === 0) {
|
|
129
|
+
style[key] = calculateSizePosition(imageStyle.width, layoutInfo?.width, val);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
style[key] = calculateSizePosition(imageStyle.height, layoutInfo?.height, val);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
style[key] = val;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
imageProps.style = {
|
|
140
|
+
...imageProps.style,
|
|
141
|
+
...style
|
|
58
142
|
};
|
|
59
143
|
}
|
|
60
144
|
// background-size 转换
|
|
61
145
|
function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
|
|
62
|
-
|
|
146
|
+
const sizeList = preImageInfo.sizeList;
|
|
63
147
|
if (!sizeList)
|
|
64
148
|
return;
|
|
149
|
+
const { width: layoutWidth, height: layoutHeight } = layoutInfo || {};
|
|
150
|
+
const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {};
|
|
151
|
+
const [width, height] = sizeList;
|
|
152
|
+
let dimensions = { width: 0, height: 0 };
|
|
65
153
|
// 枚举值
|
|
66
|
-
if (['cover', 'contain'].includes(
|
|
67
|
-
|
|
154
|
+
if (typeof width === 'string' && ['cover', 'contain'].includes(width)) {
|
|
155
|
+
if (layoutInfo && imageSize) {
|
|
156
|
+
const layoutRatio = layoutWidth / imageSizeWidth;
|
|
157
|
+
const eleRatio = imageSizeWidth / imageSizeHeight;
|
|
158
|
+
// 容器宽高比 大于 图片的宽高比,依据宽度作为基准,否则以高度为基准
|
|
159
|
+
if ((layoutRatio <= eleRatio && width === 'contain') || (layoutRatio >= eleRatio && width === 'cover')) {
|
|
160
|
+
dimensions = calculateSize(layoutWidth, imageSizeHeight / imageSizeWidth, true);
|
|
161
|
+
}
|
|
162
|
+
else if ((layoutRatio > eleRatio && width === 'contain') || (layoutRatio < eleRatio && width === 'cover')) {
|
|
163
|
+
dimensions = calculateSize(layoutHeight, imageSizeWidth / imageSizeHeight);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
68
166
|
}
|
|
69
167
|
else {
|
|
70
|
-
const [width, height] = sizeList;
|
|
71
|
-
let newWidth = 0, newHeight = 0;
|
|
72
|
-
const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {};
|
|
73
168
|
if (width === 'auto' && height === 'auto') { // 均为auto
|
|
74
169
|
if (!imageSize)
|
|
75
170
|
return;
|
|
76
|
-
|
|
77
|
-
|
|
171
|
+
dimensions = {
|
|
172
|
+
width: imageSizeWidth,
|
|
173
|
+
height: imageSizeHeight
|
|
174
|
+
};
|
|
78
175
|
}
|
|
79
176
|
else if (width === 'auto') { // auto px/rpx/%
|
|
80
177
|
if (!imageSize)
|
|
81
178
|
return;
|
|
82
|
-
|
|
179
|
+
dimensions = calculateSize(height, imageSizeWidth / imageSizeHeight, layoutInfo?.height);
|
|
83
180
|
if (!dimensions)
|
|
84
181
|
return;
|
|
85
|
-
newWidth = dimensions.width;
|
|
86
|
-
newHeight = dimensions.height;
|
|
87
182
|
}
|
|
88
183
|
else if (height === 'auto') { // auto px/rpx/%
|
|
89
184
|
if (!imageSize)
|
|
90
185
|
return;
|
|
91
|
-
|
|
186
|
+
dimensions = calculateSize(width, imageSizeHeight / imageSizeWidth, layoutInfo?.width, true);
|
|
92
187
|
if (!dimensions)
|
|
93
188
|
return;
|
|
94
|
-
newHeight = dimensions.width;
|
|
95
|
-
newWidth = dimensions.height;
|
|
96
189
|
}
|
|
97
190
|
else { // 数值类型 ImageStyle
|
|
98
191
|
// 数值类型设置为 stretch
|
|
99
192
|
imageProps.style.resizeMode = 'stretch';
|
|
100
|
-
|
|
101
|
-
|
|
193
|
+
dimensions = {
|
|
194
|
+
width: isPercent(width) ? width : +width,
|
|
195
|
+
height: isPercent(height) ? height : +height
|
|
196
|
+
};
|
|
102
197
|
}
|
|
103
|
-
// 样式合并
|
|
104
|
-
imageProps.style = {
|
|
105
|
-
...imageProps.style,
|
|
106
|
-
width: newWidth,
|
|
107
|
-
height: newHeight
|
|
108
|
-
};
|
|
109
198
|
}
|
|
199
|
+
// 样式合并
|
|
200
|
+
imageProps.style = {
|
|
201
|
+
...imageProps.style,
|
|
202
|
+
...dimensions
|
|
203
|
+
};
|
|
110
204
|
}
|
|
111
205
|
// background-image转换为source
|
|
112
206
|
function backgroundImage(imageProps, preImageInfo) {
|
|
113
|
-
|
|
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;
|
|
114
228
|
}
|
|
115
229
|
const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => {
|
|
116
230
|
// 初始化
|
|
117
231
|
const imageProps = {
|
|
118
232
|
style: {
|
|
119
233
|
resizeMode: 'cover',
|
|
120
|
-
|
|
121
|
-
|
|
234
|
+
position: 'absolute'
|
|
235
|
+
// ...StyleSheet.absoluteFillObject
|
|
236
|
+
},
|
|
237
|
+
colors: []
|
|
122
238
|
};
|
|
123
|
-
applyHandlers([backgroundSize, backgroundImage], [imageProps, preImageInfo, imageSize, layoutInfo]);
|
|
124
|
-
if (!imageProps?.src)
|
|
125
|
-
return null;
|
|
239
|
+
applyHandlers([backgroundSize, backgroundImage, backgroundPosition, linearGradient], [imageProps, preImageInfo, imageSize, layoutInfo]);
|
|
126
240
|
return imageProps;
|
|
127
241
|
};
|
|
242
|
+
function isHorizontal(val) {
|
|
243
|
+
return typeof val === 'string' && /^(left|right)$/.test(val);
|
|
244
|
+
}
|
|
245
|
+
function isVertical(val) {
|
|
246
|
+
return typeof val === 'string' && /^(top|bottom)$/.test(val);
|
|
247
|
+
}
|
|
248
|
+
function normalizeBackgroundPosition(parts) {
|
|
249
|
+
if (parts.length === 0)
|
|
250
|
+
return [];
|
|
251
|
+
// 定义默认值
|
|
252
|
+
let hStart = 'left';
|
|
253
|
+
let hOffset = 0;
|
|
254
|
+
let vStart = 'top';
|
|
255
|
+
let vOffset = 0;
|
|
256
|
+
if (parts.length === 4)
|
|
257
|
+
return parts;
|
|
258
|
+
// 归一化
|
|
259
|
+
if (parts.length === 1) {
|
|
260
|
+
// 1. center
|
|
261
|
+
// 2. 2px - hOffset, vOffset(center) - center为50%
|
|
262
|
+
// 3. 10% - hOffset, vOffset(center) - center为50%
|
|
263
|
+
// 4. left - hStart, vOffset(center) - center为50%
|
|
264
|
+
// 5. top - hOffset(center), vStart - center为50%
|
|
265
|
+
if (isHorizontal(parts[0])) {
|
|
266
|
+
hStart = parts[0];
|
|
267
|
+
vOffset = '50%';
|
|
268
|
+
}
|
|
269
|
+
else if (isVertical(parts[0])) {
|
|
270
|
+
vStart = parts[0];
|
|
271
|
+
hOffset = '50%';
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
hOffset = parts[0];
|
|
275
|
+
vOffset = '50%';
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
else if (parts.length === 2) {
|
|
279
|
+
// 1. center center - hOffset, vOffset
|
|
280
|
+
// 2. 10px center - hOffset, vStart
|
|
281
|
+
// 3. left center - hStart, vOffset
|
|
282
|
+
// 4. right center - hStart, vOffset
|
|
283
|
+
// 5. 第一位是 left right 覆盖的是 hStart
|
|
284
|
+
// center, 100% 正常的px 覆盖的是 hOffset
|
|
285
|
+
// 第二位是 top bottom 覆盖的是 vStart
|
|
286
|
+
// center, 100% 覆盖的是 vOffset
|
|
287
|
+
//
|
|
288
|
+
// 水平方向
|
|
289
|
+
if (isHorizontal(parts[0])) {
|
|
290
|
+
hStart = parts[0];
|
|
291
|
+
}
|
|
292
|
+
else { // center, 100% 正常的px 覆盖的是 hOffset
|
|
293
|
+
hOffset = parts[0];
|
|
294
|
+
}
|
|
295
|
+
// 垂直方向
|
|
296
|
+
if (isVertical(parts[1])) {
|
|
297
|
+
vStart = parts[1];
|
|
298
|
+
}
|
|
299
|
+
else { // center, 100% 正常的px 覆盖的是 hOffset
|
|
300
|
+
vOffset = parts[1];
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else if (parts.length === 3) {
|
|
304
|
+
// 1. center top 10px / top 10px center 等价 - center为50%
|
|
305
|
+
// 2. right 10px center / center right 10px 等价 - center为50%
|
|
306
|
+
// 2. bottom 50px right
|
|
307
|
+
if (typeof parts[0] === 'string' && typeof parts[1] === 'string' && /^left|bottom|right|top$/.test(parts[0]) && /^left|bottom|right|top$/.test(parts[1])) {
|
|
308
|
+
[hStart, vStart, vOffset] = parts;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
[hStart, hOffset, vStart] = parts;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return [hStart, hOffset, vStart, vOffset];
|
|
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
|
+
}
|
|
128
407
|
function preParseImage(imageStyle) {
|
|
129
|
-
const { backgroundImage, backgroundSize = [
|
|
130
|
-
const src =
|
|
131
|
-
let sizeList = backgroundSize.slice();
|
|
132
|
-
sizeList.length === 1 && sizeList.push(sizeList[0]);
|
|
408
|
+
const { backgroundImage = '', backgroundSize = ['auto'], backgroundPosition = [0, 0] } = imageStyle || {};
|
|
409
|
+
const { type, src, linearInfo } = parseBgImage(backgroundImage);
|
|
133
410
|
return {
|
|
134
411
|
src,
|
|
135
|
-
|
|
412
|
+
linearInfo,
|
|
413
|
+
type,
|
|
414
|
+
sizeList: normalizeBackgroundSize(backgroundSize, type),
|
|
415
|
+
backgroundPosition: normalizeBackgroundPosition(backgroundPosition)
|
|
136
416
|
};
|
|
137
417
|
}
|
|
418
|
+
function isDiagonalAngle(linearInfo) {
|
|
419
|
+
return !!(linearInfo?.direction && diagonalAngleMap[linearInfo.direction]);
|
|
420
|
+
}
|
|
138
421
|
function wrapImage(imageStyle) {
|
|
139
|
-
|
|
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);
|
|
140
429
|
const [, setImageSizeWidth] = useState(null);
|
|
141
430
|
const [, setImageSizeHeight] = useState(null);
|
|
142
431
|
const [, setLayoutInfoWidth] = useState(null);
|
|
143
432
|
const [, setLayoutInfoHeight] = useState(null);
|
|
144
433
|
const sizeInfo = useRef(null);
|
|
145
434
|
const layoutInfo = useRef(null);
|
|
146
|
-
// 预解析
|
|
147
|
-
const preImageInfo = preParseImage(imageStyle);
|
|
148
|
-
// 判断是否可挂载onLayout
|
|
149
|
-
const needLayout = checkNeedLayout(preImageInfo);
|
|
150
|
-
const { src, sizeList } = preImageInfo;
|
|
151
435
|
useEffect(() => {
|
|
436
|
+
sizeInfo.current = null;
|
|
437
|
+
if (type === 'linear') {
|
|
438
|
+
if (!needLayout)
|
|
439
|
+
setShow(true);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
152
442
|
if (!src) {
|
|
153
443
|
setShow(false);
|
|
154
|
-
sizeInfo.current = null;
|
|
155
|
-
layoutInfo.current = null;
|
|
156
444
|
return;
|
|
445
|
+
// 一开始未出现,数据改变时出现
|
|
157
446
|
}
|
|
158
|
-
if (!
|
|
447
|
+
else if (!(needLayout || needImageSize)) {
|
|
159
448
|
setShow(true);
|
|
160
449
|
return;
|
|
161
450
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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);
|
|
174
466
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}, [
|
|
179
|
-
if (!
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
// type 添加type 处理无渐变 有渐变的场景
|
|
470
|
+
}, [src, type]);
|
|
471
|
+
if (!type)
|
|
180
472
|
return null;
|
|
181
473
|
const onLayout = (res) => {
|
|
182
474
|
const { width, height } = res?.nativeEvent?.layout || {};
|
|
@@ -184,60 +476,77 @@ function wrapImage(imageStyle) {
|
|
|
184
476
|
width,
|
|
185
477
|
height
|
|
186
478
|
};
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
|
|
479
|
+
if (!needImageSize) {
|
|
480
|
+
setLayoutInfoWidth(width);
|
|
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
|
+
}
|
|
492
|
+
}
|
|
493
|
+
else if (sizeInfo.current) {
|
|
190
494
|
setLayoutInfoWidth(width);
|
|
191
495
|
setLayoutInfoHeight(height);
|
|
496
|
+
setImageSizeWidth(sizeInfo.current.width);
|
|
497
|
+
setImageSizeHeight(sizeInfo.current.height);
|
|
192
498
|
setShow(true);
|
|
193
499
|
}
|
|
194
500
|
};
|
|
195
|
-
return <View key='
|
|
196
|
-
{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)}/>}
|
|
197
504
|
</View>;
|
|
198
505
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}, {});
|
|
207
|
-
}
|
|
208
|
-
function every(children, callback) {
|
|
209
|
-
return children.every((child) => callback(child));
|
|
210
|
-
}
|
|
211
|
-
function wrapChildren(children, textStyle, imageStyle) {
|
|
212
|
-
children = Array.isArray(children) ? children : [children];
|
|
213
|
-
if (every(children, (child) => isText(child))) {
|
|
214
|
-
children = [<Text key='viewTextWrap' style={textStyle}>{children}</Text>];
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
if (textStyle)
|
|
218
|
-
console.warn('Text style will be ignored unless every child of the view is Text node!');
|
|
219
|
-
}
|
|
506
|
+
function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backgroundStyle, varContext, textProps }) {
|
|
507
|
+
const children = wrapChildren(props, {
|
|
508
|
+
hasVarDec,
|
|
509
|
+
varContext,
|
|
510
|
+
textStyle,
|
|
511
|
+
textProps
|
|
512
|
+
});
|
|
220
513
|
return [
|
|
221
|
-
wrapImage(
|
|
222
|
-
|
|
514
|
+
enableBackground ? wrapImage(backgroundStyle) : null,
|
|
515
|
+
children
|
|
223
516
|
];
|
|
224
517
|
}
|
|
225
|
-
const _View = forwardRef((
|
|
226
|
-
const {
|
|
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;
|
|
227
521
|
const [isHover, setIsHover] = useState(false);
|
|
228
|
-
const layoutRef = useRef({});
|
|
229
|
-
// 打平 style 数组
|
|
230
|
-
const styleObj = StyleSheet.flatten(style);
|
|
231
522
|
// 默认样式
|
|
232
523
|
const defaultStyle = {
|
|
233
524
|
// flex 布局相关的默认样式
|
|
234
|
-
...
|
|
525
|
+
...style.display === 'flex' && {
|
|
235
526
|
flexDirection: 'row',
|
|
236
527
|
flexBasis: 'auto',
|
|
237
528
|
flexShrink: 1,
|
|
238
529
|
flexWrap: 'nowrap'
|
|
239
530
|
}
|
|
240
531
|
};
|
|
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
|
|
543
|
+
});
|
|
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.');
|
|
549
|
+
}
|
|
241
550
|
const { nodeRef } = useNodesRef(props, ref, {
|
|
242
551
|
defaultStyle
|
|
243
552
|
});
|
|
@@ -251,14 +560,14 @@ const _View = forwardRef((props, ref) => {
|
|
|
251
560
|
const setStartTimer = () => {
|
|
252
561
|
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
253
562
|
dataRef.current.startTimer = setTimeout(() => {
|
|
254
|
-
setIsHover(
|
|
563
|
+
setIsHover(true);
|
|
255
564
|
}, +hoverStartTime);
|
|
256
565
|
};
|
|
257
566
|
const setStayTimer = () => {
|
|
258
567
|
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
259
568
|
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
260
569
|
dataRef.current.stayTimer = setTimeout(() => {
|
|
261
|
-
setIsHover(
|
|
570
|
+
setIsHover(false);
|
|
262
571
|
}, +hoverStayTime);
|
|
263
572
|
};
|
|
264
573
|
function onTouchStart(e) {
|
|
@@ -271,36 +580,32 @@ const _View = forwardRef((props, ref) => {
|
|
|
271
580
|
bindtouchend && bindtouchend(e);
|
|
272
581
|
setStayTimer();
|
|
273
582
|
}
|
|
274
|
-
const
|
|
275
|
-
nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
|
|
276
|
-
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
|
|
277
|
-
});
|
|
278
|
-
};
|
|
279
|
-
const { textStyle, imageStyle, innerStyle } = splitStyle(StyleSheet.flatten([
|
|
280
|
-
defaultStyle,
|
|
281
|
-
styleObj,
|
|
282
|
-
...(isHover ? hoverStyle : [])
|
|
283
|
-
]));
|
|
583
|
+
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
284
584
|
const innerProps = useInnerProps(props, {
|
|
285
585
|
ref: nodeRef,
|
|
286
|
-
|
|
586
|
+
style: { ...innerStyle, ...layoutStyle },
|
|
587
|
+
...layoutProps,
|
|
287
588
|
...(hoverStyle && {
|
|
288
589
|
bindtouchstart: onTouchStart,
|
|
289
590
|
bindtouchend: onTouchEnd
|
|
290
591
|
})
|
|
291
592
|
}, [
|
|
292
|
-
'style',
|
|
293
|
-
'children',
|
|
294
593
|
'hover-start-time',
|
|
295
594
|
'hover-stay-time',
|
|
296
|
-
'
|
|
297
|
-
'hover-class'
|
|
298
|
-
'enable-offset'
|
|
595
|
+
'hover-style',
|
|
596
|
+
'hover-class'
|
|
299
597
|
], {
|
|
300
598
|
layoutRef
|
|
301
599
|
});
|
|
302
|
-
return (<View {...innerProps}
|
|
303
|
-
{
|
|
600
|
+
return (<View {...innerProps}>
|
|
601
|
+
{wrapWithChildren(props, {
|
|
602
|
+
hasVarDec,
|
|
603
|
+
enableBackground: enableBackgroundRef.current,
|
|
604
|
+
textStyle,
|
|
605
|
+
backgroundStyle,
|
|
606
|
+
varContext: varContextRef.current,
|
|
607
|
+
textProps
|
|
608
|
+
})}
|
|
304
609
|
</View>);
|
|
305
610
|
});
|
|
306
611
|
_View.displayName = 'mpx-view';
|