@mpxjs/webpack-plugin 2.9.70 → 2.9.71
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/platform/template/wx/component-config/movable-view.js +8 -1
- package/lib/platform/template/wx/component-config/picker-view.js +1 -5
- package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
- package/lib/platform/template/wx/index.js +0 -4
- package/lib/runtime/components/react/context.ts +8 -0
- package/lib/runtime/components/react/dist/context.js +2 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +34 -31
- package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +93 -58
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +35 -0
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +151 -127
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +38 -34
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +11 -4
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +31 -8
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +670 -0
- package/lib/runtime/components/react/dist/mpx-view.jsx +15 -53
- package/lib/runtime/components/react/dist/pickerFaces.js +7 -6
- package/lib/runtime/components/react/dist/pickerVIewContext.js +14 -0
- package/lib/runtime/components/react/dist/pickerViewIndicator.jsx +23 -0
- package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
- package/lib/runtime/components/react/dist/useAnimationHooks.js +20 -2
- package/lib/runtime/components/react/dist/utils.jsx +74 -11
- package/lib/runtime/components/react/getInnerListeners.ts +43 -32
- package/lib/runtime/components/react/mpx-button.tsx +20 -57
- package/lib/runtime/components/react/mpx-movable-view.tsx +119 -74
- package/lib/runtime/components/react/mpx-navigator.tsx +1 -1
- package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
- package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
- package/lib/runtime/components/react/mpx-scroll-view.tsx +21 -10
- package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
- package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
- package/lib/runtime/components/react/mpx-view.tsx +18 -65
- package/lib/runtime/components/react/pickerFaces.ts +10 -7
- package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
- package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
- package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
- package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
- package/lib/runtime/components/react/types/global.d.ts +10 -0
- package/lib/runtime/components/react/useAnimationHooks.ts +24 -3
- package/lib/runtime/components/react/utils.tsx +85 -12
- package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
- package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
- package/lib/template-compiler/compiler.js +61 -13
- package/lib/wxss/loader.js +15 -2
- package/package.json +3 -3
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +0 -480
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +0 -68
- package/lib/runtime/components/react/dist/mpx-swiper/type.js +0 -1
- package/lib/runtime/components/react/dist/pickerOverlay.jsx +0 -21
- package/lib/runtime/components/react/dist/types/common.js +0 -1
- package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
- package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
- package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
- package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
- /package/lib/runtime/components/react/types/{common.ts → common.d.ts} +0 -0
|
@@ -10,9 +10,10 @@ import useInnerProps from './getInnerListeners';
|
|
|
10
10
|
import Animated from 'react-native-reanimated';
|
|
11
11
|
import useAnimationHooks from './useAnimationHooks';
|
|
12
12
|
import useNodesRef from './useNodesRef';
|
|
13
|
-
import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject } from './utils';
|
|
13
|
+
import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject, useHover } from './utils';
|
|
14
14
|
import { error } from '@mpxjs/utils';
|
|
15
15
|
import LinearGradient from 'react-native-linear-gradient';
|
|
16
|
+
import { GestureDetector } from 'react-native-gesture-handler';
|
|
16
17
|
const linearMap = new Map([
|
|
17
18
|
['top', 0],
|
|
18
19
|
['bottom', 180],
|
|
@@ -542,7 +543,6 @@ function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backg
|
|
|
542
543
|
const _View = forwardRef((viewProps, ref) => {
|
|
543
544
|
const { textProps, innerProps: props = {} } = splitProps(viewProps);
|
|
544
545
|
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, 'enable-fast-image': enableFastImage, 'enable-animation': enableAnimation, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, animation } = props;
|
|
545
|
-
const [isHover, setIsHover] = useState(false);
|
|
546
546
|
// 默认样式
|
|
547
547
|
const defaultStyle = style.display === 'flex'
|
|
548
548
|
? {
|
|
@@ -552,6 +552,8 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
552
552
|
flexWrap: 'nowrap'
|
|
553
553
|
}
|
|
554
554
|
: {};
|
|
555
|
+
const enableHover = !!hoverStyle;
|
|
556
|
+
const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime });
|
|
555
557
|
const styleObj = extendObject({}, defaultStyle, style, isHover ? hoverStyle : {});
|
|
556
558
|
const { normalStyle, hasSelfPercent, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
|
|
557
559
|
enableVar,
|
|
@@ -570,60 +572,17 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
570
572
|
useNodesRef(props, ref, nodeRef, {
|
|
571
573
|
style: normalStyle
|
|
572
574
|
});
|
|
573
|
-
const dataRef = useRef({});
|
|
574
|
-
useEffect(() => {
|
|
575
|
-
return () => {
|
|
576
|
-
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
577
|
-
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
578
|
-
};
|
|
579
|
-
}, []);
|
|
580
|
-
const setStartTimer = () => {
|
|
581
|
-
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
582
|
-
dataRef.current.startTimer = setTimeout(() => {
|
|
583
|
-
setIsHover(true);
|
|
584
|
-
}, +hoverStartTime);
|
|
585
|
-
};
|
|
586
|
-
const setStayTimer = () => {
|
|
587
|
-
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
588
|
-
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
589
|
-
dataRef.current.stayTimer = setTimeout(() => {
|
|
590
|
-
setIsHover(false);
|
|
591
|
-
}, +hoverStayTime);
|
|
592
|
-
};
|
|
593
|
-
function onTouchStart(e) {
|
|
594
|
-
const { bindtouchstart } = props;
|
|
595
|
-
bindtouchstart && bindtouchstart(e);
|
|
596
|
-
setStartTimer();
|
|
597
|
-
}
|
|
598
|
-
function onTouchEnd(e) {
|
|
599
|
-
const { bindtouchend } = props;
|
|
600
|
-
bindtouchend && bindtouchend(e);
|
|
601
|
-
setStayTimer();
|
|
602
|
-
}
|
|
603
575
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
604
576
|
const viewStyle = extendObject({}, innerStyle, layoutStyle);
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
}
|
|
610
|
-
const finalStyle = enableAnimationRef.current
|
|
611
|
-
? [viewStyle,
|
|
612
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
613
|
-
useAnimationHooks({
|
|
614
|
-
animation,
|
|
615
|
-
style: viewStyle
|
|
616
|
-
})]
|
|
617
|
-
: viewStyle;
|
|
577
|
+
const { enableStyleAnimation, animationStyle } = useAnimationHooks({
|
|
578
|
+
enableAnimation,
|
|
579
|
+
animation,
|
|
580
|
+
style: viewStyle
|
|
581
|
+
});
|
|
618
582
|
const innerProps = useInnerProps(props, extendObject({
|
|
619
583
|
ref: nodeRef,
|
|
620
|
-
style:
|
|
621
|
-
}, layoutProps,
|
|
622
|
-
? {
|
|
623
|
-
bindtouchstart: onTouchStart,
|
|
624
|
-
bindtouchend: onTouchEnd
|
|
625
|
-
}
|
|
626
|
-
: {}), [
|
|
584
|
+
style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
|
|
585
|
+
}, layoutProps), [
|
|
627
586
|
'hover-start-time',
|
|
628
587
|
'hover-stay-time',
|
|
629
588
|
'hover-style',
|
|
@@ -641,9 +600,12 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
641
600
|
innerStyle,
|
|
642
601
|
enableFastImage
|
|
643
602
|
});
|
|
644
|
-
|
|
603
|
+
const BaseComponent = enableStyleAnimation
|
|
645
604
|
? createElement(Animated.View, innerProps, childNode)
|
|
646
605
|
: createElement(View, innerProps, childNode);
|
|
606
|
+
return enableHover
|
|
607
|
+
? createElement(GestureDetector, { gesture: gesture }, BaseComponent)
|
|
608
|
+
: BaseComponent;
|
|
647
609
|
});
|
|
648
610
|
_View.displayName = 'MpxView';
|
|
649
611
|
export default _View;
|
|
@@ -37,15 +37,14 @@ export const createFaces = (itemHeight, visibleCount) => {
|
|
|
37
37
|
const getOpacity = (index) => {
|
|
38
38
|
const map = {
|
|
39
39
|
0: 0,
|
|
40
|
-
1: 0.
|
|
41
|
-
2: 0.
|
|
42
|
-
3: 0.45,
|
|
43
|
-
4: 0.5
|
|
40
|
+
1: 0.8,
|
|
41
|
+
2: 0.9
|
|
44
42
|
};
|
|
45
|
-
return map[index] ?? Math.min(1, map[
|
|
43
|
+
return map[index] ?? Math.min(1, map[2] + index * 0.05);
|
|
46
44
|
};
|
|
47
45
|
const degrees = getDegreesRelativeCenter();
|
|
48
46
|
const [screenHeight, offsets] = getScreenHeightsAndOffsets(degrees);
|
|
47
|
+
const scales = [0.973, 0.9, 0.8];
|
|
49
48
|
return [
|
|
50
49
|
// top items
|
|
51
50
|
...degrees
|
|
@@ -55,12 +54,13 @@ export const createFaces = (itemHeight, visibleCount) => {
|
|
|
55
54
|
deg: degree,
|
|
56
55
|
opacity: getOpacity(degrees.length - 1 - index),
|
|
57
56
|
offsetY: -1 * offsets[index],
|
|
57
|
+
scale: scales[index],
|
|
58
58
|
screenHeight: screenHeight[index]
|
|
59
59
|
};
|
|
60
60
|
})
|
|
61
61
|
.reverse(),
|
|
62
62
|
// center item
|
|
63
|
-
{ index: 0, deg: 0, opacity: 1, offsetY: 0, screenHeight: itemHeight },
|
|
63
|
+
{ index: 0, deg: 0, opacity: 1, offsetY: 0, scale: 1, screenHeight: itemHeight },
|
|
64
64
|
// bottom items
|
|
65
65
|
...degrees.map((degree, index) => {
|
|
66
66
|
return {
|
|
@@ -68,6 +68,7 @@ export const createFaces = (itemHeight, visibleCount) => {
|
|
|
68
68
|
deg: -1 * degree,
|
|
69
69
|
opacity: getOpacity(degrees.length - 1 - index),
|
|
70
70
|
offsetY: offsets[index],
|
|
71
|
+
scale: scales[index],
|
|
71
72
|
screenHeight: screenHeight[index]
|
|
72
73
|
};
|
|
73
74
|
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
export const PickerViewColumnAnimationContext = createContext(undefined);
|
|
3
|
+
export const usePickerViewColumnAnimationContext = () => {
|
|
4
|
+
const value = useContext(PickerViewColumnAnimationContext);
|
|
5
|
+
if (value === undefined) {
|
|
6
|
+
throw new Error('usePickerViewColumnAnimationContext must be called from within PickerViewColumnAnimationContext.Provider!');
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
};
|
|
10
|
+
export const PickerViewStyleContext = createContext(undefined);
|
|
11
|
+
export const usePickerViewStyleContext = () => {
|
|
12
|
+
const value = useContext(PickerViewStyleContext);
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
const _PickerViewIndicator = ({ itemHeight, indicatorItemStyle, indicatorContainerStyle }) => {
|
|
4
|
+
return (<View style={[styles.indicatorContainer, indicatorContainerStyle]} pointerEvents={'none'}>
|
|
5
|
+
<View style={[styles.selection, { height: itemHeight }, indicatorItemStyle]}/>
|
|
6
|
+
</View>);
|
|
7
|
+
};
|
|
8
|
+
const styles = StyleSheet.create({
|
|
9
|
+
indicatorContainer: {
|
|
10
|
+
...StyleSheet.absoluteFillObject,
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
zIndex: 200
|
|
14
|
+
},
|
|
15
|
+
selection: {
|
|
16
|
+
borderTopWidth: 1,
|
|
17
|
+
borderBottomWidth: 1,
|
|
18
|
+
borderColor: 'rgba(0, 0, 0, 0.05)',
|
|
19
|
+
alignSelf: 'stretch'
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
_PickerViewIndicator.displayName = 'MpxPickerViewIndicator';
|
|
23
|
+
export default _PickerViewIndicator;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
import LinearGradient from 'react-native-linear-gradient';
|
|
4
|
+
const _PickerViewMask = ({ itemHeight, maskContainerStyle }) => {
|
|
5
|
+
return (<View style={[styles.maskContainer, maskContainerStyle]} pointerEvents={'none'}>
|
|
6
|
+
<LinearGradient colors={['rgba(255,255,255,1)', 'rgba(255,255,255,0.5)']} style={{ flex: 1 }}/>
|
|
7
|
+
<View style={{ height: itemHeight }}/>
|
|
8
|
+
<LinearGradient colors={['rgba(255,255,255,0.5)', 'rgba(255,255,255,1)']} style={{ flex: 1 }}/>
|
|
9
|
+
</View>);
|
|
10
|
+
};
|
|
11
|
+
const styles = StyleSheet.create({
|
|
12
|
+
maskContainer: {
|
|
13
|
+
...StyleSheet.absoluteFillObject,
|
|
14
|
+
zIndex: 100
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
_PickerViewMask.displayName = 'MpxPickerViewMask';
|
|
18
|
+
export default _PickerViewMask;
|
|
@@ -1,5 +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
4
|
// 微信 timingFunction 和 RN Easing 对应关系
|
|
4
5
|
const EasingKey = {
|
|
5
6
|
linear: Easing.linear,
|
|
@@ -132,19 +133,29 @@ const formatStyle = (style) => {
|
|
|
132
133
|
});
|
|
133
134
|
};
|
|
134
135
|
export default function useAnimationHooks(props) {
|
|
135
|
-
const { style = {}, animation } = props;
|
|
136
|
+
const { style = {}, animation, enableAnimation } = props;
|
|
137
|
+
const enableStyleAnimation = enableAnimation || !!animation;
|
|
138
|
+
const enableAnimationRef = useRef(enableStyleAnimation);
|
|
139
|
+
if (enableAnimationRef.current !== enableStyleAnimation) {
|
|
140
|
+
error('[Mpx runtime error]: animation use should be stable in the component lifecycle, or you can set [enable-animation] with true.');
|
|
141
|
+
}
|
|
142
|
+
if (!enableAnimationRef.current)
|
|
143
|
+
return { enableStyleAnimation: false };
|
|
136
144
|
const originalStyle = formatStyle(style);
|
|
137
145
|
// id 标识
|
|
138
146
|
const id = animation?.id || -1;
|
|
139
147
|
// 有动画样式的 style key
|
|
148
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
140
149
|
const animatedStyleKeys = useSharedValue([]);
|
|
141
150
|
// 记录动画key的style样式值 没有的话设置为false
|
|
151
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
142
152
|
const animatedKeys = useRef({});
|
|
143
153
|
// const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean|number|string})
|
|
144
154
|
// ** 全量 style prop sharedValue
|
|
145
155
|
// 不能做增量的原因:
|
|
146
156
|
// 1 尝试用 useRef,但 useAnimatedStyle 访问后的 ref 不能在增加新的值,被冻结
|
|
147
157
|
// 2 尝试用 useSharedValue,因为实际触发的 style prop 需要是 sharedValue 才能驱动动画,若外层 shareValMap 也是 sharedValue,动画无法驱动。
|
|
158
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
148
159
|
const shareValMap = useMemo(() => {
|
|
149
160
|
return Object.keys(InitialValue).reduce((valMap, key) => {
|
|
150
161
|
const defaultVal = getInitialVal(key, isTransform(key));
|
|
@@ -153,6 +164,7 @@ export default function useAnimationHooks(props) {
|
|
|
153
164
|
}, {});
|
|
154
165
|
}, []);
|
|
155
166
|
// ** 获取动画样式prop & 驱动动画
|
|
167
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
156
168
|
useEffect(() => {
|
|
157
169
|
if (id === -1)
|
|
158
170
|
return;
|
|
@@ -174,6 +186,7 @@ export default function useAnimationHooks(props) {
|
|
|
174
186
|
// })
|
|
175
187
|
// }, [style])
|
|
176
188
|
// ** 清空动画
|
|
189
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
177
190
|
useEffect(() => {
|
|
178
191
|
return () => {
|
|
179
192
|
Object.values(shareValMap).forEach((value) => {
|
|
@@ -306,7 +319,8 @@ export default function useAnimationHooks(props) {
|
|
|
306
319
|
}, {});
|
|
307
320
|
}
|
|
308
321
|
// ** 生成动画样式
|
|
309
|
-
|
|
322
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
323
|
+
const animationStyle = useAnimatedStyle(() => {
|
|
310
324
|
// console.info(`useAnimatedStyle styles=`, originalStyle)
|
|
311
325
|
return animatedStyleKeys.value.reduce((styles, key) => {
|
|
312
326
|
// console.info('getAnimationStyles', key, shareValMap[key].value)
|
|
@@ -325,4 +339,8 @@ export default function useAnimationHooks(props) {
|
|
|
325
339
|
return styles;
|
|
326
340
|
}, {});
|
|
327
341
|
});
|
|
342
|
+
return {
|
|
343
|
+
enableStyleAnimation: enableAnimationRef.current,
|
|
344
|
+
animationStyle
|
|
345
|
+
};
|
|
328
346
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { useEffect, useCallback, useMemo, useRef, isValidElement, useContext, useState, Children, cloneElement } from 'react';
|
|
2
2
|
import { Image } from 'react-native';
|
|
3
|
-
import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn
|
|
4
|
-
import { VarContext } from './context';
|
|
3
|
+
import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn } from '@mpxjs/utils';
|
|
4
|
+
import { VarContext, ScrollViewContext } from './context';
|
|
5
5
|
import { ExpressionParser, parseFunc, ReplaceSource } from './parser';
|
|
6
6
|
import { initialWindowMetrics } from 'react-native-safe-area-context';
|
|
7
|
+
import { useNavigation } from '@react-navigation/native';
|
|
7
8
|
import FastImage from '@d11/react-native-fast-image';
|
|
9
|
+
import { runOnJS } from 'react-native-reanimated';
|
|
10
|
+
import { Gesture } from 'react-native-gesture-handler';
|
|
8
11
|
export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/;
|
|
9
12
|
export const PERCENT_REGEX = /^\s*-?\d+(\.\d+)?%\s*$/;
|
|
10
13
|
export const URL_REGEX = /^\s*url\(["']?(.*?)["']?\)\s*$/;
|
|
@@ -15,6 +18,8 @@ export const DEFAULT_FONT_SIZE = 16;
|
|
|
15
18
|
export const HIDDEN_STYLE = {
|
|
16
19
|
opacity: 0
|
|
17
20
|
};
|
|
21
|
+
export const isIOS = __mpx_mode__ === 'ios';
|
|
22
|
+
export const isAndroid = __mpx_mode__ === 'android';
|
|
18
23
|
const varDecRegExp = /^--/;
|
|
19
24
|
const varUseRegExp = /var\(/;
|
|
20
25
|
const unoVarDecRegExp = /^--un-/;
|
|
@@ -27,8 +32,7 @@ const safeAreaInsetMap = {
|
|
|
27
32
|
'safe-area-inset-bottom': 'bottom',
|
|
28
33
|
'safe-area-inset-left': 'left'
|
|
29
34
|
};
|
|
30
|
-
function getSafeAreaInset(name) {
|
|
31
|
-
const navigation = getFocusedNavigation();
|
|
35
|
+
function getSafeAreaInset(name, navigation) {
|
|
32
36
|
const insets = extendObject({}, initialWindowMetrics?.insets, navigation?.insets);
|
|
33
37
|
return insets[safeAreaInsetMap[name]];
|
|
34
38
|
}
|
|
@@ -194,7 +198,7 @@ function transformVar(styleObj, varKeyPaths, varContext) {
|
|
|
194
198
|
});
|
|
195
199
|
});
|
|
196
200
|
}
|
|
197
|
-
function transformEnv(styleObj, envKeyPaths) {
|
|
201
|
+
function transformEnv(styleObj, envKeyPaths, navigation) {
|
|
198
202
|
envKeyPaths.forEach((envKeyPath) => {
|
|
199
203
|
setStyle(styleObj, envKeyPath, ({ target, key, value }) => {
|
|
200
204
|
const parsed = parseFunc(value, 'env');
|
|
@@ -202,7 +206,7 @@ function transformEnv(styleObj, envKeyPaths) {
|
|
|
202
206
|
parsed.forEach(({ start, end, args }) => {
|
|
203
207
|
const name = args[0];
|
|
204
208
|
const fallback = args[1] || '';
|
|
205
|
-
const value = '' + (getSafeAreaInset(name) ?? global.__formatValue(fallback));
|
|
209
|
+
const value = '' + (getSafeAreaInset(name, navigation) ?? global.__formatValue(fallback));
|
|
206
210
|
replaced.replace(start, end - 1, value);
|
|
207
211
|
});
|
|
208
212
|
target[key] = global.__formatValue(replaced.source());
|
|
@@ -254,6 +258,7 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
|
|
|
254
258
|
const envKeyPaths = [];
|
|
255
259
|
const [width, setWidth] = useState(0);
|
|
256
260
|
const [height, setHeight] = useState(0);
|
|
261
|
+
const navigation = useNavigation();
|
|
257
262
|
function varVisitor({ key, value, keyPath }) {
|
|
258
263
|
if (keyPath.length === 1) {
|
|
259
264
|
if (unoVarDecRegExp.test(key)) {
|
|
@@ -341,7 +346,7 @@ export function useTransformStyle(styleObj = {}, { enableVar, externalVarContext
|
|
|
341
346
|
parentFontSize
|
|
342
347
|
};
|
|
343
348
|
// apply env
|
|
344
|
-
transformEnv(normalStyle, envKeyPaths);
|
|
349
|
+
transformEnv(normalStyle, envKeyPaths, navigation);
|
|
345
350
|
// apply percent
|
|
346
351
|
transformPercent(normalStyle, percentKeyPaths, percentConfig);
|
|
347
352
|
// apply calc
|
|
@@ -476,13 +481,14 @@ export function wrapChildren(props = {}, { hasVarDec, varContext, textStyle, tex
|
|
|
476
481
|
export const debounce = (func, delay) => {
|
|
477
482
|
let timer;
|
|
478
483
|
const wrapper = (...args) => {
|
|
479
|
-
clearTimeout(timer);
|
|
484
|
+
timer && clearTimeout(timer);
|
|
480
485
|
timer = setTimeout(() => {
|
|
481
486
|
func(...args);
|
|
482
487
|
}, delay);
|
|
483
488
|
};
|
|
484
489
|
wrapper.clear = () => {
|
|
485
|
-
clearTimeout(timer);
|
|
490
|
+
timer && clearTimeout(timer);
|
|
491
|
+
timer = null;
|
|
486
492
|
};
|
|
487
493
|
return wrapper;
|
|
488
494
|
};
|
|
@@ -495,12 +501,12 @@ export const useStableCallback = (callback) => {
|
|
|
495
501
|
ref.current = callback;
|
|
496
502
|
return useCallback((...args) => ref.current?.(...args), []);
|
|
497
503
|
};
|
|
498
|
-
export
|
|
504
|
+
export function usePrevious(value) {
|
|
499
505
|
const ref = useRef();
|
|
500
506
|
const prev = ref.current;
|
|
501
507
|
ref.current = value;
|
|
502
508
|
return prev;
|
|
503
|
-
}
|
|
509
|
+
}
|
|
504
510
|
export function flatGesture(gestures = []) {
|
|
505
511
|
return (gestures && gestures.flatMap((gesture) => {
|
|
506
512
|
if (gesture && gesture.nodeRefs) {
|
|
@@ -529,3 +535,60 @@ export function pickStyle(styleObj = {}, pickedKeys, callback) {
|
|
|
529
535
|
return acc;
|
|
530
536
|
}, {});
|
|
531
537
|
}
|
|
538
|
+
export function useHover({ enableHover, hoverStartTime, hoverStayTime, disabled }) {
|
|
539
|
+
const enableHoverRef = useRef(enableHover);
|
|
540
|
+
if (enableHoverRef.current !== enableHover) {
|
|
541
|
+
error('[Mpx runtime error]: hover-class use should be stable in the component lifecycle.');
|
|
542
|
+
}
|
|
543
|
+
if (!enableHoverRef.current)
|
|
544
|
+
return { isHover: false };
|
|
545
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
546
|
+
const gestureRef = useContext(ScrollViewContext).gestureRef;
|
|
547
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
548
|
+
const [isHover, setIsHover] = useState(false);
|
|
549
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
550
|
+
const dataRef = useRef({});
|
|
551
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
552
|
+
useEffect(() => {
|
|
553
|
+
return () => {
|
|
554
|
+
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
555
|
+
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
556
|
+
};
|
|
557
|
+
}, []);
|
|
558
|
+
const setStartTimer = () => {
|
|
559
|
+
if (disabled)
|
|
560
|
+
return;
|
|
561
|
+
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
562
|
+
dataRef.current.startTimer = setTimeout(() => {
|
|
563
|
+
setIsHover(true);
|
|
564
|
+
}, +hoverStartTime);
|
|
565
|
+
};
|
|
566
|
+
const setStayTimer = () => {
|
|
567
|
+
if (disabled)
|
|
568
|
+
return;
|
|
569
|
+
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
570
|
+
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
571
|
+
dataRef.current.stayTimer = setTimeout(() => {
|
|
572
|
+
setIsHover(false);
|
|
573
|
+
}, +hoverStayTime);
|
|
574
|
+
};
|
|
575
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
576
|
+
const gesture = useMemo(() => {
|
|
577
|
+
return Gesture.Pan()
|
|
578
|
+
.onTouchesDown(() => {
|
|
579
|
+
'worklet';
|
|
580
|
+
runOnJS(setStartTimer)();
|
|
581
|
+
})
|
|
582
|
+
.onTouchesUp(() => {
|
|
583
|
+
'worklet';
|
|
584
|
+
runOnJS(setStayTimer)();
|
|
585
|
+
});
|
|
586
|
+
}, []);
|
|
587
|
+
if (gestureRef) {
|
|
588
|
+
gesture.simultaneousWithExternalGesture(gestureRef);
|
|
589
|
+
}
|
|
590
|
+
return {
|
|
591
|
+
isHover,
|
|
592
|
+
gesture
|
|
593
|
+
};
|
|
594
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useRef, useMemo, RefObject } from 'react'
|
|
2
2
|
import { hasOwn, collectDataset } from '@mpxjs/utils'
|
|
3
|
+
import { useNavigation } from '@react-navigation/native'
|
|
3
4
|
import { omit, extendObject } from './utils'
|
|
4
5
|
import eventConfigMap from './event.config'
|
|
5
6
|
import {
|
|
@@ -10,15 +11,22 @@ import {
|
|
|
10
11
|
InnerRef,
|
|
11
12
|
SetTimeoutReturnType,
|
|
12
13
|
LayoutRef,
|
|
13
|
-
NativeTouchEvent
|
|
14
|
+
NativeTouchEvent,
|
|
15
|
+
Navigation
|
|
14
16
|
} from './types/getInnerListeners'
|
|
15
17
|
|
|
18
|
+
const globalEventState = {
|
|
19
|
+
needPress: true
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
const getTouchEvent = (
|
|
17
23
|
type: string,
|
|
18
24
|
event: NativeTouchEvent,
|
|
19
25
|
props: Props,
|
|
20
|
-
config: UseInnerPropsConfig
|
|
26
|
+
config: UseInnerPropsConfig,
|
|
27
|
+
navigation: Navigation
|
|
21
28
|
) => {
|
|
29
|
+
const { y: navigationY = 0 } = navigation?.layout || {}
|
|
22
30
|
const nativeEvent = event.nativeEvent
|
|
23
31
|
const { timestamp, pageX, pageY, touches, changedTouches } = nativeEvent
|
|
24
32
|
const { id } = props
|
|
@@ -49,24 +57,24 @@ const getTouchEvent = (
|
|
|
49
57
|
target,
|
|
50
58
|
detail: {
|
|
51
59
|
x: pageX,
|
|
52
|
-
y: pageY
|
|
60
|
+
y: pageY - navigationY
|
|
53
61
|
},
|
|
54
62
|
touches: touches.map((item) => {
|
|
55
63
|
return {
|
|
56
64
|
identifier: item.identifier,
|
|
57
65
|
pageX: item.pageX,
|
|
58
|
-
pageY: item.pageY,
|
|
59
|
-
clientX: item.
|
|
60
|
-
clientY: item.
|
|
66
|
+
pageY: item.pageY - navigationY,
|
|
67
|
+
clientX: item.pageX,
|
|
68
|
+
clientY: item.pageY - navigationY
|
|
61
69
|
}
|
|
62
70
|
}),
|
|
63
71
|
changedTouches: changedTouches.map((item) => {
|
|
64
72
|
return {
|
|
65
73
|
identifier: item.identifier,
|
|
66
74
|
pageX: item.pageX,
|
|
67
|
-
pageY: item.pageY,
|
|
68
|
-
clientX: item.
|
|
69
|
-
clientY: item.
|
|
75
|
+
pageY: item.pageY - navigationY,
|
|
76
|
+
clientX: item.pageX,
|
|
77
|
+
clientY: item.pageY - navigationY
|
|
70
78
|
}
|
|
71
79
|
}),
|
|
72
80
|
persist: event.persist,
|
|
@@ -105,7 +113,8 @@ function handleEmitEvent (
|
|
|
105
113
|
type: string,
|
|
106
114
|
oe: NativeTouchEvent,
|
|
107
115
|
propsRef: Record<string, any>,
|
|
108
|
-
config: UseInnerPropsConfig
|
|
116
|
+
config: UseInnerPropsConfig,
|
|
117
|
+
navigation: Navigation
|
|
109
118
|
) {
|
|
110
119
|
events.forEach((event) => {
|
|
111
120
|
if (propsRef.current[event]) {
|
|
@@ -114,7 +123,7 @@ function handleEmitEvent (
|
|
|
114
123
|
oe.stopPropagation()
|
|
115
124
|
}
|
|
116
125
|
propsRef.current[event](
|
|
117
|
-
getTouchEvent(type, oe, propsRef.current, config)
|
|
126
|
+
getTouchEvent(type, oe, propsRef.current, config, navigation)
|
|
118
127
|
)
|
|
119
128
|
}
|
|
120
129
|
})
|
|
@@ -129,14 +138,14 @@ function checkIsNeedPress (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
129
138
|
Math.abs(currentPageX - tapDetailInfo.x) > 3 ||
|
|
130
139
|
Math.abs(currentPageY - tapDetailInfo.y) > 3
|
|
131
140
|
) {
|
|
132
|
-
|
|
141
|
+
globalEventState.needPress = false
|
|
133
142
|
ref.current!.startTimer[type] &&
|
|
134
143
|
clearTimeout(ref.current!.startTimer[type] as SetTimeoutReturnType)
|
|
135
144
|
ref.current!.startTimer[type] = null
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
|
|
139
|
-
function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig) {
|
|
148
|
+
function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) {
|
|
140
149
|
e.persist()
|
|
141
150
|
const bubbleTouchEvent = ['catchtouchstart', 'bindtouchstart']
|
|
142
151
|
const bubblePressEvent = ['catchlongpress', 'bindlongpress']
|
|
@@ -149,7 +158,7 @@ function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
149
158
|
'capture-bindlongpress'
|
|
150
159
|
]
|
|
151
160
|
ref.current!.startTimer[type] = null
|
|
152
|
-
|
|
161
|
+
globalEventState.needPress = true
|
|
153
162
|
const nativeEvent = e.nativeEvent
|
|
154
163
|
ref.current!.mpxPressInfo.detail = {
|
|
155
164
|
x: nativeEvent.changedTouches[0].pageX,
|
|
@@ -159,7 +168,7 @@ function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
159
168
|
type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
160
169
|
const currentPressEvent =
|
|
161
170
|
type === 'bubble' ? bubblePressEvent : capturePressEvent
|
|
162
|
-
handleEmitEvent(currentTouchEvent, 'touchstart', e, propsRef, config)
|
|
171
|
+
handleEmitEvent(currentTouchEvent, 'touchstart', e, propsRef, config, navigation)
|
|
163
172
|
const {
|
|
164
173
|
catchlongpress,
|
|
165
174
|
bindlongpress,
|
|
@@ -173,13 +182,14 @@ function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
173
182
|
captureBindlongpress
|
|
174
183
|
) {
|
|
175
184
|
ref.current!.startTimer[type] = setTimeout(() => {
|
|
176
|
-
|
|
177
|
-
|
|
185
|
+
// 只要触发过longpress, 全局就不再触发tap
|
|
186
|
+
globalEventState.needPress = false
|
|
187
|
+
handleEmitEvent(currentPressEvent, 'longpress', e, propsRef, config, navigation)
|
|
178
188
|
}, 350)
|
|
179
189
|
}
|
|
180
190
|
}
|
|
181
191
|
|
|
182
|
-
function handleTouchmove (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig) {
|
|
192
|
+
function handleTouchmove (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) {
|
|
183
193
|
const bubbleTouchEvent = ['catchtouchmove', 'bindtouchmove']
|
|
184
194
|
const captureTouchEvent = [
|
|
185
195
|
'capture-catchtouchmove',
|
|
@@ -187,11 +197,11 @@ function handleTouchmove (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
187
197
|
]
|
|
188
198
|
const currentTouchEvent =
|
|
189
199
|
type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
190
|
-
handleEmitEvent(currentTouchEvent, 'touchmove', e, propsRef, config)
|
|
200
|
+
handleEmitEvent(currentTouchEvent, 'touchmove', e, propsRef, config, navigation)
|
|
191
201
|
checkIsNeedPress(e, type, ref)
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
function handleTouchend (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig) {
|
|
204
|
+
function handleTouchend (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) {
|
|
195
205
|
// move event may not be triggered
|
|
196
206
|
checkIsNeedPress(e, type, ref)
|
|
197
207
|
const bubbleTouchEvent = ['catchtouchend', 'bindtouchend']
|
|
@@ -208,19 +218,22 @@ function handleTouchend (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: R
|
|
|
208
218
|
ref.current!.startTimer[type] &&
|
|
209
219
|
clearTimeout(ref.current!.startTimer[type] as SetTimeoutReturnType)
|
|
210
220
|
ref.current!.startTimer[type] = null
|
|
211
|
-
handleEmitEvent(currentTouchEvent, 'touchend', e, propsRef, config)
|
|
212
|
-
if (
|
|
221
|
+
handleEmitEvent(currentTouchEvent, 'touchend', e, propsRef, config, navigation)
|
|
222
|
+
if (globalEventState.needPress) {
|
|
213
223
|
if (type === 'bubble' && config.disableTap) {
|
|
214
224
|
return
|
|
215
225
|
}
|
|
216
|
-
handleEmitEvent(currentTapEvent, 'tap', e, propsRef, config)
|
|
226
|
+
handleEmitEvent(currentTapEvent, 'tap', e, propsRef, config, navigation)
|
|
217
227
|
}
|
|
218
228
|
}
|
|
219
229
|
|
|
220
230
|
function handleTouchcancel (
|
|
221
231
|
e: NativeTouchEvent,
|
|
222
232
|
type: 'bubble' | 'capture',
|
|
223
|
-
ref: RefObject<InnerRef>,
|
|
233
|
+
ref: RefObject<InnerRef>,
|
|
234
|
+
propsRef: Record<string, any>,
|
|
235
|
+
config: UseInnerPropsConfig,
|
|
236
|
+
navigation: Navigation
|
|
224
237
|
) {
|
|
225
238
|
const bubbleTouchEvent = ['catchtouchcancel', 'bindtouchcancel']
|
|
226
239
|
const captureTouchEvent = [
|
|
@@ -232,11 +245,11 @@ function handleTouchcancel (
|
|
|
232
245
|
ref.current!.startTimer[type] &&
|
|
233
246
|
clearTimeout(ref.current!.startTimer[type] as SetTimeoutReturnType)
|
|
234
247
|
ref.current!.startTimer[type] = null
|
|
235
|
-
handleEmitEvent(currentTouchEvent, 'touchcancel', e, propsRef, config)
|
|
248
|
+
handleEmitEvent(currentTouchEvent, 'touchcancel', e, propsRef, config, navigation)
|
|
236
249
|
}
|
|
237
250
|
|
|
238
251
|
function createTouchEventHandler (eventName: 'onTouchStart'|'onTouchMove'|'onTouchEnd'|'onTouchCancel', type: 'bubble' | 'capture') {
|
|
239
|
-
return (e: NativeTouchEvent, ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig) => {
|
|
252
|
+
return (e: NativeTouchEvent, ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) => {
|
|
240
253
|
const handlerMap = {
|
|
241
254
|
onTouchStart: handleTouchstart,
|
|
242
255
|
onTouchMove: handleTouchmove,
|
|
@@ -246,7 +259,7 @@ function createTouchEventHandler (eventName: 'onTouchStart'|'onTouchMove'|'onTou
|
|
|
246
259
|
|
|
247
260
|
const handler = handlerMap[eventName]
|
|
248
261
|
if (handler) {
|
|
249
|
-
handler(e, type, ref, propsRef, config)
|
|
262
|
+
handler(e, type, ref, propsRef, config, navigation)
|
|
250
263
|
}
|
|
251
264
|
}
|
|
252
265
|
}
|
|
@@ -273,10 +286,6 @@ const useInnerProps = (
|
|
|
273
286
|
bubble: null,
|
|
274
287
|
capture: null
|
|
275
288
|
},
|
|
276
|
-
needPress: {
|
|
277
|
-
bubble: false,
|
|
278
|
-
capture: false
|
|
279
|
-
},
|
|
280
289
|
mpxPressInfo: {
|
|
281
290
|
detail: {
|
|
282
291
|
x: 0,
|
|
@@ -291,6 +300,8 @@ const useInnerProps = (
|
|
|
291
300
|
layoutRef: { current: {} },
|
|
292
301
|
disableTap: false
|
|
293
302
|
}
|
|
303
|
+
const navigation = useNavigation()
|
|
304
|
+
|
|
294
305
|
const removeProps = [
|
|
295
306
|
'children',
|
|
296
307
|
'enable-background',
|
|
@@ -332,7 +343,7 @@ const useInnerProps = (
|
|
|
332
343
|
touchEventList.forEach((item) => {
|
|
333
344
|
if (finalEventKeys.includes(item.eventName)) {
|
|
334
345
|
events[item.eventName] = (e: NativeTouchEvent) =>
|
|
335
|
-
item.handler(e, ref, propsRef, config)
|
|
346
|
+
item.handler(e, ref, propsRef, config, navigation)
|
|
336
347
|
}
|
|
337
348
|
})
|
|
338
349
|
|