@mpxjs/webpack-plugin 2.9.69-beta.3 → 2.9.69-beta.4

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 (65) hide show
  1. package/lib/index.js +17 -1
  2. package/lib/platform/style/wx/index.js +18 -18
  3. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  4. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  5. package/lib/react/processScript.js +1 -1
  6. package/lib/resolver/AddEnvPlugin.js +1 -0
  7. package/lib/resolver/AddModePlugin.js +1 -0
  8. package/lib/runtime/components/react/context.ts +25 -0
  9. package/lib/runtime/components/react/dist/context.js +2 -0
  10. package/lib/runtime/components/react/dist/getInnerListeners.js +2 -2
  11. package/lib/runtime/components/react/dist/locale-provider.jsx +15 -0
  12. package/lib/runtime/components/react/dist/mpx-button.jsx +9 -37
  13. package/lib/runtime/components/react/dist/mpx-image.jsx +13 -9
  14. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +2 -1
  15. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +12 -13
  16. package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +23 -0
  17. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +124 -0
  18. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +40 -0
  19. package/lib/runtime/components/react/dist/mpx-portal.jsx +12 -0
  20. package/lib/runtime/components/react/dist/mpx-provider.jsx +31 -0
  21. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  22. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +10 -16
  23. package/lib/runtime/components/react/dist/mpx-swiper.jsx +10 -5
  24. package/lib/runtime/components/react/dist/mpx-view.jsx +15 -21
  25. package/lib/runtime/components/react/dist/mpx-web-view.jsx +78 -20
  26. package/lib/runtime/components/react/dist/pickerFaces.js +1 -1
  27. package/lib/runtime/components/react/dist/useAnimationHooks.js +14 -2
  28. package/lib/runtime/components/react/getInnerListeners.ts +5 -7
  29. package/lib/runtime/components/react/locale-provider.tsx +83 -0
  30. package/lib/runtime/components/react/mpx-button.tsx +13 -49
  31. package/lib/runtime/components/react/mpx-image.tsx +41 -25
  32. package/lib/runtime/components/react/mpx-input.tsx +1 -1
  33. package/lib/runtime/components/react/mpx-movable-view.tsx +1 -1
  34. package/lib/runtime/components/react/mpx-picker/time.tsx +2 -1
  35. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +88 -0
  36. package/lib/runtime/components/react/mpx-picker-view-column.tsx +180 -163
  37. package/lib/runtime/components/react/mpx-picker-view.tsx +35 -37
  38. package/lib/runtime/components/react/mpx-portal/portal-consumer.tsx +32 -0
  39. package/lib/runtime/components/react/mpx-portal/portal-host.tsx +158 -0
  40. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +64 -0
  41. package/lib/runtime/components/react/mpx-portal.tsx +29 -0
  42. package/lib/runtime/components/react/mpx-provider.tsx +51 -0
  43. package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
  44. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  45. package/lib/runtime/components/react/mpx-scroll-view.tsx +29 -18
  46. package/lib/runtime/components/react/mpx-swiper-item.tsx +38 -10
  47. package/lib/runtime/components/react/mpx-swiper.tsx +696 -0
  48. package/lib/runtime/components/react/mpx-view.tsx +25 -71
  49. package/lib/runtime/components/react/mpx-web-view.tsx +156 -23
  50. package/lib/runtime/components/react/pickerFaces.ts +15 -7
  51. package/lib/runtime/components/react/pickerVIewContext.ts +18 -0
  52. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  53. package/lib/runtime/components/react/{pickerOverlay.tsx → pickerViewOverlay.tsx} +5 -3
  54. package/lib/runtime/components/react/types/global.d.ts +6 -1
  55. package/lib/runtime/components/react/useAnimationHooks.ts +20 -4
  56. package/lib/runtime/components/react/utils.tsx +75 -5
  57. package/lib/style-compiler/index.js +3 -4
  58. package/lib/style-compiler/strip-conditional-loader.js +118 -0
  59. package/lib/template-compiler/compiler.js +9 -14
  60. package/lib/utils/hump-dash.js +1 -1
  61. package/lib/utils/pre-process-json.js +5 -9
  62. package/package.json +1 -1
  63. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  64. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  65. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
@@ -0,0 +1,31 @@
1
+ import { createContext, useMemo } from 'react';
2
+ import LocaleProvider from './locale-provider';
3
+ import Portal from './mpx-portal';
4
+ import { extendObject } from './utils';
5
+ const defaultTheme = {
6
+ color_text_base: '#000000',
7
+ color_text_base_inverse: '#ffffff',
8
+ color_text_secondary: '#a4a9b0',
9
+ color_text_placeholder: '#bbbbbb',
10
+ color_text_disabled: '#bbbbbb',
11
+ color_text_caption: '#888888',
12
+ color_text_paragraph: '#333333',
13
+ color_error: '#ff4d4f',
14
+ color_warning: '#faad14',
15
+ color_success: '#52c41a',
16
+ color_primary: '#1677ff'
17
+ };
18
+ export const ThemeContext = createContext(defaultTheme);
19
+ const ThemeProvider = (props) => {
20
+ const { value, children } = props;
21
+ const theme = useMemo(() => (extendObject({}, defaultTheme, value)), [value]);
22
+ return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
23
+ };
24
+ const Provider = ({ locale, theme, children }) => {
25
+ return (<LocaleProvider locale={locale}>
26
+ <ThemeProvider value={theme}>
27
+ <Portal.Host>{children}</Portal.Host>
28
+ </ThemeProvider>
29
+ </LocaleProvider>);
30
+ };
31
+ export default Provider;
@@ -2,7 +2,7 @@
2
2
  * ✔ enable
3
3
  */
4
4
  import { createElement, Fragment } from 'react';
5
- import { Portal } from '@ant-design/react-native';
5
+ import Portal from './mpx-portal';
6
6
  import { warn } from '@mpxjs/utils';
7
7
  const _RootPortal = (props) => {
8
8
  const { children, enable = true } = props;
@@ -32,7 +32,7 @@
32
32
  * ✔ bindscroll
33
33
  */
34
34
  import { ScrollView } from 'react-native-gesture-handler';
35
- import { RefreshControl, Platform } from 'react-native';
35
+ import { RefreshControl } from 'react-native';
36
36
  import { useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react';
37
37
  import { useAnimatedRef } from 'react-native-reanimated';
38
38
  import { warn } from '@mpxjs/utils';
@@ -184,7 +184,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
184
184
  visibleLength
185
185
  });
186
186
  }
187
- const observerTimers = {};
188
187
  function onScroll(e) {
189
188
  const { bindscroll } = props;
190
189
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
@@ -202,20 +201,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
202
201
  layoutRef
203
202
  }, props));
204
203
  updateScrollOptions(e, { scrollLeft, scrollTop });
205
- if (enableTriggerIntersectionObserver && intersectionObservers) {
206
- for (const key in intersectionObservers) {
207
- if (Platform.OS === 'android') {
208
- intersectionObservers[key].throttleMeasure();
209
- }
210
- else {
211
- // TODO: 由于iOS在onScroll滚动的过程中view的计算measureInWindow计算的值不发生变化,所以暂时在ios上加一个延时计算
212
- observerTimers[key] && clearTimeout(observerTimers[key]);
213
- observerTimers[key] = setTimeout(() => {
214
- intersectionObservers[key].throttleMeasure();
215
- }, 300);
216
- }
217
- }
218
- }
219
204
  }
220
205
  function onScrollEnd(e) {
221
206
  const { bindscrollend } = props;
@@ -234,6 +219,14 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
234
219
  updateScrollOptions(e, { scrollLeft, scrollTop });
235
220
  onStartReached(e);
236
221
  onEndReached(e);
222
+ updateIntersection();
223
+ }
224
+ function updateIntersection() {
225
+ if (enableTriggerIntersectionObserver && intersectionObservers) {
226
+ for (const key in intersectionObservers) {
227
+ intersectionObservers[key].throttleMeasure();
228
+ }
229
+ }
237
230
  }
238
231
  function scrollToOffset(x = 0, y = 0) {
239
232
  if (scrollViewRef.current) {
@@ -292,6 +285,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
292
285
  function onScrollDrag(e) {
293
286
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
294
287
  updateScrollOptions(e, { scrollLeft, scrollTop });
288
+ updateIntersection();
295
289
  }
296
290
  const scrollAdditionalProps = extendObject({
297
291
  style: extendObject({}, innerStyle, layoutStyle),
@@ -361,8 +361,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
361
361
  let isCriticalItem = false;
362
362
  // 真实滚动到的偏移量坐标
363
363
  let moveToTargetPos = 0;
364
- // 当前的位置
365
- const currentOffset = offset.value - previousMargin;
364
+ const currentOffset = translation < 0 ? offset.value - previousMargin : offset.value + previousMargin;
366
365
  const computedIndex = Math.abs(currentOffset) / step.value;
367
366
  const moveToIndex = translation < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex);
368
367
  // 实际应该定位的索引值
@@ -442,10 +441,13 @@ const SwiperWrapper = forwardRef((props, ref) => {
442
441
  'worklet';
443
442
  const { translation } = eventData;
444
443
  // 向右滑动的back:trans < 0, 向左滑动的back: trans < 0
445
- const currentOffset = Math.abs(offset.value);
444
+ let currentOffset = Math.abs(offset.value);
445
+ if (props.circular) {
446
+ currentOffset += translation < 0 ? previousMargin : -previousMargin;
447
+ }
446
448
  const curIndex = currentOffset / step.value;
447
449
  const moveToIndex = (translation < 0 ? Math.floor(curIndex) : Math.ceil(curIndex)) - patchElementNum;
448
- const targetOffset = -(moveToIndex + patchElementNum) * step.value + (translation < 0 ? -previousMargin : previousMargin);
450
+ const targetOffset = -(moveToIndex + patchElementNum) * step.value + (props.circular ? -previousMargin : 0);
449
451
  offset.value = withTiming(targetOffset, {
450
452
  duration: easeDuration,
451
453
  easing: easeMap[easeingFunc]
@@ -459,7 +461,10 @@ const SwiperWrapper = forwardRef((props, ref) => {
459
461
  function handleLongPress(eventData) {
460
462
  'worklet';
461
463
  const { translation } = eventData;
462
- const currentOffset = Math.abs(offset.value) + (translation < 0 ? previousMargin : -previousMargin);
464
+ let currentOffset = Math.abs(offset.value);
465
+ if (props.circular) {
466
+ currentOffset += previousMargin;
467
+ }
463
468
  const half = currentOffset % step.value > step.value / 2;
464
469
  // 向右trans < 0, 向左trans > 0
465
470
  const isExceedHalf = translation < 0 ? half : !half;
@@ -528,6 +528,11 @@ 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
+ }
531
536
  const children = wrapChildren(props, {
532
537
  hasVarDec,
533
538
  varContext,
@@ -541,7 +546,7 @@ function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backg
541
546
  }
542
547
  const _View = forwardRef((viewProps, ref) => {
543
548
  const { textProps, innerProps: props = {} } = splitProps(viewProps);
544
- 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;
549
+ const { 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
550
  // 默认样式
546
551
  const defaultStyle = style.display === 'flex'
547
552
  ? {
@@ -561,31 +566,20 @@ const _View = forwardRef((viewProps, ref) => {
561
566
  parentHeight
562
567
  });
563
568
  const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle);
564
- enableBackground = enableBackground || !!backgroundStyle;
565
- const enableBackgroundRef = useRef(enableBackground);
566
- if (enableBackgroundRef.current !== enableBackground) {
567
- error('[Mpx runtime error]: background use should be stable in the component lifecycle, or you can set [enable-background] with true.');
568
- }
569
569
  const nodeRef = useRef(null);
570
570
  useNodesRef(props, ref, nodeRef, {
571
571
  style: normalStyle
572
572
  });
573
573
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
574
574
  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;
575
+ const { enableStyleAnimation, animationStyle } = useAnimationHooks({
576
+ enableAnimation,
577
+ animation,
578
+ style: viewStyle
579
+ });
586
580
  const innerProps = useInnerProps(props, extendObject({
587
581
  ref: nodeRef,
588
- style: finalStyle
582
+ style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
589
583
  }, layoutProps), [
590
584
  'hover-start-time',
591
585
  'hover-stay-time',
@@ -596,7 +590,7 @@ const _View = forwardRef((viewProps, ref) => {
596
590
  });
597
591
  const childNode = wrapWithChildren(props, {
598
592
  hasVarDec,
599
- enableBackground: enableBackgroundRef.current,
593
+ enableBackground,
600
594
  textStyle,
601
595
  backgroundStyle,
602
596
  varContext: varContextRef.current,
@@ -604,8 +598,8 @@ const _View = forwardRef((viewProps, ref) => {
604
598
  innerStyle,
605
599
  enableFastImage
606
600
  });
607
- const BaseComponent = enableAnimation
608
- ? createElement(Animated.View, extendObject({}, innerProps, { style: finalStyle }), childNode)
601
+ const BaseComponent = enableStyleAnimation
602
+ ? createElement(Animated.View, innerProps, childNode)
609
603
  : createElement(View, innerProps, childNode);
610
604
  return enableHoverStyle
611
605
  ? createElement(GestureDetector, { gesture }, BaseComponent)
@@ -1,20 +1,56 @@
1
- import { forwardRef, useRef, useContext, useMemo, createElement, useCallback, useEffect } from 'react';
1
+ import { forwardRef, useRef, useContext, useMemo, useState, useCallback, useEffect } from 'react';
2
2
  import { warn, getFocusedNavigation, isFunction } from '@mpxjs/utils';
3
- import { Portal } from '@ant-design/react-native';
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
8
  import { getCurrentPage, extendObject } from './utils';
9
9
  import { RouteContext } from './context';
10
- import { BackHandler } from 'react-native';
10
+ import { BackHandler, StyleSheet, View, Text, Platform } from 'react-native';
11
+ const styles = StyleSheet.create({
12
+ loadErrorContext: {
13
+ display: 'flex',
14
+ alignItems: 'center'
15
+ },
16
+ loadErrorText: {
17
+ fontSize: 12,
18
+ color: '#666666',
19
+ paddingTop: '40%',
20
+ paddingBottom: 20,
21
+ paddingLeft: '10%',
22
+ paddingRight: '10%',
23
+ textAlign: 'center'
24
+ },
25
+ loadErrorButton: {
26
+ color: '#666666',
27
+ textAlign: 'center',
28
+ padding: 10,
29
+ borderColor: '#666666',
30
+ borderStyle: 'solid',
31
+ borderWidth: StyleSheet.hairlineWidth,
32
+ borderRadius: 10
33
+ }
34
+ });
11
35
  const _WebView = forwardRef((props, ref) => {
12
36
  const { src, bindmessage, bindload, binderror } = props;
13
37
  const mpx = global.__mpx;
38
+ const errorText = {
39
+ 'zh-CN': {
40
+ text: '网络不可用,请检查网络设置',
41
+ button: '重新加载'
42
+ },
43
+ 'en-US': {
44
+ text: 'The network is not available. Please check the network settings',
45
+ button: 'Reload'
46
+ }
47
+ };
48
+ const currentErrorText = errorText[mpx.i18n.locale || 'zh-CN'];
14
49
  if (props.style) {
15
50
  warn('The web-view component does not support the style prop.');
16
51
  }
17
52
  const pageId = useContext(RouteContext);
53
+ const [pageLoadErr, setPageLoadErr] = useState(false);
18
54
  const currentPage = useMemo(() => getCurrentPage(pageId), [pageId]);
19
55
  const webViewRef = useRef(null);
20
56
  const defaultWebViewStyle = {
@@ -39,12 +75,34 @@ const _WebView = forwardRef((props, ref) => {
39
75
  }
40
76
  }, [canGoBack]);
41
77
  const navigation = getFocusedNavigation();
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]);
42
99
  navigation?.addListener('beforeRemove', beforeRemoveHandle);
43
100
  useEffect(() => {
44
101
  if (__mpx_mode__ === 'android') {
45
102
  BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
46
103
  return () => {
47
104
  BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
105
+ navigation?.removeListener('beforeRemove', beforeRemoveHandle);
48
106
  };
49
107
  }
50
108
  }, []);
@@ -65,6 +123,7 @@ const _WebView = forwardRef((props, ref) => {
65
123
  bindload?.(result);
66
124
  };
67
125
  const _error = function (res) {
126
+ setPageLoadErr(true);
68
127
  const result = {
69
128
  type: 'error',
70
129
  timeStamp: res.timeStamp,
@@ -72,7 +131,10 @@ const _WebView = forwardRef((props, ref) => {
72
131
  src: ''
73
132
  }
74
133
  };
75
- binderror?.(result);
134
+ binderror && binderror(result);
135
+ };
136
+ const _reload = function () {
137
+ setPageLoadErr(false);
76
138
  };
77
139
  const injectedJavaScript = `
78
140
  if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
@@ -97,6 +159,7 @@ const _WebView = forwardRef((props, ref) => {
97
159
  return _documentTitle
98
160
  }
99
161
  });
162
+ ${hashInjectedJavascript}
100
163
  }
101
164
  true;
102
165
  `;
@@ -207,22 +270,17 @@ const _WebView = forwardRef((props, ref) => {
207
270
  onLoad: _load
208
271
  });
209
272
  }
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)));
273
+ extendObject(events, {
274
+ onError: _error
275
+ });
276
+ return (<Portal key={pageLoadErr ? 'error' : 'webview'}>
277
+ {pageLoadErr
278
+ ? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
279
+ <View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
280
+ <View style={styles.loadErrorButton} onTouchEnd={_reload}><Text style={{ fontSize: 12, color: '#666666' }}>{currentErrorText.button}</Text></View>
281
+ </View>)
282
+ : (<WebView style={defaultWebViewStyle} source={source} ref={webViewRef} javaScriptEnabled={true} onNavigationStateChange={_changeUrl} onMessage={_message} injectedJavaScript={injectedJavaScript} onLoadProgress={_onLoadProgress} allowsBackForwardNavigationGestures={true} {...events}></WebView>)}
283
+ </Portal>);
226
284
  });
227
285
  _WebView.displayName = 'MpxWebview';
228
286
  export default _WebView;
@@ -49,7 +49,7 @@ export const createFaces = (itemHeight, visibleCount) => {
49
49
  };
50
50
  const degrees = getDegreesRelativeCenter();
51
51
  const [screenHeight, offsets] = getScreenHeightsAndOffsets(degrees);
52
- const scales = [1, 0.925, 0.8];
52
+ const scales = [0.973, 0.9, 0.8];
53
53
  return [
54
54
  // top items
55
55
  ...degrees
@@ -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,7 +133,14 @@ 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 (!enableStyleAnimation)
143
+ return { enableStyleAnimation };
136
144
  const originalStyle = formatStyle(style);
137
145
  // id 标识
138
146
  const id = animation?.id || -1;
@@ -307,7 +315,7 @@ export default function useAnimationHooks(props) {
307
315
  }, {});
308
316
  }
309
317
  // ** 生成动画样式
310
- return useAnimatedStyle(() => {
318
+ const animationStyle = useAnimatedStyle(() => {
311
319
  // console.info(`useAnimatedStyle styles=`, originalStyle)
312
320
  return animatedStyleKeys.value.reduce((styles, key) => {
313
321
  // console.info('getAnimationStyles', key, shareValMap[key].value)
@@ -326,4 +334,8 @@ export default function useAnimationHooks(props) {
326
334
  return styles;
327
335
  }, {});
328
336
  });
337
+ return {
338
+ enableStyleAnimation,
339
+ animationStyle
340
+ };
329
341
  }
@@ -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] &&
@@ -289,7 +289,6 @@ const useInnerProps = (
289
289
  const eventConfig: { [key: string]: string[] } = {}
290
290
  const config = rawConfig || {
291
291
  layoutRef: { current: {} },
292
- disableTouch: false,
293
292
  disableTap: false
294
293
  }
295
294
  const removeProps = [
@@ -317,11 +316,10 @@ const useInnerProps = (
317
316
  }
318
317
  }
319
318
 
320
- if (!rawEventKeys.length || config.disableTouch) {
321
- return omit(propsRef.current, removeProps)
322
- }
323
-
324
319
  const events = useMemo(() => {
320
+ if (!rawEventKeys.length) {
321
+ return {}
322
+ }
325
323
  const transformedEventKeys = rawEventKeys.reduce((acc: string[], key) => {
326
324
  if (propsRef.current[key]) {
327
325
  return acc.concat(eventConfig[key])
@@ -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)
@@ -34,7 +34,7 @@
34
34
  * ✘ bindagreeprivacyauthorization
35
35
  * ✔ bindtap
36
36
  */
37
- import { createElement, useEffect, useRef, useState, ReactNode, forwardRef, useContext, JSX } from 'react'
37
+ import { createElement, useEffect, useRef, ReactNode, forwardRef, useContext, JSX } from 'react'
38
38
  import {
39
39
  View,
40
40
  StyleSheet,
@@ -45,10 +45,12 @@ import {
45
45
  NativeSyntheticEvent
46
46
  } from 'react-native'
47
47
  import { warn } from '@mpxjs/utils'
48
- import { getCurrentPage, splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils'
48
+ import { GestureDetector } from 'react-native-gesture-handler'
49
+ import { getCurrentPage, splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject, useHoverStyle } from './utils'
49
50
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
50
51
  import useNodesRef, { HandlerRef } from './useNodesRef'
51
52
  import { RouteContext, FormContext } from './context'
53
+ import type { ExtendedViewStyle } from './types/common'
52
54
 
53
55
  export type Type = 'default' | 'primary' | 'warn'
54
56
 
@@ -68,7 +70,7 @@ export interface ButtonProps {
68
70
  disabled?: boolean
69
71
  loading?: boolean
70
72
  'hover-class'?: string
71
- 'hover-style'?: ViewStyle & TextStyle & Record<string, any>
73
+ 'hover-style'?: ExtendedViewStyle
72
74
  'hover-start-time'?: number
73
75
  'hover-stay-time'?: number
74
76
  'open-type'?: OpenType
@@ -83,8 +85,6 @@ export interface ButtonProps {
83
85
  children: ReactNode
84
86
  bindgetuserinfo?: (userInfo: any) => void
85
87
  bindtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
86
- bindtouchstart?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
87
- bindtouchend?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
88
88
  }
89
89
 
90
90
  const LOADING_IMAGE_URI =
@@ -216,15 +216,15 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
216
216
  style = {},
217
217
  children,
218
218
  bindgetuserinfo,
219
- bindtap,
220
- bindtouchstart,
221
- bindtouchend
219
+ bindtap
222
220
  } = props
223
221
 
224
222
  const pageId = useContext(RouteContext)
225
223
 
226
224
  const formContext = useContext(FormContext)
227
225
 
226
+ const { isHover, enableHoverStyle, gesture } = useHoverStyle({ hoverStyle, hoverStartTime, hoverStayTime, disabled })
227
+
228
228
  let submitFn: () => void | undefined
229
229
  let resetFn: () => void | undefined
230
230
 
@@ -233,16 +233,6 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
233
233
  resetFn = formContext.reset
234
234
  }
235
235
 
236
- const refs = useRef<{
237
- hoverStartTimer: ReturnType<typeof setTimeout> | undefined
238
- hoverStayTimer: ReturnType<typeof setTimeout> | undefined
239
- }>({
240
- hoverStartTimer: undefined,
241
- hoverStayTimer: undefined
242
- })
243
-
244
- const [isHover, setIsHover] = useState(false)
245
-
246
236
  const isMiniSize = size === 'mini'
247
237
 
248
238
  const applyHoverEffect = isHover && hoverClass !== 'none'
@@ -366,34 +356,6 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
366
356
  }
367
357
  }
368
358
 
369
- const setStayTimer = () => {
370
- clearTimeout(refs.current.hoverStayTimer)
371
- refs.current.hoverStayTimer = setTimeout(() => {
372
- setIsHover(false)
373
- clearTimeout(refs.current.hoverStayTimer)
374
- }, hoverStayTime)
375
- }
376
-
377
- const setStartTimer = () => {
378
- clearTimeout(refs.current.hoverStartTimer)
379
- refs.current.hoverStartTimer = setTimeout(() => {
380
- setIsHover(true)
381
- clearTimeout(refs.current.hoverStartTimer)
382
- }, hoverStartTime)
383
- }
384
-
385
- const onTouchStart = (evt: NativeSyntheticEvent<TouchEvent>) => {
386
- bindtouchstart && bindtouchstart(evt)
387
- if (disabled) return
388
- setStartTimer()
389
- }
390
-
391
- const onTouchEnd = (evt: NativeSyntheticEvent<TouchEvent>) => {
392
- bindtouchend && bindtouchend(evt)
393
- if (disabled) return
394
- setStayTimer()
395
- }
396
-
397
359
  const handleFormTypeFn = () => {
398
360
  if (formType === 'submit') {
399
361
  submitFn && submitFn()
@@ -418,8 +380,6 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
418
380
  },
419
381
  layoutProps,
420
382
  {
421
- bindtouchstart: (bindtouchstart || !disabled) && onTouchStart,
422
- bindtouchend: (bindtouchend || !disabled) && onTouchEnd,
423
383
  bindtap: !disabled && onTap
424
384
  }
425
385
  ),
@@ -442,7 +402,7 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
442
402
  }
443
403
  )
444
404
 
445
- return createElement(View, innerProps, loading && createElement(Loading, { alone: !children }),
405
+ const baseButton = createElement(View, innerProps, loading && createElement(Loading, { alone: !children }),
446
406
  wrapChildren(
447
407
  props,
448
408
  {
@@ -453,6 +413,10 @@ const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((buttonPro
453
413
  }
454
414
  )
455
415
  )
416
+
417
+ return enableHoverStyle
418
+ ? createElement(GestureDetector, { gesture }, baseButton)
419
+ : baseButton
456
420
  })
457
421
 
458
422
  Button.displayName = 'MpxButton'