@mpxjs/webpack-plugin 2.10.2 → 2.10.3
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/dependencies/RecordPageConfigsMapDependency.js +45 -0
- package/lib/index.js +12 -0
- package/lib/platform/style/wx/index.js +6 -4
- package/lib/platform/template/wx/component-config/view.js +12 -2
- package/lib/react/index.js +0 -1
- package/lib/react/processJSON.js +13 -2
- package/lib/react/processScript.js +4 -2
- package/lib/react/processTemplate.js +18 -3
- package/lib/react/script-helper.js +18 -4
- package/lib/runtime/components/react/dist/mpx-input.jsx +1 -11
- package/lib/runtime/components/react/dist/{KeyboardAvoidingView.jsx → mpx-keyboard-avoiding-view.jsx} +4 -3
- package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +10 -5
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +22 -0
- package/lib/runtime/components/react/dist/mpx-view.jsx +10 -5
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +2 -2
- package/lib/runtime/components/react/dist/useAnimationHooks.js +46 -48
- package/lib/runtime/components/react/dist/utils.jsx +17 -7
- package/lib/runtime/components/react/mpx-input.tsx +1 -19
- package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx} +4 -2
- package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +1 -2
- package/lib/runtime/components/react/mpx-scroll-view.tsx +13 -4
- package/lib/runtime/components/react/mpx-simple-view.tsx +32 -0
- package/lib/runtime/components/react/mpx-view.tsx +17 -10
- package/lib/runtime/components/react/mpx-web-view.tsx +7 -7
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +46 -48
- package/lib/runtime/components/react/utils.tsx +21 -10
- package/lib/runtime/optionProcessor.js +3 -2
- package/lib/style-compiler/index.js +8 -6
- package/lib/template-compiler/compiler.js +20 -12
- package/lib/utils/match-condition.js +14 -8
- package/lib/web/processJSON.js +1 -3
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { Easing, useSharedValue, withTiming, useAnimatedStyle, withSequence, withDelay, makeMutable, cancelAnimation } from 'react-native-reanimated';
|
|
3
|
-
import { error } from '@mpxjs/utils';
|
|
3
|
+
import { error, hasOwn } from '@mpxjs/utils';
|
|
4
4
|
// 微信 timingFunction 和 RN Easing 对应关系
|
|
5
5
|
const EasingKey = {
|
|
6
6
|
linear: Easing.linear,
|
|
@@ -14,20 +14,20 @@ const EasingKey = {
|
|
|
14
14
|
const TransformInitial = {
|
|
15
15
|
// matrix: 0,
|
|
16
16
|
// matrix3d: 0,
|
|
17
|
-
rotate: '0deg',
|
|
17
|
+
// rotate: '0deg',
|
|
18
18
|
rotateX: '0deg',
|
|
19
19
|
rotateY: '0deg',
|
|
20
20
|
rotateZ: '0deg',
|
|
21
21
|
// rotate3d:[0,0,0]
|
|
22
|
-
scale: 1,
|
|
22
|
+
// scale: 1,
|
|
23
23
|
// scale3d: [1, 1, 1],
|
|
24
24
|
scaleX: 1,
|
|
25
25
|
scaleY: 1,
|
|
26
26
|
// scaleZ: 1,
|
|
27
|
-
skew: 0,
|
|
27
|
+
// skew: 0,
|
|
28
28
|
skewX: '0deg',
|
|
29
29
|
skewY: '0deg',
|
|
30
|
-
translate: 0,
|
|
30
|
+
// translate: 0,
|
|
31
31
|
// translate3d: 0,
|
|
32
32
|
translateX: 0,
|
|
33
33
|
translateY: 0
|
|
@@ -92,23 +92,23 @@ const parseTransform = (transformStr) => {
|
|
|
92
92
|
case 'skewX':
|
|
93
93
|
case 'skewY':
|
|
94
94
|
case 'perspective':
|
|
95
|
+
// rotate 处理成 rotateZ
|
|
96
|
+
key = key === 'rotate' ? 'rotateZ' : key;
|
|
95
97
|
// 单个值处理
|
|
96
98
|
transform.push({ [key]: global.__formatValue(val) });
|
|
97
99
|
break;
|
|
98
100
|
case 'matrix':
|
|
99
|
-
case 'matrix3d':
|
|
100
101
|
transform.push({ [key]: parseValues(val, ',').map(val => +val) });
|
|
101
102
|
break;
|
|
102
103
|
case 'translate':
|
|
103
104
|
case 'scale':
|
|
104
105
|
case 'skew':
|
|
105
|
-
case 'rotate3d': // x y z angle
|
|
106
106
|
case 'translate3d': // x y 支持 z不支持
|
|
107
107
|
case 'scale3d': // x y 支持 z不支持
|
|
108
108
|
{
|
|
109
109
|
// 2 个以上的值处理
|
|
110
110
|
key = key.replace('3d', '');
|
|
111
|
-
const vals = parseValues(val, ',').splice(0,
|
|
111
|
+
const vals = parseValues(val, ',').splice(0, 3);
|
|
112
112
|
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
113
113
|
if (vals.length === 1 && key === 'scale') {
|
|
114
114
|
vals.push(vals[0]);
|
|
@@ -132,6 +132,13 @@ const formatStyle = (style) => {
|
|
|
132
132
|
transform: parseTransform(style.transform)
|
|
133
133
|
});
|
|
134
134
|
};
|
|
135
|
+
// transform 数组转对象
|
|
136
|
+
function getTransformObj(transforms) {
|
|
137
|
+
'worklet';
|
|
138
|
+
return transforms.reduce((transformObj, item) => {
|
|
139
|
+
return Object.assign(transformObj, item);
|
|
140
|
+
}, {});
|
|
141
|
+
}
|
|
135
142
|
export default function useAnimationHooks(props) {
|
|
136
143
|
const { style = {}, animation, enableAnimation } = props;
|
|
137
144
|
const enableStyleAnimation = enableAnimation || !!animation;
|
|
@@ -150,7 +157,9 @@ export default function useAnimationHooks(props) {
|
|
|
150
157
|
// 记录动画key的style样式值 没有的话设置为false
|
|
151
158
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
152
159
|
const animatedKeys = useRef({});
|
|
153
|
-
//
|
|
160
|
+
// 记录上次style map
|
|
161
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
162
|
+
const lastStyleRef = useRef({});
|
|
154
163
|
// ** 全量 style prop sharedValue
|
|
155
164
|
// 不能做增量的原因:
|
|
156
165
|
// 1 尝试用 useRef,但 useAnimatedStyle 访问后的 ref 不能在增加新的值,被冻结
|
|
@@ -163,6 +172,12 @@ export default function useAnimationHooks(props) {
|
|
|
163
172
|
return valMap;
|
|
164
173
|
}, {});
|
|
165
174
|
}, []);
|
|
175
|
+
// ** style更新同步
|
|
176
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
// style 更新后同步更新 lastStyleRef & shareValMap
|
|
179
|
+
updateStyleVal();
|
|
180
|
+
}, [style]);
|
|
166
181
|
// ** 获取动画样式prop & 驱动动画
|
|
167
182
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
168
183
|
useEffect(() => {
|
|
@@ -175,16 +190,6 @@ export default function useAnimationHooks(props) {
|
|
|
175
190
|
// 驱动动画
|
|
176
191
|
createAnimation(keys);
|
|
177
192
|
}, [id]);
|
|
178
|
-
// 同步style更新
|
|
179
|
-
// useEffect(() => {
|
|
180
|
-
// Object.keys(animatedKeys.current).forEach(key => {
|
|
181
|
-
// const originVal = getOriginalStyleVal(key, isTransform(key))
|
|
182
|
-
// if (originVal && animatedKeys.current[key] !== originVal) {
|
|
183
|
-
// animatedKeys.current[key] = originVal
|
|
184
|
-
// shareValMap[key].value = originVal
|
|
185
|
-
// }
|
|
186
|
-
// })
|
|
187
|
-
// }, [style])
|
|
188
193
|
// ** 清空动画
|
|
189
194
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
190
195
|
useEffect(() => {
|
|
@@ -194,7 +199,7 @@ export default function useAnimationHooks(props) {
|
|
|
194
199
|
});
|
|
195
200
|
};
|
|
196
201
|
}, []);
|
|
197
|
-
// 根据 animation action 创建&驱动动画
|
|
202
|
+
// 根据 animation action 创建&驱动动画
|
|
198
203
|
function createAnimation(animatedKeys = []) {
|
|
199
204
|
const actions = animation?.actions || [];
|
|
200
205
|
const sequence = {};
|
|
@@ -251,6 +256,7 @@ export default function useAnimationHooks(props) {
|
|
|
251
256
|
: withTiming(value, { duration, easing });
|
|
252
257
|
return delay ? withDelay(delay, animation) : animation;
|
|
253
258
|
}
|
|
259
|
+
// 获取样式初始值(prop style or 默认值)
|
|
254
260
|
function getInitialVal(key, isTransform = false) {
|
|
255
261
|
if (isTransform && Array.isArray(originalStyle.transform)) {
|
|
256
262
|
let initialVal = InitialValue[key];
|
|
@@ -263,31 +269,12 @@ export default function useAnimationHooks(props) {
|
|
|
263
269
|
}
|
|
264
270
|
return originalStyle[key] === undefined ? InitialValue[key] : originalStyle[key];
|
|
265
271
|
}
|
|
266
|
-
// 从 prop style 中获取样式初始值 没有为undefined
|
|
267
|
-
// function getOriginalStyleVal (key: keyof ExtendedViewStyle, isTransform = false) {
|
|
268
|
-
// if (isTransform && Array.isArray(originalStyle.transform)) {
|
|
269
|
-
// let initialVal = undefined // InitialValue[key]
|
|
270
|
-
// // 仅支持 { transform: [{rotateX: '45deg'}, {rotateZ: '0.785398rad'}] } 格式的初始样式
|
|
271
|
-
// originalStyle.transform.forEach(item => {
|
|
272
|
-
// if (item[key] !== undefined) initialVal = item[key]
|
|
273
|
-
// })
|
|
274
|
-
// return initialVal
|
|
275
|
-
// }
|
|
276
|
-
// return originalStyle[key] // === undefined ? InitialValue[key] : originalStyle[key]
|
|
277
|
-
// }
|
|
278
|
-
// 获取动画shareVal初始值(prop style or 默认值)
|
|
279
|
-
// function getInitialVal (key: keyof ExtendedViewStyle, isTransform = false) {
|
|
280
|
-
// const originalVal = getOriginalStyleVal(key, isTransform)
|
|
281
|
-
// return originalVal === undefined ? InitialValue[key] : originalStyle[key]
|
|
282
|
-
// }
|
|
283
272
|
// 循环 animation actions 获取所有有动画的 style prop name
|
|
284
273
|
function getAnimatedStyleKeys() {
|
|
285
274
|
return (animation?.actions || []).reduce((keyMap, action) => {
|
|
286
275
|
const { rules, transform } = action;
|
|
287
276
|
const ruleArr = [...rules.keys(), ...transform.keys()];
|
|
288
277
|
ruleArr.forEach(key => {
|
|
289
|
-
// const originalVal = getOriginalStyleVal(key, isTransform(key))
|
|
290
|
-
// if (!keyMap[key]) keyMap[key] = originalVal === undefined ? false : originalVal
|
|
291
278
|
if (!keyMap[key])
|
|
292
279
|
keyMap[key] = true;
|
|
293
280
|
});
|
|
@@ -295,7 +282,7 @@ export default function useAnimationHooks(props) {
|
|
|
295
282
|
}, animatedKeys.current);
|
|
296
283
|
}
|
|
297
284
|
// animated key transform 格式化
|
|
298
|
-
function formatAnimatedKeys(keys
|
|
285
|
+
function formatAnimatedKeys(keys) {
|
|
299
286
|
const animatedKeys = [];
|
|
300
287
|
const transforms = [];
|
|
301
288
|
keys.forEach(key => {
|
|
@@ -310,13 +297,24 @@ export default function useAnimationHooks(props) {
|
|
|
310
297
|
animatedKeys.push(transforms);
|
|
311
298
|
return animatedKeys;
|
|
312
299
|
}
|
|
313
|
-
//
|
|
314
|
-
function
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
300
|
+
// 设置 lastShareValRef & shareValMap
|
|
301
|
+
function updateStyleVal() {
|
|
302
|
+
Object.entries(originalStyle).forEach(([key, value]) => {
|
|
303
|
+
if (key === 'transform') {
|
|
304
|
+
Object.entries(getTransformObj(value)).forEach(([key, value]) => {
|
|
305
|
+
if (value !== lastStyleRef.current[key]) {
|
|
306
|
+
lastStyleRef.current[key] = value;
|
|
307
|
+
shareValMap[key].value = value;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else if (hasOwn(shareValMap, key)) {
|
|
312
|
+
if (value !== lastStyleRef.current[key]) {
|
|
313
|
+
lastStyleRef.current[key] = value;
|
|
314
|
+
shareValMap[key].value = value;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
});
|
|
320
318
|
}
|
|
321
319
|
// ** 生成动画样式
|
|
322
320
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -325,7 +323,7 @@ export default function useAnimationHooks(props) {
|
|
|
325
323
|
return animatedStyleKeys.value.reduce((styles, key) => {
|
|
326
324
|
// console.info('getAnimationStyles', key, shareValMap[key].value)
|
|
327
325
|
if (Array.isArray(key)) {
|
|
328
|
-
const transformStyle = getTransformObj();
|
|
326
|
+
const transformStyle = getTransformObj(originalStyle.transform || []);
|
|
329
327
|
key.forEach((transformKey) => {
|
|
330
328
|
transformStyle[transformKey] = shareValMap[transformKey].value;
|
|
331
329
|
});
|
|
@@ -239,12 +239,8 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
|
|
|
239
239
|
const normalStyleChangedRef = useRef(false);
|
|
240
240
|
let hasVarDec = false;
|
|
241
241
|
let hasVarUse = false;
|
|
242
|
-
let hasSelfPercent = false;
|
|
243
242
|
const varKeyPaths = [];
|
|
244
243
|
const unoVarKeyPaths = [];
|
|
245
|
-
const percentKeyPaths = [];
|
|
246
|
-
const calcKeyPaths = [];
|
|
247
|
-
const envKeyPaths = [];
|
|
248
244
|
const [width, setWidth] = useState(0);
|
|
249
245
|
const [height, setHeight] = useState(0);
|
|
250
246
|
const navigation = useNavigation();
|
|
@@ -304,6 +300,11 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
|
|
|
304
300
|
normalStyleChangedRef.current = !normalStyleChangedRef.current;
|
|
305
301
|
}
|
|
306
302
|
const memoResult = useMemo(() => {
|
|
303
|
+
let hasSelfPercent = false;
|
|
304
|
+
let hasPositionFixed = false;
|
|
305
|
+
const percentKeyPaths = [];
|
|
306
|
+
const calcKeyPaths = [];
|
|
307
|
+
const envKeyPaths = [];
|
|
307
308
|
// transform can be memoized
|
|
308
309
|
function envVisitor({ value, keyPath }) {
|
|
309
310
|
if (envUseRegExp.test(value)) {
|
|
@@ -324,6 +325,12 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
|
|
|
324
325
|
percentKeyPaths.push(keyPath.slice());
|
|
325
326
|
}
|
|
326
327
|
}
|
|
328
|
+
function transformPosition(styleObj) {
|
|
329
|
+
if (styleObj.position === 'fixed') {
|
|
330
|
+
hasPositionFixed = true;
|
|
331
|
+
styleObj.position = 'absolute';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
327
334
|
// traverse env & calc & percent
|
|
328
335
|
traverseStyle(normalStyle, [envVisitor, percentVisitor, calcVisitor]);
|
|
329
336
|
const percentConfig = {
|
|
@@ -355,11 +362,14 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
|
|
|
355
362
|
}
|
|
356
363
|
}
|
|
357
364
|
});
|
|
365
|
+
// apply position
|
|
366
|
+
transformPosition(normalStyle);
|
|
358
367
|
// transform number enum stringify
|
|
359
368
|
transformStringify(normalStyle);
|
|
360
369
|
return {
|
|
361
370
|
normalStyle,
|
|
362
|
-
hasSelfPercent
|
|
371
|
+
hasSelfPercent,
|
|
372
|
+
hasPositionFixed
|
|
363
373
|
};
|
|
364
374
|
}, [normalStyleChangedRef.current, width, height, parentWidth, parentHeight, parentFontSize]);
|
|
365
375
|
return extendObject({
|
|
@@ -434,8 +444,8 @@ export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout
|
|
|
434
444
|
hasLayoutRef.current = true;
|
|
435
445
|
if (hasSelfPercent) {
|
|
436
446
|
const { width, height } = e?.nativeEvent?.layout || {};
|
|
437
|
-
setWidth(width || 0);
|
|
438
|
-
setHeight(height || 0);
|
|
447
|
+
setWidth && setWidth(width || 0);
|
|
448
|
+
setHeight && setHeight(height || 0);
|
|
439
449
|
}
|
|
440
450
|
if (enableOffset) {
|
|
441
451
|
nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
|
|
@@ -324,23 +324,6 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
324
324
|
)
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
const onKeyPress = (evt: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
|
|
328
|
-
evt.nativeEvent.key === 'Enter' &&
|
|
329
|
-
bindconfirm!(
|
|
330
|
-
getCustomEvent(
|
|
331
|
-
'confirm',
|
|
332
|
-
evt,
|
|
333
|
-
{
|
|
334
|
-
detail: {
|
|
335
|
-
value: tmpValue.current || ''
|
|
336
|
-
},
|
|
337
|
-
layoutRef
|
|
338
|
-
},
|
|
339
|
-
props
|
|
340
|
-
)
|
|
341
|
-
)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
327
|
const onSubmitEditing = (evt: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => {
|
|
345
328
|
bindconfirm!(
|
|
346
329
|
getCustomEvent(
|
|
@@ -474,8 +457,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
474
457
|
onChange,
|
|
475
458
|
onSelectionChange,
|
|
476
459
|
onContentSizeChange,
|
|
477
|
-
|
|
478
|
-
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
460
|
+
onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
|
|
479
461
|
}
|
|
480
462
|
),
|
|
481
463
|
[
|
package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx}
RENAMED
|
@@ -26,8 +26,8 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
|
|
|
26
26
|
const gesture = useMemo(() => {
|
|
27
27
|
return Gesture.Tap()
|
|
28
28
|
.onEnd(() => {
|
|
29
|
-
|
|
30
|
-
})
|
|
29
|
+
dismiss()
|
|
30
|
+
}).runOnJS(true)
|
|
31
31
|
}, [])
|
|
32
32
|
|
|
33
33
|
const animatedStyle = useAnimatedStyle(() => {
|
|
@@ -117,4 +117,6 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
|
|
|
117
117
|
)
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
KeyboardAvoidingView.displayName = 'MpxKeyboardAvoidingView'
|
|
121
|
+
|
|
120
122
|
export default KeyboardAvoidingView
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useState, useCallback, forwardRef, ForwardedRef, useImperativeHandle, ReactNode, ReactElement } from 'react'
|
|
2
2
|
import { View, StyleSheet } from 'react-native'
|
|
3
|
-
import { extendObject } from '../utils'
|
|
4
3
|
|
|
5
4
|
export type State = {
|
|
6
5
|
portals: Array<{
|
|
@@ -27,7 +26,7 @@ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<u
|
|
|
27
26
|
setState((prevState) => ({
|
|
28
27
|
portals: prevState.portals.map((item) => {
|
|
29
28
|
if (item.key === key) {
|
|
30
|
-
return
|
|
29
|
+
return Object.assign({}, item, { children })
|
|
31
30
|
}
|
|
32
31
|
return item
|
|
33
32
|
})
|
|
@@ -70,6 +70,7 @@ interface ScrollViewProps {
|
|
|
70
70
|
'parent-height'?: number;
|
|
71
71
|
'wait-for'?: Array<GestureHandler>;
|
|
72
72
|
'simultaneous-handlers'?: Array<GestureHandler>;
|
|
73
|
+
'scroll-event-throttle'?:number;
|
|
73
74
|
bindscrolltoupper?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
74
75
|
bindscrolltolower?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
75
76
|
bindscroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
@@ -140,6 +141,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
140
141
|
'parent-height': parentHeight,
|
|
141
142
|
'simultaneous-handlers': originSimultaneousHandlers,
|
|
142
143
|
'wait-for': waitFor,
|
|
144
|
+
'scroll-event-throttle': scrollEventThrottle = 0,
|
|
143
145
|
__selectRef
|
|
144
146
|
} = props
|
|
145
147
|
|
|
@@ -159,7 +161,6 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
159
161
|
visibleLength: 0
|
|
160
162
|
})
|
|
161
163
|
|
|
162
|
-
const scrollEventThrottle = 50
|
|
163
164
|
const hasCallScrollToUpper = useRef(true)
|
|
164
165
|
const hasCallScrollToLower = useRef(false)
|
|
165
166
|
const initialTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
@@ -202,6 +203,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
202
203
|
|
|
203
204
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
|
|
204
205
|
|
|
206
|
+
const lastOffset = useRef(0)
|
|
207
|
+
|
|
205
208
|
if (scrollX && scrollY) {
|
|
206
209
|
warn('scroll-x and scroll-y cannot be set to true at the same time, Mpx will use the value of scroll-y as the criterion')
|
|
207
210
|
}
|
|
@@ -263,7 +266,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
263
266
|
function onStartReached (e: NativeSyntheticEvent<NativeScrollEvent>) {
|
|
264
267
|
const { bindscrolltoupper } = props
|
|
265
268
|
const { offset } = scrollOptions.current
|
|
266
|
-
|
|
269
|
+
const isScrollingBackward = offset < lastOffset.current
|
|
270
|
+
if (bindscrolltoupper && (offset <= upperThreshold) && isScrollingBackward) {
|
|
267
271
|
if (!hasCallScrollToUpper.current) {
|
|
268
272
|
bindscrolltoupper(
|
|
269
273
|
getCustomEvent('scrolltoupper', e, {
|
|
@@ -284,13 +288,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
284
288
|
const { bindscrolltolower } = props
|
|
285
289
|
const { contentLength, visibleLength, offset } = scrollOptions.current
|
|
286
290
|
const distanceFromEnd = contentLength - visibleLength - offset
|
|
287
|
-
|
|
291
|
+
const isScrollingForward = offset > lastOffset.current
|
|
292
|
+
|
|
293
|
+
if (bindscrolltolower && (distanceFromEnd < lowerThreshold) && isScrollingForward) {
|
|
288
294
|
if (!hasCallScrollToLower.current) {
|
|
289
295
|
hasCallScrollToLower.current = true
|
|
290
296
|
bindscrolltolower(
|
|
291
297
|
getCustomEvent('scrolltolower', e, {
|
|
292
298
|
detail: {
|
|
293
|
-
direction: scrollX ? 'right' : '
|
|
299
|
+
direction: scrollX ? 'right' : 'bottom'
|
|
294
300
|
},
|
|
295
301
|
layoutRef
|
|
296
302
|
}, props)
|
|
@@ -345,6 +351,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
345
351
|
onStartReached(e)
|
|
346
352
|
onEndReached(e)
|
|
347
353
|
updateIntersection()
|
|
354
|
+
// 在 onStartReached、onEndReached 执行完后更新 lastOffset
|
|
355
|
+
lastOffset.current = scrollOptions.current.offset
|
|
348
356
|
}
|
|
349
357
|
|
|
350
358
|
function onScrollEnd (e: NativeSyntheticEvent<NativeScrollEvent>) {
|
|
@@ -367,6 +375,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
367
375
|
onStartReached(e)
|
|
368
376
|
onEndReached(e)
|
|
369
377
|
updateIntersection()
|
|
378
|
+
lastOffset.current = scrollOptions.current.offset
|
|
370
379
|
}
|
|
371
380
|
function updateIntersection () {
|
|
372
381
|
if (enableTriggerIntersectionObserver && intersectionObservers) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { View, ViewProps, TextStyle } from 'react-native'
|
|
2
|
+
import { createElement, forwardRef, useRef } from 'react'
|
|
3
|
+
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
4
|
+
import { extendObject, splitProps, splitStyle, wrapChildren } from './utils'
|
|
5
|
+
|
|
6
|
+
const _View2 = forwardRef<HandlerRef<View, ViewProps>, ViewProps>((simpleViewProps: ViewProps, ref) => {
|
|
7
|
+
const nodeRef = useRef(null)
|
|
8
|
+
|
|
9
|
+
const { textProps, innerProps: props = {} } = splitProps(simpleViewProps)
|
|
10
|
+
|
|
11
|
+
const { textStyle, innerStyle = {} } = splitStyle(props.style || {})
|
|
12
|
+
|
|
13
|
+
useNodesRef(props, ref, nodeRef, {
|
|
14
|
+
style: innerStyle || {}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
return createElement(View, extendObject({}, props, {
|
|
18
|
+
style: innerStyle,
|
|
19
|
+
ref: nodeRef
|
|
20
|
+
}), wrapChildren(
|
|
21
|
+
props,
|
|
22
|
+
{
|
|
23
|
+
hasVarDec: false,
|
|
24
|
+
textStyle: textStyle as TextStyle,
|
|
25
|
+
textProps
|
|
26
|
+
}
|
|
27
|
+
))
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
_View2.displayName = 'MpxSimpleView'
|
|
31
|
+
|
|
32
|
+
export default _View2
|
|
@@ -16,6 +16,7 @@ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wra
|
|
|
16
16
|
import { error } from '@mpxjs/utils'
|
|
17
17
|
import LinearGradient from 'react-native-linear-gradient'
|
|
18
18
|
import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
|
|
19
|
+
import Portal from './mpx-portal'
|
|
19
20
|
|
|
20
21
|
export interface _ViewProps extends ViewProps {
|
|
21
22
|
style?: ExtendedViewStyle
|
|
@@ -79,7 +80,7 @@ type PreImageInfo = {
|
|
|
79
80
|
type ImageProps = {
|
|
80
81
|
style: ImageStyle,
|
|
81
82
|
src?: string,
|
|
82
|
-
source?: {uri: string },
|
|
83
|
+
source?: { uri: string },
|
|
83
84
|
colors: Array<string>,
|
|
84
85
|
locations?: Array<number>
|
|
85
86
|
angle?: number
|
|
@@ -483,8 +484,8 @@ function parseLinearGradient (text: string): LinearInfo | undefined {
|
|
|
483
484
|
}
|
|
484
485
|
|
|
485
486
|
function parseBgImage (text: string): {
|
|
486
|
-
linearInfo?: LinearInfo
|
|
487
|
-
direction?: string
|
|
487
|
+
linearInfo?: LinearInfo
|
|
488
|
+
direction?: string
|
|
488
489
|
type?: 'image' | 'linear'
|
|
489
490
|
src?: string
|
|
490
491
|
} {
|
|
@@ -578,7 +579,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
|
|
|
578
579
|
if (!src) {
|
|
579
580
|
setShow(false)
|
|
580
581
|
return
|
|
581
|
-
|
|
582
|
+
// 一开始未出现,数据改变时出现
|
|
582
583
|
} else if (!(needLayout || needImageSize)) {
|
|
583
584
|
setShow(true)
|
|
584
585
|
return
|
|
@@ -602,7 +603,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
|
|
|
602
603
|
}
|
|
603
604
|
})
|
|
604
605
|
}
|
|
605
|
-
|
|
606
|
+
// type 添加type 处理无渐变 有渐变的场景
|
|
606
607
|
}, [src, type])
|
|
607
608
|
|
|
608
609
|
if (!type) return null
|
|
@@ -636,7 +637,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
|
|
|
636
637
|
}
|
|
637
638
|
|
|
638
639
|
return <View key='backgroundImage' {...needLayout ? { onLayout } : null} style={{ ...inheritStyle(innerStyle), ...StyleSheet.absoluteFillObject, overflow: 'hidden' }}>
|
|
639
|
-
{show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} />
|
|
640
|
+
{show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} />}
|
|
640
641
|
{show && type === 'image' && (renderImage(imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size), enableFastImage))}
|
|
641
642
|
</View>
|
|
642
643
|
}
|
|
@@ -703,6 +704,7 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
703
704
|
const {
|
|
704
705
|
normalStyle,
|
|
705
706
|
hasSelfPercent,
|
|
707
|
+
hasPositionFixed,
|
|
706
708
|
hasVarDec,
|
|
707
709
|
varContextRef,
|
|
708
710
|
setWidth,
|
|
@@ -769,13 +771,18 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
|
|
|
769
771
|
enableFastImage
|
|
770
772
|
})
|
|
771
773
|
|
|
772
|
-
|
|
774
|
+
let finalComponent: JSX.Element = enableStyleAnimation
|
|
773
775
|
? createElement(Animated.View, innerProps, childNode)
|
|
774
776
|
: createElement(View, innerProps, childNode)
|
|
775
777
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
778
|
+
if (enableHover) {
|
|
779
|
+
finalComponent = createElement(GestureDetector, { gesture: gesture as PanGesture }, finalComponent)
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
if (hasPositionFixed) {
|
|
783
|
+
finalComponent = createElement(Portal, null, finalComponent)
|
|
784
|
+
}
|
|
785
|
+
return finalComponent
|
|
779
786
|
})
|
|
780
787
|
|
|
781
788
|
_View.displayName = 'MpxView'
|
|
@@ -89,7 +89,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
89
89
|
button: 'Reload'
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
const currentErrorText = errorText[(mpx.i18n
|
|
92
|
+
const currentErrorText = errorText[(mpx.i18n?.locale as LanguageCode) || 'zh-CN']
|
|
93
93
|
|
|
94
94
|
if (props.style) {
|
|
95
95
|
warn('The web-view component does not support the style prop.')
|
|
@@ -103,11 +103,11 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
103
103
|
const statusCode = useRef<string|number>('')
|
|
104
104
|
const [isLoaded, setIsLoaded] = useState<boolean>(true)
|
|
105
105
|
const defaultWebViewStyle = {
|
|
106
|
-
position: 'absolute' as
|
|
107
|
-
left: 0
|
|
108
|
-
right: 0
|
|
109
|
-
top: 0
|
|
110
|
-
bottom: 0
|
|
106
|
+
position: 'absolute' as const,
|
|
107
|
+
left: 0,
|
|
108
|
+
right: 0,
|
|
109
|
+
top: 0,
|
|
110
|
+
bottom: 0
|
|
111
111
|
}
|
|
112
112
|
const canGoBack = useRef<boolean>(false)
|
|
113
113
|
const isNavigateBack = useRef<boolean>(false)
|
|
@@ -329,7 +329,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
return (
|
|
332
|
-
<Portal
|
|
332
|
+
<Portal>
|
|
333
333
|
{pageLoadErr
|
|
334
334
|
? (
|
|
335
335
|
<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
|