@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
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import { useEffect, useRef, isValidElement, useContext, useState, Children, cloneElement } from 'react';
|
|
2
|
+
import { isObject, hasOwn, diffAndCloneA, error, warn, getFocusedNavigation } from '@mpxjs/utils';
|
|
3
|
+
import { VarContext } from './context';
|
|
4
|
+
import { ExpressionParser, parseFunc, ReplaceSource } from './parser';
|
|
5
|
+
import { initialWindowMetrics } from 'react-native-safe-area-context';
|
|
6
|
+
export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/;
|
|
7
|
+
export const PERCENT_REGEX = /^\s*-?\d+(\.\d+)?%\s*$/;
|
|
8
|
+
export const URL_REGEX = /^\s*url\(["']?(.*?)["']?\)\s*$/;
|
|
9
|
+
export const BACKGROUND_REGEX = /^background(Image|Size|Repeat|Position)$/;
|
|
10
|
+
export const TEXT_PROPS_REGEX = /ellipsizeMode|numberOfLines/;
|
|
11
|
+
export const DEFAULT_FONT_SIZE = 16;
|
|
12
|
+
export const DEFAULT_UNLAY_STYLE = {
|
|
13
|
+
opacity: 0
|
|
14
|
+
};
|
|
15
|
+
const varDecRegExp = /^--.*/;
|
|
16
|
+
const varUseRegExp = /var\(/;
|
|
17
|
+
const calcUseRegExp = /calc\(/;
|
|
18
|
+
const envUseRegExp = /env\(/;
|
|
19
|
+
const safeAreaInsetMap = {
|
|
20
|
+
'safe-area-inset-top': 'top',
|
|
21
|
+
'safe-area-inset-right': 'right',
|
|
22
|
+
'safe-area-inset-bottom': 'bottom',
|
|
23
|
+
'safe-area-inset-left': 'left'
|
|
24
|
+
};
|
|
25
|
+
function getSafeAreaInset(name) {
|
|
26
|
+
const navigation = getFocusedNavigation();
|
|
27
|
+
const insets = {
|
|
28
|
+
...initialWindowMetrics?.insets,
|
|
29
|
+
...navigation?.insets
|
|
30
|
+
};
|
|
31
|
+
return insets[safeAreaInsetMap[name]];
|
|
32
|
+
}
|
|
33
|
+
export function omit(obj, fields) {
|
|
34
|
+
const shallowCopy = Object.assign({}, obj);
|
|
35
|
+
for (let i = 0; i < fields.length; i += 1) {
|
|
36
|
+
const key = fields[i];
|
|
37
|
+
delete shallowCopy[key];
|
|
38
|
+
}
|
|
39
|
+
return shallowCopy;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行
|
|
43
|
+
*/
|
|
44
|
+
export const useUpdateEffect = (effect, deps) => {
|
|
45
|
+
const isMounted = useRef(false);
|
|
46
|
+
// for react-refresh
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
return () => {
|
|
49
|
+
isMounted.current = false;
|
|
50
|
+
};
|
|
51
|
+
}, []);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!isMounted.current) {
|
|
54
|
+
isMounted.current = true;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return effect();
|
|
58
|
+
}
|
|
59
|
+
}, deps);
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* 解析行内样式
|
|
63
|
+
* @param inlineStyle
|
|
64
|
+
* @returns
|
|
65
|
+
*/
|
|
66
|
+
export const parseInlineStyle = (inlineStyle = '') => {
|
|
67
|
+
return inlineStyle.split(';').reduce((styleObj, style) => {
|
|
68
|
+
const [k, v, ...rest] = style.split(':');
|
|
69
|
+
if (rest.length || !v || !k)
|
|
70
|
+
return styleObj;
|
|
71
|
+
const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase());
|
|
72
|
+
return Object.assign(styleObj, { [key]: v.trim() });
|
|
73
|
+
}, {});
|
|
74
|
+
};
|
|
75
|
+
export const parseUrl = (cssUrl = '') => {
|
|
76
|
+
if (!cssUrl)
|
|
77
|
+
return;
|
|
78
|
+
const match = cssUrl.match(URL_REGEX);
|
|
79
|
+
return match?.[1];
|
|
80
|
+
};
|
|
81
|
+
export const getRestProps = (transferProps = {}, originProps = {}, deletePropsKey = []) => {
|
|
82
|
+
return {
|
|
83
|
+
...transferProps,
|
|
84
|
+
...omit(originProps, deletePropsKey)
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
export function isText(ele) {
|
|
88
|
+
if (isValidElement(ele)) {
|
|
89
|
+
const displayName = ele.type?.displayName;
|
|
90
|
+
return displayName === 'mpx-text' || displayName === 'Text';
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
export function isEmbedded(ele) {
|
|
95
|
+
if (isValidElement(ele)) {
|
|
96
|
+
const displayName = ele.type?.displayName || '';
|
|
97
|
+
return ['mpx-checkbox', 'mpx-radio', 'mpx-switch'].includes(displayName);
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
export function every(children, callback) {
|
|
102
|
+
const childrenArray = Array.isArray(children) ? children : [children];
|
|
103
|
+
return childrenArray.every((child) => callback(child));
|
|
104
|
+
}
|
|
105
|
+
export function groupBy(obj, callback, group = {}) {
|
|
106
|
+
Object.entries(obj).forEach(([key, val]) => {
|
|
107
|
+
const groupKey = callback(key, val);
|
|
108
|
+
group[groupKey] = group[groupKey] || {};
|
|
109
|
+
group[groupKey][key] = val;
|
|
110
|
+
});
|
|
111
|
+
return group;
|
|
112
|
+
}
|
|
113
|
+
export function splitStyle(styleObj) {
|
|
114
|
+
return groupBy(styleObj, (key) => {
|
|
115
|
+
if (TEXT_STYLE_REGEX.test(key)) {
|
|
116
|
+
return 'textStyle';
|
|
117
|
+
}
|
|
118
|
+
else if (BACKGROUND_REGEX.test(key)) {
|
|
119
|
+
return 'backgroundStyle';
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
return 'innerStyle';
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const selfPercentRule = {
|
|
127
|
+
translateX: 'width',
|
|
128
|
+
translateY: 'height',
|
|
129
|
+
borderTopLeftRadius: 'width',
|
|
130
|
+
borderBottomLeftRadius: 'width',
|
|
131
|
+
borderBottomRightRadius: 'width',
|
|
132
|
+
borderTopRightRadius: 'width',
|
|
133
|
+
borderRadius: 'width'
|
|
134
|
+
};
|
|
135
|
+
const parentHeightPercentRule = {
|
|
136
|
+
height: true,
|
|
137
|
+
top: true,
|
|
138
|
+
bottom: true
|
|
139
|
+
};
|
|
140
|
+
function resolvePercent(value, key, percentConfig) {
|
|
141
|
+
if (!(typeof value === 'string' && PERCENT_REGEX.test(value)))
|
|
142
|
+
return value;
|
|
143
|
+
let base;
|
|
144
|
+
let reason;
|
|
145
|
+
if (key === 'fontSize') {
|
|
146
|
+
base = percentConfig.parentFontSize;
|
|
147
|
+
reason = 'parent-font-size';
|
|
148
|
+
}
|
|
149
|
+
else if (key === 'lineHeight') {
|
|
150
|
+
base = resolvePercent(percentConfig.fontSize, 'fontSize', percentConfig);
|
|
151
|
+
reason = 'font-size';
|
|
152
|
+
}
|
|
153
|
+
else if (selfPercentRule[key]) {
|
|
154
|
+
base = percentConfig[selfPercentRule[key]];
|
|
155
|
+
reason = selfPercentRule[key];
|
|
156
|
+
}
|
|
157
|
+
else if (parentHeightPercentRule[key]) {
|
|
158
|
+
base = percentConfig.parentHeight;
|
|
159
|
+
reason = 'parent-height';
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
base = percentConfig.parentWidth;
|
|
163
|
+
reason = 'parent-width';
|
|
164
|
+
}
|
|
165
|
+
if (typeof base !== 'number') {
|
|
166
|
+
error(`[${key}] can not contain % unit unless you set [${reason}] with a number for the percent calculation.`);
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
return parseFloat(value) / 100 * base;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function transformPercent(styleObj, percentKeyPaths, percentConfig) {
|
|
174
|
+
percentKeyPaths.forEach((percentKeyPath) => {
|
|
175
|
+
setStyle(styleObj, percentKeyPath, ({ target, key, value }) => {
|
|
176
|
+
target[key] = resolvePercent(value, key, percentConfig);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function resolveVar(input, varContext) {
|
|
181
|
+
const parsed = parseFunc(input, 'var');
|
|
182
|
+
const replaced = new ReplaceSource(input);
|
|
183
|
+
parsed.forEach(({ start, end, args }) => {
|
|
184
|
+
const varName = args[0];
|
|
185
|
+
const fallback = args[1] || '';
|
|
186
|
+
let varValue = hasOwn(varContext, varName) ? varContext[varName] : fallback;
|
|
187
|
+
if (varUseRegExp.test(varValue)) {
|
|
188
|
+
varValue = '' + resolveVar(varValue, varContext);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
varValue = '' + global.__formatValue(varValue);
|
|
192
|
+
}
|
|
193
|
+
replaced.replace(start, end - 1, varValue);
|
|
194
|
+
});
|
|
195
|
+
return global.__formatValue(replaced.source());
|
|
196
|
+
}
|
|
197
|
+
function transformVar(styleObj, varKeyPaths, varContext) {
|
|
198
|
+
varKeyPaths.forEach((varKeyPath) => {
|
|
199
|
+
setStyle(styleObj, varKeyPath, ({ target, key, value }) => {
|
|
200
|
+
target[key] = resolveVar(value, varContext);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function transformEnv(styleObj, envKeyPaths) {
|
|
205
|
+
envKeyPaths.forEach((envKeyPath) => {
|
|
206
|
+
setStyle(styleObj, envKeyPath, ({ target, key, value }) => {
|
|
207
|
+
const parsed = parseFunc(value, 'env');
|
|
208
|
+
const replaced = new ReplaceSource(value);
|
|
209
|
+
parsed.forEach(({ start, end, args }) => {
|
|
210
|
+
const name = args[0];
|
|
211
|
+
const fallback = args[1] || '';
|
|
212
|
+
const value = '' + (getSafeAreaInset(name) ?? global.__formatValue(fallback));
|
|
213
|
+
replaced.replace(start, end - 1, value);
|
|
214
|
+
});
|
|
215
|
+
target[key] = global.__formatValue(replaced.source());
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
function transformCalc(styleObj, calcKeyPaths, formatter) {
|
|
220
|
+
calcKeyPaths.forEach((calcKeyPath) => {
|
|
221
|
+
setStyle(styleObj, calcKeyPath, ({ target, key, value }) => {
|
|
222
|
+
const parsed = parseFunc(value, 'calc');
|
|
223
|
+
const replaced = new ReplaceSource(value);
|
|
224
|
+
parsed.forEach(({ start, end, args }) => {
|
|
225
|
+
const exp = args[0];
|
|
226
|
+
try {
|
|
227
|
+
const result = new ExpressionParser(exp, (value) => {
|
|
228
|
+
return formatter(value, key);
|
|
229
|
+
}).parse();
|
|
230
|
+
replaced.replace(start, end - 1, '' + result.value);
|
|
231
|
+
}
|
|
232
|
+
catch (e) {
|
|
233
|
+
error(`calc(${exp}) parse error.`, undefined, e);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
target[key] = global.__formatValue(replaced.source());
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }) {
|
|
241
|
+
const varStyle = {};
|
|
242
|
+
const normalStyle = {};
|
|
243
|
+
let hasVarDec = false;
|
|
244
|
+
let hasVarUse = false;
|
|
245
|
+
let hasSelfPercent = false;
|
|
246
|
+
const varKeyPaths = [];
|
|
247
|
+
const percentKeyPaths = [];
|
|
248
|
+
const calcKeyPaths = [];
|
|
249
|
+
const envKeyPaths = [];
|
|
250
|
+
const [width, setWidth] = useState(0);
|
|
251
|
+
const [height, setHeight] = useState(0);
|
|
252
|
+
function varVisitor({ key, value, keyPath }) {
|
|
253
|
+
if (keyPath.length === 1) {
|
|
254
|
+
if (varDecRegExp.test(key)) {
|
|
255
|
+
hasVarDec = true;
|
|
256
|
+
varStyle[key] = value;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
// clone对象避免set值时改写到props
|
|
260
|
+
normalStyle[key] = isObject(value) ? diffAndCloneA(value).clone : value;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// 对于var定义中使用的var无需替换值,可以通过resolveVar递归解析出值
|
|
264
|
+
if (!varDecRegExp.test(key) && varUseRegExp.test(value)) {
|
|
265
|
+
hasVarUse = true;
|
|
266
|
+
varKeyPaths.push(keyPath.slice());
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// traverse var
|
|
270
|
+
traverseStyle(styleObj, [varVisitor]);
|
|
271
|
+
hasVarDec = hasVarDec || !!externalVarContext;
|
|
272
|
+
enableVar = enableVar || hasVarDec || hasVarUse;
|
|
273
|
+
const enableVarRef = useRef(enableVar);
|
|
274
|
+
if (enableVarRef.current !== enableVar) {
|
|
275
|
+
error('css variable use/declare should be stable in the component lifecycle, or you can set [enable-var] with true.');
|
|
276
|
+
}
|
|
277
|
+
// apply var
|
|
278
|
+
const varContextRef = useRef({});
|
|
279
|
+
if (enableVarRef.current) {
|
|
280
|
+
const varContext = useContext(VarContext);
|
|
281
|
+
const newVarContext = Object.assign({}, varContext, externalVarContext, varStyle);
|
|
282
|
+
// 缓存比较newVarContext是否发生变化
|
|
283
|
+
if (diffAndCloneA(varContextRef.current, newVarContext).diff) {
|
|
284
|
+
varContextRef.current = newVarContext;
|
|
285
|
+
}
|
|
286
|
+
transformVar(normalStyle, varKeyPaths, varContextRef.current);
|
|
287
|
+
}
|
|
288
|
+
function envVisitor({ value, keyPath }) {
|
|
289
|
+
if (envUseRegExp.test(value)) {
|
|
290
|
+
envKeyPaths.push(keyPath.slice());
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function calcVisitor({ value, keyPath }) {
|
|
294
|
+
if (calcUseRegExp.test(value)) {
|
|
295
|
+
calcKeyPaths.push(keyPath.slice());
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function percentVisitor({ key, value, keyPath }) {
|
|
299
|
+
if (hasOwn(selfPercentRule, key) && PERCENT_REGEX.test(value)) {
|
|
300
|
+
hasSelfPercent = true;
|
|
301
|
+
percentKeyPaths.push(keyPath.slice());
|
|
302
|
+
}
|
|
303
|
+
else if ((key === 'fontSize' || key === 'lineHeight') && PERCENT_REGEX.test(value)) {
|
|
304
|
+
percentKeyPaths.push(keyPath.slice());
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// traverse env & calc & percent
|
|
308
|
+
traverseStyle(normalStyle, [envVisitor, percentVisitor, calcVisitor]);
|
|
309
|
+
const percentConfig = {
|
|
310
|
+
width,
|
|
311
|
+
height,
|
|
312
|
+
fontSize: normalStyle.fontSize,
|
|
313
|
+
parentWidth,
|
|
314
|
+
parentHeight,
|
|
315
|
+
parentFontSize
|
|
316
|
+
};
|
|
317
|
+
// apply env
|
|
318
|
+
transformEnv(normalStyle, envKeyPaths);
|
|
319
|
+
// apply percent
|
|
320
|
+
transformPercent(normalStyle, percentKeyPaths, percentConfig);
|
|
321
|
+
// apply calc
|
|
322
|
+
transformCalc(normalStyle, calcKeyPaths, (value, key) => {
|
|
323
|
+
if (PERCENT_REGEX.test(value)) {
|
|
324
|
+
const resolved = resolvePercent(value, key, percentConfig);
|
|
325
|
+
return typeof resolved === 'number' ? resolved : 0;
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
const formatted = global.__formatValue(value);
|
|
329
|
+
if (typeof formatted === 'number') {
|
|
330
|
+
return formatted;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
warn('calc() only support number, px, rpx, % temporarily.');
|
|
334
|
+
return 0;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
return {
|
|
339
|
+
normalStyle,
|
|
340
|
+
hasSelfPercent,
|
|
341
|
+
hasVarDec,
|
|
342
|
+
enableVarRef,
|
|
343
|
+
varContextRef,
|
|
344
|
+
setWidth,
|
|
345
|
+
setHeight
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
export function traverseStyle(styleObj, visitors) {
|
|
349
|
+
const keyPath = [];
|
|
350
|
+
function traverse(target) {
|
|
351
|
+
if (Array.isArray(target)) {
|
|
352
|
+
target.forEach((value, index) => {
|
|
353
|
+
const key = String(index);
|
|
354
|
+
keyPath.push(key);
|
|
355
|
+
visitors.forEach(visitor => visitor({
|
|
356
|
+
target,
|
|
357
|
+
key,
|
|
358
|
+
value,
|
|
359
|
+
keyPath
|
|
360
|
+
}));
|
|
361
|
+
traverse(value);
|
|
362
|
+
keyPath.pop();
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
else if (isObject(target)) {
|
|
366
|
+
Object.entries(target).forEach(([key, value]) => {
|
|
367
|
+
keyPath.push(key);
|
|
368
|
+
visitors.forEach(visitor => visitor({ target, key, value, keyPath }));
|
|
369
|
+
traverse(value);
|
|
370
|
+
keyPath.pop();
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
traverse(styleObj);
|
|
375
|
+
}
|
|
376
|
+
export function setStyle(styleObj, keyPath, setter) {
|
|
377
|
+
let target = styleObj;
|
|
378
|
+
const lastKey = keyPath[keyPath.length - 1];
|
|
379
|
+
for (let i = 0; i < keyPath.length - 1; i++) {
|
|
380
|
+
target = target[keyPath[i]];
|
|
381
|
+
if (!target)
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
setter({
|
|
385
|
+
target,
|
|
386
|
+
key: lastKey,
|
|
387
|
+
value: target[lastKey],
|
|
388
|
+
keyPath
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
export function splitProps(props) {
|
|
392
|
+
return groupBy(props, (key) => {
|
|
393
|
+
if (TEXT_PROPS_REGEX.test(key)) {
|
|
394
|
+
return 'textProps';
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
return 'innerProps';
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout, nodeRef }) => {
|
|
402
|
+
const layoutRef = useRef({});
|
|
403
|
+
const hasLayoutRef = useRef(false);
|
|
404
|
+
const layoutStyle = !hasLayoutRef.current && hasSelfPercent ? DEFAULT_UNLAY_STYLE : {};
|
|
405
|
+
const layoutProps = {};
|
|
406
|
+
const enableOffset = props['enable-offset'];
|
|
407
|
+
if (hasSelfPercent || onLayout || enableOffset) {
|
|
408
|
+
layoutProps.onLayout = (e) => {
|
|
409
|
+
hasLayoutRef.current = true;
|
|
410
|
+
if (hasSelfPercent) {
|
|
411
|
+
const { width, height } = e?.nativeEvent?.layout || {};
|
|
412
|
+
setWidth(width || 0);
|
|
413
|
+
setHeight(height || 0);
|
|
414
|
+
}
|
|
415
|
+
if (enableOffset) {
|
|
416
|
+
nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
|
|
417
|
+
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
onLayout && onLayout(e);
|
|
421
|
+
props.onLayout && props.onLayout(e);
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
layoutRef,
|
|
426
|
+
layoutStyle,
|
|
427
|
+
layoutProps
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
export function wrapChildren(props = {}, { hasVarDec, varContext, textStyle, textProps }) {
|
|
431
|
+
let { children } = props;
|
|
432
|
+
if (textStyle || textProps) {
|
|
433
|
+
children = Children.map(children, (child) => {
|
|
434
|
+
if (isText(child)) {
|
|
435
|
+
const style = { ...textStyle, ...child.props.style };
|
|
436
|
+
return cloneElement(child, { ...textProps, style });
|
|
437
|
+
}
|
|
438
|
+
return child;
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
if (hasVarDec && varContext) {
|
|
442
|
+
children = <VarContext.Provider value={varContext} key='varContextWrap'>{children}</VarContext.Provider>;
|
|
443
|
+
}
|
|
444
|
+
return children;
|
|
445
|
+
}
|
|
@@ -82,7 +82,7 @@ export const getDataSet = (props: Record<string, any>) => {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export const getCustomEvent = (
|
|
85
|
-
type
|
|
85
|
+
type = '',
|
|
86
86
|
oe: any = {},
|
|
87
87
|
{ detail = {}, layoutRef }: { detail?: Record<string, unknown>; layoutRef: LayoutRef },
|
|
88
88
|
props: Props = {}
|
|
@@ -107,7 +107,7 @@ export const getCustomEvent = (
|
|
|
107
107
|
const useInnerProps = (
|
|
108
108
|
props: Props = {},
|
|
109
109
|
additionalProps: AdditionalProps = {},
|
|
110
|
-
|
|
110
|
+
userRemoveProps: RemoveProps = [],
|
|
111
111
|
rawConfig?: UseInnerPropsConfig
|
|
112
112
|
) => {
|
|
113
113
|
const ref = useRef<InnerRef>({
|
|
@@ -130,6 +130,17 @@ const useInnerProps = (
|
|
|
130
130
|
const propsRef = useRef<Record<string, any>>({})
|
|
131
131
|
const eventConfig: { [key: string]: string[] } = {}
|
|
132
132
|
const config = rawConfig || { layoutRef: { current: {} }, disableTouch: false, disableTap: false }
|
|
133
|
+
const removeProps = [
|
|
134
|
+
'children',
|
|
135
|
+
'enable-background',
|
|
136
|
+
'enable-offset',
|
|
137
|
+
'enable-var',
|
|
138
|
+
'external-var-context',
|
|
139
|
+
'parent-font-size',
|
|
140
|
+
'parent-width',
|
|
141
|
+
'parent-height',
|
|
142
|
+
...userRemoveProps
|
|
143
|
+
]
|
|
133
144
|
|
|
134
145
|
propsRef.current = { ...props, ...additionalProps }
|
|
135
146
|
|
|
@@ -143,7 +154,7 @@ const useInnerProps = (
|
|
|
143
154
|
return omit(propsRef.current, removeProps)
|
|
144
155
|
}
|
|
145
156
|
|
|
146
|
-
function handleEmitEvent(
|
|
157
|
+
function handleEmitEvent (
|
|
147
158
|
events: string[],
|
|
148
159
|
type: string,
|
|
149
160
|
oe: NativeTouchEvent
|
|
@@ -171,7 +182,7 @@ const useInnerProps = (
|
|
|
171
182
|
}
|
|
172
183
|
}
|
|
173
184
|
|
|
174
|
-
function handleTouchstart(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
185
|
+
function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
175
186
|
e.persist()
|
|
176
187
|
const bubbleTouchEvent = ['catchtouchstart', 'bindtouchstart']
|
|
177
188
|
const bubblePressEvent = ['catchlongpress', 'bindlongpress']
|
|
@@ -196,7 +207,7 @@ const useInnerProps = (
|
|
|
196
207
|
}
|
|
197
208
|
}
|
|
198
209
|
|
|
199
|
-
function handleTouchmove(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
210
|
+
function handleTouchmove (e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
200
211
|
const bubbleTouchEvent = ['catchtouchmove', 'bindtouchmove']
|
|
201
212
|
const captureTouchEvent = ['capture-catchtouchmove', 'capture-bindtouchmove']
|
|
202
213
|
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
@@ -204,7 +215,7 @@ const useInnerProps = (
|
|
|
204
215
|
checkIsNeedPress(e, type)
|
|
205
216
|
}
|
|
206
217
|
|
|
207
|
-
function handleTouchend(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
218
|
+
function handleTouchend (e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
208
219
|
// move event may not be triggered
|
|
209
220
|
checkIsNeedPress(e, type)
|
|
210
221
|
const bubbleTouchEvent = ['catchtouchend', 'bindtouchend']
|
|
@@ -224,7 +235,7 @@ const useInnerProps = (
|
|
|
224
235
|
}
|
|
225
236
|
}
|
|
226
237
|
|
|
227
|
-
function handleTouchcancel(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
238
|
+
function handleTouchcancel (e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
228
239
|
const bubbleTouchEvent = ['catchtouchcancel', 'bindtouchcancel']
|
|
229
240
|
const captureTouchEvent = ['capture-catchtouchcancel', 'capture-bindtouchcancel']
|
|
230
241
|
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
@@ -284,7 +295,6 @@ const useInnerProps = (
|
|
|
284
295
|
|
|
285
296
|
const finalEventKeys = [...new Set(transformedEventKeys)]
|
|
286
297
|
|
|
287
|
-
|
|
288
298
|
touchEventList.forEach(item => {
|
|
289
299
|
if (finalEventKeys.includes(item.eventName)) {
|
|
290
300
|
events[item.eventName] = item.handler
|