@mpxjs/webpack-plugin 2.9.69-beta.5 → 2.9.69-beta.7
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 +3 -1
- package/lib/platform/template/wx/index.js +3 -1
- package/lib/runtime/components/react/dist/mpx-button.jsx +11 -11
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +16 -2
- package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +10 -41
- package/lib/runtime/components/react/dist/mpx-portal.jsx +1 -0
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +13 -7
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +407 -327
- package/lib/runtime/components/react/dist/mpx-view.jsx +15 -13
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +66 -63
- package/lib/runtime/components/react/dist/pickerFaces.js +1 -6
- package/lib/runtime/components/react/dist/useAnimationHooks.js +15 -10
- package/lib/runtime/components/react/dist/utils.jsx +57 -0
- package/lib/runtime/components/react/mpx-swiper.tsx +56 -36
- package/lib/runtime/components/react/mpx-web-view.tsx +61 -44
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@ 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,
|
|
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
16
|
import { GestureDetector } from 'react-native-gesture-handler';
|
|
@@ -442,7 +442,7 @@ function inheritStyle(innerStyle = {}) {
|
|
|
442
442
|
}
|
|
443
443
|
: undefined);
|
|
444
444
|
}
|
|
445
|
-
function
|
|
445
|
+
function useWrapImage(imageStyle, innerStyle, enableFastImage) {
|
|
446
446
|
// 预处理数据
|
|
447
447
|
const preImageInfo = preParseImage(imageStyle);
|
|
448
448
|
// 预解析
|
|
@@ -528,11 +528,6 @@ function wrapImage(imageStyle, innerStyle, enableFastImage) {
|
|
|
528
528
|
</View>;
|
|
529
529
|
}
|
|
530
530
|
function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backgroundStyle, varContext, textProps, innerStyle, enableFastImage }) {
|
|
531
|
-
enableBackground = enableBackground || !!backgroundStyle;
|
|
532
|
-
const enableBackgroundRef = useRef(enableBackground);
|
|
533
|
-
if (enableBackgroundRef.current !== enableBackground) {
|
|
534
|
-
error('[Mpx runtime error]: background use should be stable in the component lifecycle, or you can set [enable-background] with true.');
|
|
535
|
-
}
|
|
536
531
|
const children = wrapChildren(props, {
|
|
537
532
|
hasVarDec,
|
|
538
533
|
varContext,
|
|
@@ -540,13 +535,14 @@ function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backg
|
|
|
540
535
|
textProps
|
|
541
536
|
});
|
|
542
537
|
return [
|
|
543
|
-
|
|
538
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
539
|
+
enableBackground ? useWrapImage(backgroundStyle, innerStyle, enableFastImage) : null,
|
|
544
540
|
children
|
|
545
541
|
];
|
|
546
542
|
}
|
|
547
543
|
const _View = forwardRef((viewProps, ref) => {
|
|
548
544
|
const { textProps, innerProps: props = {} } = splitProps(viewProps);
|
|
549
|
-
|
|
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;
|
|
550
546
|
// 默认样式
|
|
551
547
|
const defaultStyle = style.display === 'flex'
|
|
552
548
|
? {
|
|
@@ -556,7 +552,8 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
556
552
|
flexWrap: 'nowrap'
|
|
557
553
|
}
|
|
558
554
|
: {};
|
|
559
|
-
const
|
|
555
|
+
const enableHover = !!hoverStyle;
|
|
556
|
+
const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime });
|
|
560
557
|
const styleObj = extendObject({}, defaultStyle, style, isHover ? hoverStyle : {});
|
|
561
558
|
const { normalStyle, hasSelfPercent, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
|
|
562
559
|
enableVar,
|
|
@@ -566,6 +563,11 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
566
563
|
parentHeight
|
|
567
564
|
});
|
|
568
565
|
const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle);
|
|
566
|
+
enableBackground = enableBackground || !!backgroundStyle;
|
|
567
|
+
const enableBackgroundRef = useRef(enableBackground);
|
|
568
|
+
if (enableBackgroundRef.current !== enableBackground) {
|
|
569
|
+
error('[Mpx runtime error]: background use should be stable in the component lifecycle, or you can set [enable-background] with true.');
|
|
570
|
+
}
|
|
569
571
|
const nodeRef = useRef(null);
|
|
570
572
|
useNodesRef(props, ref, nodeRef, {
|
|
571
573
|
style: normalStyle
|
|
@@ -590,7 +592,7 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
590
592
|
});
|
|
591
593
|
const childNode = wrapWithChildren(props, {
|
|
592
594
|
hasVarDec,
|
|
593
|
-
enableBackground,
|
|
595
|
+
enableBackground: enableBackgroundRef.current,
|
|
594
596
|
textStyle,
|
|
595
597
|
backgroundStyle,
|
|
596
598
|
varContext: varContextRef.current,
|
|
@@ -601,8 +603,8 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
601
603
|
const BaseComponent = enableStyleAnimation
|
|
602
604
|
? createElement(Animated.View, innerProps, childNode)
|
|
603
605
|
: createElement(View, innerProps, childNode);
|
|
604
|
-
return
|
|
605
|
-
? createElement(GestureDetector, { gesture }, BaseComponent)
|
|
606
|
+
return enableHover
|
|
607
|
+
? createElement(GestureDetector, { gesture: gesture }, BaseComponent)
|
|
606
608
|
: BaseComponent;
|
|
607
609
|
});
|
|
608
610
|
_View.displayName = 'MpxView';
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { forwardRef, useRef, useContext, useMemo, useState, useCallback, useEffect } from 'react';
|
|
2
|
-
import { warn,
|
|
2
|
+
import { warn, isFunction } from '@mpxjs/utils';
|
|
3
3
|
import Portal from './mpx-portal';
|
|
4
4
|
import { getCustomEvent } from './getInnerListeners';
|
|
5
5
|
import { promisify, redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy';
|
|
6
6
|
import { WebView } from 'react-native-webview';
|
|
7
7
|
import useNodesRef from './useNodesRef';
|
|
8
|
-
import { getCurrentPage
|
|
8
|
+
import { getCurrentPage } from './utils';
|
|
9
|
+
import { useNavigation } from '@react-navigation/native';
|
|
9
10
|
import { RouteContext } from './context';
|
|
10
|
-
import { BackHandler, StyleSheet, View, Text
|
|
11
|
+
import { BackHandler, StyleSheet, View, Text } from 'react-native';
|
|
11
12
|
const styles = StyleSheet.create({
|
|
12
13
|
loadErrorContext: {
|
|
13
14
|
display: 'flex',
|
|
@@ -53,6 +54,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
53
54
|
const [pageLoadErr, setPageLoadErr] = useState(false);
|
|
54
55
|
const currentPage = useMemo(() => getCurrentPage(pageId), [pageId]);
|
|
55
56
|
const webViewRef = useRef(null);
|
|
57
|
+
const isLoaded = useRef(false);
|
|
56
58
|
const defaultWebViewStyle = {
|
|
57
59
|
position: 'absolute',
|
|
58
60
|
left: 0,
|
|
@@ -61,6 +63,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
61
63
|
bottom: 0
|
|
62
64
|
};
|
|
63
65
|
const canGoBack = useRef(false);
|
|
66
|
+
const isNavigateBack = useRef(false);
|
|
64
67
|
const onAndroidBackPress = useCallback(() => {
|
|
65
68
|
if (canGoBack.current) {
|
|
66
69
|
webViewRef.current?.goBack();
|
|
@@ -69,42 +72,27 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
69
72
|
return false;
|
|
70
73
|
}, [canGoBack]);
|
|
71
74
|
const beforeRemoveHandle = useCallback((e) => {
|
|
72
|
-
if (canGoBack.current) {
|
|
75
|
+
if (canGoBack.current && !isNavigateBack.current) {
|
|
73
76
|
webViewRef.current?.goBack();
|
|
74
77
|
e.preventDefault();
|
|
75
78
|
}
|
|
79
|
+
isNavigateBack.current = false;
|
|
76
80
|
}, [canGoBack]);
|
|
77
|
-
const navigation =
|
|
78
|
-
// ios 16以下版本 的hash会被转义,因此对于iOS环境下在页面load之后再注入hash部分的逻辑
|
|
79
|
-
let [baseUrl, hashParams = ''] = src.split('#');
|
|
80
|
-
if (hashParams)
|
|
81
|
-
hashParams = '#' + hashParams;
|
|
82
|
-
const source = useMemo(() => {
|
|
83
|
-
if (Platform.OS === 'ios') {
|
|
84
|
-
return { uri: baseUrl };
|
|
85
|
-
}
|
|
86
|
-
return { uri: baseUrl + hashParams };
|
|
87
|
-
}, [baseUrl, hashParams]);
|
|
88
|
-
const hashInjectedJavascript = useMemo(() => {
|
|
89
|
-
if (Platform.OS === 'ios' && hashParams) {
|
|
90
|
-
return `(function() {
|
|
91
|
-
try {
|
|
92
|
-
location.hash = '${hashParams}';
|
|
93
|
-
} catch(e) {
|
|
94
|
-
}
|
|
95
|
-
})()`;
|
|
96
|
-
}
|
|
97
|
-
return '';
|
|
98
|
-
}, [hashParams]);
|
|
99
|
-
navigation?.addListener('beforeRemove', beforeRemoveHandle);
|
|
81
|
+
const navigation = useNavigation();
|
|
100
82
|
useEffect(() => {
|
|
101
83
|
if (__mpx_mode__ === 'android') {
|
|
102
84
|
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
|
|
103
|
-
return () => {
|
|
104
|
-
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
|
|
105
|
-
navigation?.removeListener('beforeRemove', beforeRemoveHandle);
|
|
106
|
-
};
|
|
107
85
|
}
|
|
86
|
+
const addListener = navigation?.addListener.bind(navigation);
|
|
87
|
+
const beforeRemoveSubscription = addListener?.('beforeRemove', beforeRemoveHandle);
|
|
88
|
+
return () => {
|
|
89
|
+
if (__mpx_mode__ === 'android') {
|
|
90
|
+
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
|
|
91
|
+
}
|
|
92
|
+
if (isFunction(beforeRemoveSubscription)) {
|
|
93
|
+
beforeRemoveSubscription();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
108
96
|
}, []);
|
|
109
97
|
useNodesRef(props, ref, webViewRef, {
|
|
110
98
|
style: defaultWebViewStyle
|
|
@@ -112,27 +100,6 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
112
100
|
if (!src) {
|
|
113
101
|
return null;
|
|
114
102
|
}
|
|
115
|
-
const _load = function (res) {
|
|
116
|
-
const result = {
|
|
117
|
-
type: 'load',
|
|
118
|
-
timeStamp: res.timeStamp,
|
|
119
|
-
detail: {
|
|
120
|
-
src: res.nativeEvent?.url
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
bindload?.(result);
|
|
124
|
-
};
|
|
125
|
-
const _error = function (res) {
|
|
126
|
-
setPageLoadErr(true);
|
|
127
|
-
const result = {
|
|
128
|
-
type: 'error',
|
|
129
|
-
timeStamp: res.timeStamp,
|
|
130
|
-
detail: {
|
|
131
|
-
src: ''
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
binderror && binderror(result);
|
|
135
|
-
};
|
|
136
103
|
const _reload = function () {
|
|
137
104
|
setPageLoadErr(false);
|
|
138
105
|
};
|
|
@@ -159,7 +126,6 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
159
126
|
return _documentTitle
|
|
160
127
|
}
|
|
161
128
|
});
|
|
162
|
-
${hashInjectedJavascript}
|
|
163
129
|
}
|
|
164
130
|
true;
|
|
165
131
|
`;
|
|
@@ -218,6 +184,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
218
184
|
asyncCallback = navObj.navigateTo(...params);
|
|
219
185
|
break;
|
|
220
186
|
case 'navigateBack':
|
|
187
|
+
isNavigateBack.current = true;
|
|
221
188
|
asyncCallback = navObj.navigateBack(...params);
|
|
222
189
|
break;
|
|
223
190
|
case 'redirectTo':
|
|
@@ -264,22 +231,58 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
264
231
|
}
|
|
265
232
|
});
|
|
266
233
|
};
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
234
|
+
let isLoadError = false;
|
|
235
|
+
let fristLoaded = false;
|
|
236
|
+
let statusCode = '';
|
|
237
|
+
const onLoadEnd = function (res) {
|
|
238
|
+
fristLoaded = true;
|
|
239
|
+
isLoaded.current = true;
|
|
240
|
+
const src = res.nativeEvent?.url;
|
|
241
|
+
if (isLoadError) {
|
|
242
|
+
isLoadError = false;
|
|
243
|
+
isNavigateBack.current = false;
|
|
244
|
+
const result = {
|
|
245
|
+
type: 'error',
|
|
246
|
+
timeStamp: res.timeStamp,
|
|
247
|
+
detail: {
|
|
248
|
+
src,
|
|
249
|
+
statusCode
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
binderror && binderror(result);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
const result = {
|
|
256
|
+
type: 'load',
|
|
257
|
+
timeStamp: res.timeStamp,
|
|
258
|
+
detail: {
|
|
259
|
+
src
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
bindload?.(result);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const onHttpError = function (res) {
|
|
266
|
+
isLoadError = true;
|
|
267
|
+
statusCode = res.nativeEvent?.statusCode;
|
|
268
|
+
};
|
|
269
|
+
const onError = function () {
|
|
270
|
+
statusCode = '';
|
|
271
|
+
isLoadError = true;
|
|
272
|
+
if (!fristLoaded) {
|
|
273
|
+
setPageLoadErr(true);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const onLoadStart = function () {
|
|
277
|
+
isLoaded.current = false;
|
|
278
|
+
};
|
|
276
279
|
return (<Portal key={pageLoadErr ? 'error' : 'webview'}>
|
|
277
280
|
{pageLoadErr
|
|
278
281
|
? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
|
|
279
282
|
<View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
|
|
280
283
|
<View style={styles.loadErrorButton} onTouchEnd={_reload}><Text style={{ fontSize: 12, color: '#666666' }}>{currentErrorText.button}</Text></View>
|
|
281
284
|
</View>)
|
|
282
|
-
: (<WebView style={defaultWebViewStyle} source={
|
|
285
|
+
: (<WebView style={defaultWebViewStyle} source={{ uri: src }} pointerEvents={isLoaded ? 'auto' : 'none'} ref={webViewRef} javaScriptEnabled={true} onNavigationStateChange={_changeUrl} onMessage={_message} injectedJavaScript={injectedJavaScript} onLoadProgress={_onLoadProgress} onLoadEnd={onLoadEnd} onHttpError={onHttpError} onError={onError} onLoadStart={onLoadStart} allowsBackForwardNavigationGestures={true}></WebView>)}
|
|
283
286
|
</Portal>);
|
|
284
287
|
});
|
|
285
288
|
_WebView.displayName = 'MpxWebview';
|
|
@@ -30,9 +30,6 @@ export const createFaces = (itemHeight, visibleCount) => {
|
|
|
30
30
|
for (let i = 0; i < index; i++) {
|
|
31
31
|
offset += freeSpaces[i];
|
|
32
32
|
}
|
|
33
|
-
if (index === 0) {
|
|
34
|
-
offset *= 0.6;
|
|
35
|
-
}
|
|
36
33
|
return offset;
|
|
37
34
|
});
|
|
38
35
|
return [screenHeights, offsets];
|
|
@@ -41,9 +38,7 @@ export const createFaces = (itemHeight, visibleCount) => {
|
|
|
41
38
|
const map = {
|
|
42
39
|
0: 0,
|
|
43
40
|
1: 0.8,
|
|
44
|
-
2: 0.9
|
|
45
|
-
// 3: 0.45, // 0.45
|
|
46
|
-
// 4: 0.5 // 0.5
|
|
41
|
+
2: 0.9
|
|
47
42
|
};
|
|
48
43
|
return map[index] ?? Math.min(1, map[2] + index * 0.05);
|
|
49
44
|
};
|
|
@@ -139,20 +139,23 @@ export default function useAnimationHooks(props) {
|
|
|
139
139
|
if (enableAnimationRef.current !== enableStyleAnimation) {
|
|
140
140
|
error('[Mpx runtime error]: animation use should be stable in the component lifecycle, or you can set [enable-animation] with true.');
|
|
141
141
|
}
|
|
142
|
-
if (!
|
|
143
|
-
return { enableStyleAnimation };
|
|
142
|
+
if (!enableAnimationRef.current)
|
|
143
|
+
return { enableStyleAnimation: false };
|
|
144
144
|
const originalStyle = formatStyle(style);
|
|
145
145
|
// id 标识
|
|
146
146
|
const id = animation?.id || -1;
|
|
147
147
|
// 有动画样式的 style key
|
|
148
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
148
149
|
const animatedStyleKeys = useSharedValue([]);
|
|
149
150
|
// 记录动画key的style样式值 没有的话设置为false
|
|
151
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
150
152
|
const animatedKeys = useRef({});
|
|
151
153
|
// const animatedKeys = useRef({} as {[propName: keyof ExtendedViewStyle]: boolean|number|string})
|
|
152
154
|
// ** 全量 style prop sharedValue
|
|
153
155
|
// 不能做增量的原因:
|
|
154
156
|
// 1 尝试用 useRef,但 useAnimatedStyle 访问后的 ref 不能在增加新的值,被冻结
|
|
155
157
|
// 2 尝试用 useSharedValue,因为实际触发的 style prop 需要是 sharedValue 才能驱动动画,若外层 shareValMap 也是 sharedValue,动画无法驱动。
|
|
158
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
156
159
|
const shareValMap = useMemo(() => {
|
|
157
160
|
return Object.keys(InitialValue).reduce((valMap, key) => {
|
|
158
161
|
const defaultVal = getInitialVal(key, isTransform(key));
|
|
@@ -161,6 +164,7 @@ export default function useAnimationHooks(props) {
|
|
|
161
164
|
}, {});
|
|
162
165
|
}, []);
|
|
163
166
|
// ** 获取动画样式prop & 驱动动画
|
|
167
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
164
168
|
useEffect(() => {
|
|
165
169
|
if (id === -1)
|
|
166
170
|
return;
|
|
@@ -182,6 +186,7 @@ export default function useAnimationHooks(props) {
|
|
|
182
186
|
// })
|
|
183
187
|
// }, [style])
|
|
184
188
|
// ** 清空动画
|
|
189
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
185
190
|
useEffect(() => {
|
|
186
191
|
return () => {
|
|
187
192
|
Object.values(shareValMap).forEach((value) => {
|
|
@@ -214,14 +219,13 @@ export default function useAnimationHooks(props) {
|
|
|
214
219
|
}
|
|
215
220
|
// 添加每个key的多次step动画
|
|
216
221
|
animatedKeys.forEach(key => {
|
|
222
|
+
const ruleV = isTransform(key) ? transform.get(key) : rules.get(key);
|
|
217
223
|
// key不存在,第一轮取shareValMap[key]value,非第一轮取上一轮的
|
|
218
|
-
const toVal =
|
|
219
|
-
?
|
|
220
|
-
:
|
|
221
|
-
?
|
|
222
|
-
:
|
|
223
|
-
? lastValueMap[key]
|
|
224
|
-
: shareValMap[key].value;
|
|
224
|
+
const toVal = ruleV !== undefined
|
|
225
|
+
? ruleV
|
|
226
|
+
: index > 0
|
|
227
|
+
? lastValueMap[key]
|
|
228
|
+
: shareValMap[key].value;
|
|
225
229
|
const animation = getAnimation({ key, value: toVal }, { delay, duration, easing }, needSetCallback ? setTransformOrigin : undefined);
|
|
226
230
|
needSetCallback = false;
|
|
227
231
|
if (!sequence[key]) {
|
|
@@ -315,6 +319,7 @@ export default function useAnimationHooks(props) {
|
|
|
315
319
|
}, {});
|
|
316
320
|
}
|
|
317
321
|
// ** 生成动画样式
|
|
322
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
318
323
|
const animationStyle = useAnimatedStyle(() => {
|
|
319
324
|
// console.info(`useAnimatedStyle styles=`, originalStyle)
|
|
320
325
|
return animatedStyleKeys.value.reduce((styles, key) => {
|
|
@@ -335,7 +340,7 @@ export default function useAnimationHooks(props) {
|
|
|
335
340
|
}, {});
|
|
336
341
|
});
|
|
337
342
|
return {
|
|
338
|
-
enableStyleAnimation,
|
|
343
|
+
enableStyleAnimation: enableAnimationRef.current,
|
|
339
344
|
animationStyle
|
|
340
345
|
};
|
|
341
346
|
}
|
|
@@ -559,3 +559,60 @@ export function useHoverStyle({ hoverStyle, hoverStartTime, hoverStayTime, disab
|
|
|
559
559
|
enableHoverStyle
|
|
560
560
|
};
|
|
561
561
|
}
|
|
562
|
+
export function useHover({ enableHover, hoverStartTime, hoverStayTime, disabled }) {
|
|
563
|
+
const enableHoverRef = useRef(enableHover);
|
|
564
|
+
if (enableHoverRef.current !== enableHover) {
|
|
565
|
+
error('[Mpx runtime error]: hover-class use should be stable in the component lifecycle.');
|
|
566
|
+
}
|
|
567
|
+
if (!enableHoverRef.current)
|
|
568
|
+
return { isHover: false };
|
|
569
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
570
|
+
const gestureRef = useContext(ScrollViewContext).gestureRef;
|
|
571
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
572
|
+
const [isHover, setIsHover] = useState(false);
|
|
573
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
574
|
+
const dataRef = useRef({});
|
|
575
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
576
|
+
useEffect(() => {
|
|
577
|
+
return () => {
|
|
578
|
+
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
579
|
+
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
580
|
+
};
|
|
581
|
+
}, []);
|
|
582
|
+
const setStartTimer = () => {
|
|
583
|
+
if (disabled)
|
|
584
|
+
return;
|
|
585
|
+
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
586
|
+
dataRef.current.startTimer = setTimeout(() => {
|
|
587
|
+
setIsHover(true);
|
|
588
|
+
}, +hoverStartTime);
|
|
589
|
+
};
|
|
590
|
+
const setStayTimer = () => {
|
|
591
|
+
if (disabled)
|
|
592
|
+
return;
|
|
593
|
+
dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
|
|
594
|
+
dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
|
|
595
|
+
dataRef.current.stayTimer = setTimeout(() => {
|
|
596
|
+
setIsHover(false);
|
|
597
|
+
}, +hoverStayTime);
|
|
598
|
+
};
|
|
599
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
600
|
+
const gesture = useMemo(() => {
|
|
601
|
+
return Gesture.Pan()
|
|
602
|
+
.onTouchesDown(() => {
|
|
603
|
+
'worklet';
|
|
604
|
+
runOnJS(setStartTimer)();
|
|
605
|
+
})
|
|
606
|
+
.onTouchesUp(() => {
|
|
607
|
+
'worklet';
|
|
608
|
+
runOnJS(setStayTimer)();
|
|
609
|
+
});
|
|
610
|
+
}, []);
|
|
611
|
+
if (gestureRef) {
|
|
612
|
+
gesture.simultaneousWithExternalGesture(gestureRef);
|
|
613
|
+
}
|
|
614
|
+
return {
|
|
615
|
+
isHover,
|
|
616
|
+
gesture
|
|
617
|
+
};
|
|
618
|
+
}
|