@mpxjs/webpack-plugin 2.9.69-beta.1 → 2.9.69-beta.10

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.
Files changed (51) hide show
  1. package/lib/config.js +3 -1
  2. package/lib/platform/template/wx/index.js +3 -1
  3. package/lib/react/processScript.js +6 -4
  4. package/lib/runtime/components/react/context.ts +17 -0
  5. package/lib/runtime/components/react/dist/context.js +2 -0
  6. package/lib/runtime/components/react/dist/getInnerListeners.js +2 -2
  7. package/lib/runtime/components/react/dist/locale-provider.jsx +15 -0
  8. package/lib/runtime/components/react/dist/mpx-button.jsx +16 -44
  9. package/lib/runtime/components/react/dist/mpx-image.jsx +13 -9
  10. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +2 -1
  11. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +2 -2
  12. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +65 -61
  13. package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +23 -0
  14. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +93 -0
  15. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +40 -0
  16. package/lib/runtime/components/react/dist/mpx-portal.jsx +13 -0
  17. package/lib/runtime/components/react/dist/mpx-provider.jsx +31 -0
  18. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  19. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +9 -5
  20. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +13 -7
  21. package/lib/runtime/components/react/dist/mpx-swiper.jsx +384 -321
  22. package/lib/runtime/components/react/dist/mpx-view.jsx +16 -20
  23. package/lib/runtime/components/react/dist/mpx-web-view.jsx +129 -53
  24. package/lib/runtime/components/react/dist/pickerFaces.js +2 -7
  25. package/lib/runtime/components/react/dist/useAnimationHooks.js +30 -13
  26. package/lib/runtime/components/react/dist/utils.jsx +60 -2
  27. package/lib/runtime/components/react/getInnerListeners.ts +2 -2
  28. package/lib/runtime/components/react/locale-provider.tsx +83 -0
  29. package/lib/runtime/components/react/mpx-button.tsx +20 -57
  30. package/lib/runtime/components/react/mpx-image.tsx +41 -25
  31. package/lib/runtime/components/react/mpx-picker/time.tsx +2 -1
  32. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +3 -3
  33. package/lib/runtime/components/react/mpx-picker-view-column.tsx +70 -69
  34. package/lib/runtime/components/react/mpx-portal/portal-consumer.tsx +32 -0
  35. package/lib/runtime/components/react/mpx-portal/portal-host.tsx +127 -0
  36. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +64 -0
  37. package/lib/runtime/components/react/mpx-portal.tsx +30 -0
  38. package/lib/runtime/components/react/mpx-provider.tsx +51 -0
  39. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  40. package/lib/runtime/components/react/mpx-scroll-view.tsx +10 -8
  41. package/lib/runtime/components/react/mpx-swiper-item.tsx +13 -7
  42. package/lib/runtime/components/react/mpx-swiper.tsx +378 -325
  43. package/lib/runtime/components/react/mpx-view.tsx +19 -22
  44. package/lib/runtime/components/react/mpx-web-view.tsx +170 -62
  45. package/lib/runtime/components/react/pickerFaces.ts +2 -7
  46. package/lib/runtime/components/react/types/global.d.ts +7 -0
  47. package/lib/runtime/components/react/useAnimationHooks.ts +34 -14
  48. package/lib/runtime/components/react/utils.tsx +67 -2
  49. package/lib/template-compiler/compiler.js +1 -1
  50. package/lib/wxss/loader.js +15 -2
  51. 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, useHoverStyle } 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
16
  import { GestureDetector } from 'react-native-gesture-handler';
@@ -442,7 +442,7 @@ function inheritStyle(innerStyle = {}) {
442
442
  }
443
443
  : undefined);
444
444
  }
445
- function wrapImage(imageStyle, innerStyle, enableFastImage) {
445
+ function useWrapImage(imageStyle, innerStyle, enableFastImage) {
446
446
  // 预处理数据
447
447
  const preImageInfo = preParseImage(imageStyle);
448
448
  // 预解析
@@ -535,7 +535,8 @@ function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backg
535
535
  textProps
536
536
  });
537
537
  return [
538
- enableBackground ? wrapImage(backgroundStyle, innerStyle, enableFastImage) : null,
538
+ // eslint-disable-next-line react-hooks/rules-of-hooks
539
+ enableBackground ? useWrapImage(backgroundStyle, innerStyle, enableFastImage) : null,
539
540
  children
540
541
  ];
541
542
  }
@@ -551,7 +552,8 @@ const _View = forwardRef((viewProps, ref) => {
551
552
  flexWrap: 'nowrap'
552
553
  }
553
554
  : {};
554
- const { isHover, enableHoverStyle, gesture } = useHoverStyle({ hoverStyle, hoverStartTime, hoverStayTime });
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,
@@ -572,20 +574,14 @@ const _View = forwardRef((viewProps, ref) => {
572
574
  });
573
575
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
574
576
  const viewStyle = extendObject({}, innerStyle, layoutStyle);
575
- enableAnimation = enableAnimation || !!animation;
576
- const enableAnimationRef = useRef(enableAnimation);
577
- if (enableAnimationRef.current !== enableAnimation) {
578
- error('[Mpx runtime error]: animation use should be stable in the component lifecycle, or you can set [enable-animation] with true.');
579
- }
580
- const finalStyle = enableAnimationRef.current
581
- ? [viewStyle, useAnimationHooks({
582
- animation,
583
- style: viewStyle
584
- })]
585
- : viewStyle;
577
+ const { enableStyleAnimation, animationStyle } = useAnimationHooks({
578
+ enableAnimation,
579
+ animation,
580
+ style: viewStyle
581
+ });
586
582
  const innerProps = useInnerProps(props, extendObject({
587
583
  ref: nodeRef,
588
- style: finalStyle
584
+ style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
589
585
  }, layoutProps), [
590
586
  'hover-start-time',
591
587
  'hover-stay-time',
@@ -604,11 +600,11 @@ const _View = forwardRef((viewProps, ref) => {
604
600
  innerStyle,
605
601
  enableFastImage
606
602
  });
607
- const BaseComponent = enableAnimation
608
- ? createElement(Animated.View, extendObject({}, innerProps, { style: finalStyle }), childNode)
603
+ const BaseComponent = enableStyleAnimation
604
+ ? createElement(Animated.View, innerProps, childNode)
609
605
  : createElement(View, innerProps, childNode);
610
- return enableHoverStyle
611
- ? createElement(GestureDetector, { gesture }, BaseComponent)
606
+ return enableHover
607
+ ? createElement(GestureDetector, { gesture: gesture }, BaseComponent)
612
608
  : BaseComponent;
613
609
  });
614
610
  _View.displayName = 'MpxView';
@@ -1,22 +1,61 @@
1
- import { forwardRef, useRef, useContext, useMemo, createElement, useCallback, useEffect } from 'react';
2
- import { warn, getFocusedNavigation, isFunction } from '@mpxjs/utils';
3
- import { Portal } from '@ant-design/react-native';
1
+ import { forwardRef, useRef, useContext, useMemo, useState, useCallback, useEffect } from 'react';
2
+ import { warn, isFunction } from '@mpxjs/utils';
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, extendObject } from './utils';
8
+ import { getCurrentPage } from './utils';
9
+ import { useNavigation } from '@react-navigation/native';
9
10
  import { RouteContext } from './context';
10
- import { BackHandler } from 'react-native';
11
+ import { BackHandler, StyleSheet, View, Text } from 'react-native';
12
+ const styles = StyleSheet.create({
13
+ loadErrorContext: {
14
+ display: 'flex',
15
+ alignItems: 'center'
16
+ },
17
+ loadErrorText: {
18
+ fontSize: 12,
19
+ color: '#666666',
20
+ paddingTop: '40%',
21
+ paddingBottom: 20,
22
+ paddingLeft: '10%',
23
+ paddingRight: '10%',
24
+ textAlign: 'center'
25
+ },
26
+ loadErrorButton: {
27
+ color: '#666666',
28
+ textAlign: 'center',
29
+ padding: 10,
30
+ borderColor: '#666666',
31
+ borderStyle: 'solid',
32
+ borderWidth: StyleSheet.hairlineWidth,
33
+ borderRadius: 10
34
+ }
35
+ });
11
36
  const _WebView = forwardRef((props, ref) => {
12
37
  const { src, bindmessage, bindload, binderror } = props;
13
38
  const mpx = global.__mpx;
39
+ const errorText = {
40
+ 'zh-CN': {
41
+ text: '网络不可用,请检查网络设置',
42
+ button: '重新加载'
43
+ },
44
+ 'en-US': {
45
+ text: 'The network is not available. Please check the network settings',
46
+ button: 'Reload'
47
+ }
48
+ };
49
+ const currentErrorText = errorText[mpx.i18n.locale || 'zh-CN'];
14
50
  if (props.style) {
15
51
  warn('The web-view component does not support the style prop.');
16
52
  }
17
53
  const pageId = useContext(RouteContext);
54
+ const [pageLoadErr, setPageLoadErr] = useState(false);
18
55
  const currentPage = useMemo(() => getCurrentPage(pageId), [pageId]);
19
56
  const webViewRef = useRef(null);
57
+ const [isLoaded, setIsLoaded] = useState(true);
58
+ const fristLoaded = useRef(false);
20
59
  const defaultWebViewStyle = {
21
60
  position: 'absolute',
22
61
  left: 0,
@@ -25,6 +64,7 @@ const _WebView = forwardRef((props, ref) => {
25
64
  bottom: 0
26
65
  };
27
66
  const canGoBack = useRef(false);
67
+ const isNavigateBack = useRef(false);
28
68
  const onAndroidBackPress = useCallback(() => {
29
69
  if (canGoBack.current) {
30
70
  webViewRef.current?.goBack();
@@ -33,20 +73,27 @@ const _WebView = forwardRef((props, ref) => {
33
73
  return false;
34
74
  }, [canGoBack]);
35
75
  const beforeRemoveHandle = useCallback((e) => {
36
- if (canGoBack.current) {
76
+ if (canGoBack.current && !isNavigateBack.current) {
37
77
  webViewRef.current?.goBack();
38
78
  e.preventDefault();
39
79
  }
80
+ isNavigateBack.current = false;
40
81
  }, [canGoBack]);
41
- const navigation = getFocusedNavigation();
42
- navigation?.addListener('beforeRemove', beforeRemoveHandle);
82
+ const navigation = useNavigation();
43
83
  useEffect(() => {
44
84
  if (__mpx_mode__ === 'android') {
45
85
  BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
46
- return () => {
47
- BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
48
- };
49
86
  }
87
+ const addListener = navigation?.addListener.bind(navigation);
88
+ const beforeRemoveSubscription = addListener?.('beforeRemove', beforeRemoveHandle);
89
+ return () => {
90
+ if (__mpx_mode__ === 'android') {
91
+ BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
92
+ }
93
+ if (isFunction(beforeRemoveSubscription)) {
94
+ beforeRemoveSubscription();
95
+ }
96
+ };
50
97
  }, []);
51
98
  useNodesRef(props, ref, webViewRef, {
52
99
  style: defaultWebViewStyle
@@ -54,25 +101,11 @@ const _WebView = forwardRef((props, ref) => {
54
101
  if (!src) {
55
102
  return null;
56
103
  }
57
- const _load = function (res) {
58
- const result = {
59
- type: 'load',
60
- timeStamp: res.timeStamp,
61
- detail: {
62
- src: res.nativeEvent?.url
63
- }
64
- };
65
- bindload(result);
66
- };
67
- const _error = function (res) {
68
- const result = {
69
- type: 'error',
70
- timeStamp: res.timeStamp,
71
- detail: {
72
- src: ''
73
- }
74
- };
75
- binderror(result);
104
+ const _reload = function () {
105
+ if (__mpx_mode__ === 'android') {
106
+ fristLoaded.current = false; // 安卓需要重新设置
107
+ }
108
+ setPageLoadErr(false);
76
109
  };
77
110
  const injectedJavaScript = `
78
111
  if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
@@ -102,7 +135,7 @@ const _WebView = forwardRef((props, ref) => {
102
135
  `;
103
136
  const sendMessage = function (params) {
104
137
  return `
105
- window.mpxWebviewMessageCallback(${params})
138
+ window.mpxWebviewMessageCallback && window.mpxWebviewMessageCallback(${params})
106
139
  true;
107
140
  `;
108
141
  };
@@ -155,6 +188,7 @@ const _WebView = forwardRef((props, ref) => {
155
188
  asyncCallback = navObj.navigateTo(...params);
156
189
  break;
157
190
  case 'navigateBack':
191
+ isNavigateBack.current = true;
158
192
  asyncCallback = navObj.navigateBack(...params);
159
193
  break;
160
194
  case 'redirectTo':
@@ -201,28 +235,70 @@ const _WebView = forwardRef((props, ref) => {
201
235
  }
202
236
  });
203
237
  };
204
- const events = {};
205
- if (bindload) {
206
- extendObject(events, {
207
- onLoad: _load
208
- });
209
- }
210
- if (binderror) {
211
- extendObject(events, {
212
- onError: _error
213
- });
214
- }
215
- return createElement(Portal, null, createElement(WebView, extendObject({
216
- style: defaultWebViewStyle,
217
- source: { uri: src },
218
- ref: webViewRef,
219
- javaScriptEnabled: true,
220
- onNavigationStateChange: _changeUrl,
221
- onMessage: _message,
222
- injectedJavaScript: injectedJavaScript,
223
- onLoadProgress: _onLoadProgress,
224
- allowsBackForwardNavigationGestures: true
225
- }, events)));
238
+ let isLoadError = false;
239
+ let statusCode = '';
240
+ const onLoadEndHandle = function (res) {
241
+ fristLoaded.current = true;
242
+ setIsLoaded(true);
243
+ const src = res.nativeEvent?.url;
244
+ if (isLoadError) {
245
+ isLoadError = false;
246
+ isNavigateBack.current = false;
247
+ const result = {
248
+ type: 'error',
249
+ timeStamp: res.timeStamp,
250
+ detail: {
251
+ src,
252
+ statusCode
253
+ }
254
+ };
255
+ binderror && binderror(result);
256
+ }
257
+ else {
258
+ const result = {
259
+ type: 'load',
260
+ timeStamp: res.timeStamp,
261
+ detail: {
262
+ src
263
+ }
264
+ };
265
+ bindload?.(result);
266
+ }
267
+ };
268
+ const onLoadEnd = function (res) {
269
+ if (__mpx_mode__ === 'android') {
270
+ setTimeout(() => {
271
+ onLoadEndHandle(res);
272
+ }, 0);
273
+ }
274
+ else {
275
+ onLoadEndHandle(res);
276
+ }
277
+ };
278
+ const onHttpError = function (res) {
279
+ isLoadError = true;
280
+ statusCode = res.nativeEvent?.statusCode;
281
+ };
282
+ const onError = function () {
283
+ statusCode = '';
284
+ isLoadError = true;
285
+ if (!fristLoaded.current) {
286
+ setPageLoadErr(true);
287
+ }
288
+ };
289
+ const onLoadStart = function () {
290
+ if (!fristLoaded.current) {
291
+ setIsLoaded(false);
292
+ }
293
+ };
294
+ return (<Portal key={pageLoadErr ? 'error' : 'webview'}>
295
+ {pageLoadErr
296
+ ? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
297
+ <View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
298
+ <View style={styles.loadErrorButton} onTouchEnd={_reload}><Text style={{ fontSize: 12, color: '#666666' }}>{currentErrorText.button}</Text></View>
299
+ </View>)
300
+ : (<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>)}
301
+ </Portal>);
226
302
  });
227
303
  _WebView.displayName = 'MpxWebview';
228
304
  export default _WebView;
@@ -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,15 +38,13 @@ export const createFaces = (itemHeight, visibleCount) => {
41
38
  const map = {
42
39
  0: 0,
43
40
  1: 0.8,
44
- 2: 0.9 // 0.35
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
  };
50
45
  const degrees = getDegreesRelativeCenter();
51
46
  const [screenHeight, offsets] = getScreenHeightsAndOffsets(degrees);
52
- const scales = [1, 0.925, 0.8];
47
+ const scales = [0.973, 0.9, 0.8];
53
48
  return [
54
49
  // top items
55
50
  ...degrees
@@ -1,12 +1,13 @@
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,
6
- ease: Easing.ease,
7
- 'ease-in': Easing.in(Easing.ease),
8
- 'ease-in-out': Easing.inOut(Easing.ease),
9
- 'ease-out': Easing.out(Easing.ease)
7
+ ease: Easing.inOut(Easing.ease),
8
+ 'ease-in': Easing.in(Easing.poly(3)),
9
+ 'ease-in-out': Easing.inOut(Easing.poly(3)),
10
+ 'ease-out': Easing.out(Easing.poly(3))
10
11
  // 'step-start': '',
11
12
  // 'step-end': ''
12
13
  };
@@ -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) => {
@@ -206,14 +219,13 @@ export default function useAnimationHooks(props) {
206
219
  }
207
220
  // 添加每个key的多次step动画
208
221
  animatedKeys.forEach(key => {
222
+ const ruleV = isTransform(key) ? transform.get(key) : rules.get(key);
209
223
  // key不存在,第一轮取shareValMap[key]value,非第一轮取上一轮的
210
- const toVal = rules.get(key) !== undefined
211
- ? rules.get(key)
212
- : transform.get(key) !== undefined
213
- ? transform.get(key)
214
- : index > 0
215
- ? lastValueMap[key]
216
- : shareValMap[key].value;
224
+ const toVal = ruleV !== undefined
225
+ ? ruleV
226
+ : index > 0
227
+ ? lastValueMap[key]
228
+ : shareValMap[key].value;
217
229
  const animation = getAnimation({ key, value: toVal }, { delay, duration, easing }, needSetCallback ? setTransformOrigin : undefined);
218
230
  needSetCallback = false;
219
231
  if (!sequence[key]) {
@@ -307,7 +319,8 @@ export default function useAnimationHooks(props) {
307
319
  }, {});
308
320
  }
309
321
  // ** 生成动画样式
310
- return useAnimatedStyle(() => {
322
+ // eslint-disable-next-line react-hooks/rules-of-hooks
323
+ const animationStyle = useAnimatedStyle(() => {
311
324
  // console.info(`useAnimatedStyle styles=`, originalStyle)
312
325
  return animatedStyleKeys.value.reduce((styles, key) => {
313
326
  // console.info('getAnimationStyles', key, shareValMap[key].value)
@@ -326,4 +339,8 @@ export default function useAnimationHooks(props) {
326
339
  return styles;
327
340
  }, {});
328
341
  });
342
+ return {
343
+ enableStyleAnimation: enableAnimationRef.current,
344
+ animationStyle
345
+ };
329
346
  }
@@ -451,13 +451,14 @@ export function wrapChildren(props = {}, { hasVarDec, varContext, textStyle, tex
451
451
  export const debounce = (func, delay) => {
452
452
  let timer;
453
453
  const wrapper = (...args) => {
454
- clearTimeout(timer);
454
+ timer && clearTimeout(timer);
455
455
  timer = setTimeout(() => {
456
456
  func(...args);
457
457
  }, delay);
458
458
  };
459
459
  wrapper.clear = () => {
460
- clearTimeout(timer);
460
+ timer && clearTimeout(timer);
461
+ timer = null;
461
462
  };
462
463
  return wrapper;
463
464
  };
@@ -558,3 +559,60 @@ export function useHoverStyle({ hoverStyle, hoverStartTime, hoverStayTime, disab
558
559
  enableHoverStyle
559
560
  };
560
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
+ }
@@ -126,8 +126,8 @@ function checkIsNeedPress (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
126
126
  const currentPageX = nativeEvent.changedTouches[0].pageX
127
127
  const currentPageY = nativeEvent.changedTouches[0].pageY
128
128
  if (
129
- Math.abs(currentPageX - tapDetailInfo.x) > 1 ||
130
- Math.abs(currentPageY - tapDetailInfo.y) > 1
129
+ Math.abs(currentPageX - tapDetailInfo.x) > 3 ||
130
+ Math.abs(currentPageY - tapDetailInfo.y) > 3
131
131
  ) {
132
132
  ref.current!.needPress[type] = false
133
133
  ref.current!.startTimer[type] &&
@@ -0,0 +1,83 @@
1
+ import { createContext, useMemo, memo, ReactNode } from 'react'
2
+ import { extendObject } from './utils'
3
+
4
+ interface Locale {
5
+ /** zh_CN */
6
+ locale: string
7
+ DatePicker: {
8
+ /** 确定 */
9
+ okText: string
10
+ /** 取消 */
11
+ dismissText: string
12
+ /** 请选择 */
13
+ extra: string
14
+ DatePickerLocale: {
15
+ /** 年 */
16
+ year: string
17
+ /** 月 */
18
+ month: string
19
+ /** 日 */
20
+ day: string
21
+ /** 时 */
22
+ hour: string
23
+ /** 分 */
24
+ minute: string
25
+ /** 上午 */
26
+ am: string
27
+ /** 下午 */
28
+ pm: string
29
+ }
30
+ }
31
+ DatePickerView: {
32
+ /** 年 */
33
+ year: string
34
+ /** 月 */
35
+ month: string
36
+ /** 日 */
37
+ day: string
38
+ /** 时 */
39
+ hour: string
40
+ /** 分 */
41
+ minute: string
42
+ /** 上午 */
43
+ am: string
44
+ /** 下午 */
45
+ pm: string
46
+ }
47
+ Picker: {
48
+ /** 确定 */
49
+ okText: string
50
+ /** 取消 */
51
+ dismissText: string
52
+ /** 请选择 */
53
+ extra: string
54
+ }
55
+ }
56
+ export type LocaleContextProps = {
57
+ antLocale: Partial<Locale & { exist: boolean }>
58
+ }
59
+ export interface LocaleProviderProps {
60
+ children?: ReactNode,
61
+ locale?: LocaleContextProps
62
+ }
63
+
64
+ export const LocaleContext = createContext<
65
+ LocaleContextProps | undefined
66
+ >(undefined)
67
+
68
+ const LocaleProvider = (props :LocaleProviderProps): JSX.Element => {
69
+ const locale = useMemo(() => {
70
+ return {
71
+ antLocale: extendObject({}, props.locale, { exist: true })
72
+ }
73
+ }, [props.locale])
74
+ return (
75
+ <LocaleContext.Provider value={locale}>
76
+ {props.children}
77
+ </LocaleContext.Provider>
78
+ )
79
+ }
80
+
81
+ LocaleProvider.displayName = 'LocaleProvider'
82
+
83
+ export default memo(LocaleProvider)