@mpxjs/webpack-plugin 2.9.69 → 2.9.70-alpha.1

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 (144) hide show
  1. package/README.md +1 -1
  2. package/lib/config.js +14 -0
  3. package/lib/dependencies/AddEntryDependency.js +24 -0
  4. package/lib/dependencies/ResolveDependency.js +5 -0
  5. package/lib/index.js +38 -7
  6. package/lib/json-compiler/helper.js +3 -3
  7. package/lib/loader.js +52 -0
  8. package/lib/platform/template/wx/component-config/button.js +14 -2
  9. package/lib/platform/template/wx/component-config/image.js +4 -0
  10. package/lib/platform/template/wx/component-config/input.js +5 -1
  11. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  12. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  13. package/lib/platform/template/wx/component-config/swiper.js +1 -1
  14. package/lib/platform/template/wx/component-config/switch.js +4 -0
  15. package/lib/platform/template/wx/component-config/text.js +4 -0
  16. package/lib/platform/template/wx/component-config/textarea.js +6 -1
  17. package/lib/platform/template/wx/component-config/view.js +4 -0
  18. package/lib/platform/template/wx/index.js +127 -1
  19. package/lib/react/processTemplate.js +3 -0
  20. package/lib/resolve-loader.js +4 -1
  21. package/lib/runtime/components/react/context.ts +4 -0
  22. package/lib/runtime/components/react/dist/context.js +5 -0
  23. package/lib/runtime/components/react/dist/event.config.js +24 -24
  24. package/lib/runtime/components/react/dist/getInnerListeners.js +183 -166
  25. package/lib/runtime/components/react/dist/locale-provider.jsx +15 -0
  26. package/lib/runtime/components/react/dist/mpx-button.jsx +39 -74
  27. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +30 -12
  28. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +13 -19
  29. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +29 -38
  30. package/lib/runtime/components/react/dist/mpx-form.jsx +16 -19
  31. package/lib/runtime/components/react/dist/mpx-icon.jsx +8 -16
  32. package/lib/runtime/components/react/dist/mpx-image.jsx +295 -0
  33. package/lib/runtime/components/react/dist/mpx-input.jsx +54 -27
  34. package/lib/runtime/components/react/dist/mpx-label.jsx +15 -22
  35. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +13 -16
  36. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +14 -14
  37. package/lib/runtime/components/react/dist/mpx-navigator.jsx +2 -4
  38. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +6 -2
  39. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +5 -3
  40. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +6 -2
  41. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +6 -2
  42. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +6 -2
  43. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +10 -14
  44. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +39 -0
  45. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +126 -112
  46. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +32 -29
  47. package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +23 -0
  48. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +124 -0
  49. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +40 -0
  50. package/lib/runtime/components/react/dist/mpx-portal.jsx +12 -0
  51. package/lib/runtime/components/react/dist/mpx-provider.jsx +31 -0
  52. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +11 -19
  53. package/lib/runtime/components/react/dist/mpx-radio.jsx +27 -42
  54. package/lib/runtime/components/react/dist/mpx-rich-text/html.js +39 -0
  55. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +62 -0
  56. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +7 -5
  57. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +62 -47
  58. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +11 -0
  59. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +28 -9
  60. package/lib/runtime/components/react/dist/mpx-swiper.jsx +613 -0
  61. package/lib/runtime/components/react/dist/mpx-switch.jsx +20 -10
  62. package/lib/runtime/components/react/dist/mpx-text.jsx +11 -10
  63. package/lib/runtime/components/react/dist/mpx-textarea.jsx +8 -3
  64. package/lib/runtime/components/react/dist/mpx-view.jsx +37 -89
  65. package/lib/runtime/components/react/dist/mpx-web-view.jsx +205 -46
  66. package/lib/runtime/components/react/dist/pickerFaces.js +12 -6
  67. package/lib/runtime/components/react/dist/pickerVIewContext.js +9 -0
  68. package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
  69. package/lib/runtime/components/react/dist/{pickerOverlay.jsx → pickerViewOverlay.jsx} +5 -3
  70. package/lib/runtime/components/react/dist/useAnimationHooks.js +50 -12
  71. package/lib/runtime/components/react/dist/utils.jsx +83 -28
  72. package/lib/runtime/components/react/getInnerListeners.ts +35 -28
  73. package/lib/runtime/components/react/mpx-button.tsx +55 -36
  74. package/lib/runtime/components/react/mpx-canvas/index.tsx +2 -2
  75. package/lib/runtime/components/react/mpx-checkbox-group.tsx +13 -12
  76. package/lib/runtime/components/react/mpx-checkbox.tsx +28 -28
  77. package/lib/runtime/components/react/mpx-form.tsx +10 -8
  78. package/lib/runtime/components/react/mpx-icon.tsx +10 -15
  79. package/lib/runtime/components/react/mpx-image.tsx +396 -0
  80. package/lib/runtime/components/react/mpx-input.tsx +61 -33
  81. package/lib/runtime/components/react/mpx-label.tsx +14 -13
  82. package/lib/runtime/components/react/mpx-movable-area.tsx +8 -7
  83. package/lib/runtime/components/react/mpx-movable-view.tsx +1 -1
  84. package/lib/runtime/components/react/mpx-picker/date.tsx +5 -2
  85. package/lib/runtime/components/react/mpx-picker/index.tsx +3 -2
  86. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +5 -2
  87. package/lib/runtime/components/react/mpx-picker/region.tsx +5 -2
  88. package/lib/runtime/components/react/mpx-picker/selector.tsx +5 -2
  89. package/lib/runtime/components/react/mpx-picker/time.tsx +10 -15
  90. package/lib/runtime/components/react/mpx-picker/type.ts +48 -43
  91. package/lib/runtime/components/react/mpx-picker-view-column.tsx +4 -1
  92. package/lib/runtime/components/react/mpx-picker-view.tsx +7 -1
  93. package/lib/runtime/components/react/mpx-radio-group.tsx +11 -12
  94. package/lib/runtime/components/react/mpx-radio.tsx +26 -29
  95. package/lib/runtime/components/react/mpx-scroll-view.tsx +32 -30
  96. package/lib/runtime/components/react/mpx-simple-text.tsx +18 -0
  97. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +4 -2
  98. package/lib/runtime/components/react/mpx-swiper-item.tsx +3 -2
  99. package/lib/runtime/components/react/mpx-switch.tsx +10 -8
  100. package/lib/runtime/components/react/mpx-text.tsx +6 -2
  101. package/lib/runtime/components/react/mpx-view.tsx +37 -45
  102. package/lib/runtime/components/react/mpx-web-view.tsx +25 -15
  103. package/lib/runtime/components/react/types/global.d.ts +1 -16
  104. package/lib/runtime/components/react/utils.tsx +24 -24
  105. package/lib/runtime/components/tenon/getInnerListeners.js +334 -0
  106. package/lib/runtime/components/tenon/tenon-button.vue +309 -0
  107. package/lib/runtime/components/tenon/tenon-image.vue +66 -0
  108. package/lib/runtime/components/tenon/tenon-input.vue +171 -0
  109. package/lib/runtime/components/tenon/tenon-rich-text.vue +26 -0
  110. package/lib/runtime/components/tenon/tenon-scroll-view.vue +127 -0
  111. package/lib/runtime/components/tenon/tenon-switch.vue +96 -0
  112. package/lib/runtime/components/tenon/tenon-text.vue +70 -0
  113. package/lib/runtime/components/tenon/tenon-textarea.vue +86 -0
  114. package/lib/runtime/components/tenon/tenon-view.vue +93 -0
  115. package/lib/runtime/components/web/getInnerListeners.js +6 -6
  116. package/lib/runtime/components/web/mpx-movable-view.vue +334 -344
  117. package/lib/runtime/components/web/mpx-picker-view-column.vue +75 -75
  118. package/lib/runtime/components/web/mpx-picker.vue +382 -385
  119. package/lib/runtime/components/web/mpx-web-view.vue +162 -162
  120. package/lib/runtime/optionProcessor.js +7 -16
  121. package/lib/runtime/optionProcessor.tenon.js +84 -0
  122. package/lib/runtime/utils.js +2 -0
  123. package/lib/style-compiler/index.js +1 -1
  124. package/lib/style-compiler/plugins/hm.js +20 -0
  125. package/lib/template-compiler/bind-this.js +7 -2
  126. package/lib/template-compiler/compiler.js +67 -40
  127. package/lib/template-compiler/gen-node-react.js +2 -2
  128. package/lib/tenon/index.js +112 -0
  129. package/lib/tenon/processJSON.js +352 -0
  130. package/lib/tenon/processScript.js +198 -0
  131. package/lib/tenon/processStyles.js +21 -0
  132. package/lib/tenon/processTemplate.js +125 -0
  133. package/lib/tenon/script-helper.js +223 -0
  134. package/lib/utils/env.js +6 -1
  135. package/lib/utils/get-relative-path.js +25 -0
  136. package/package.json +7 -3
  137. package/LICENSE +0 -433
  138. package/lib/runtime/components/react/dist/mpx-image/index.jsx +0 -226
  139. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +0 -7
  140. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +0 -478
  141. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +0 -68
  142. package/lib/runtime/components/react/dist/mpx-swiper/type.js +0 -1
  143. package/lib/runtime/components/react/mpx-image/index.tsx +0 -345
  144. package/lib/runtime/components/react/mpx-image/svg.tsx +0 -22
@@ -4,12 +4,12 @@
4
4
  * ✘ decode
5
5
  */
6
6
  import { Text } from 'react-native';
7
- import { useRef, forwardRef } from 'react';
7
+ import { useRef, forwardRef, createElement } from 'react';
8
8
  import useInnerProps from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef'; // 引入辅助函数
10
10
  import { useTransformStyle, wrapChildren } from './utils';
11
11
  const _Text = forwardRef((props, ref) => {
12
- const { style = {}, selectable, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'user-select': userSelect, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
12
+ const { style = {}, allowFontScaling = false, selectable, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'user-select': userSelect, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
13
  const layoutRef = useRef({});
14
14
  const { normalStyle, hasVarDec, varContextRef } = useTransformStyle(style, {
15
15
  enableVar,
@@ -19,22 +19,23 @@ const _Text = forwardRef((props, ref) => {
19
19
  parentHeight
20
20
  });
21
21
  const nodeRef = useRef(null);
22
- useNodesRef(props, ref, nodeRef);
22
+ useNodesRef(props, ref, nodeRef, {
23
+ style: normalStyle
24
+ });
23
25
  const innerProps = useInnerProps(props, {
24
26
  ref: nodeRef,
25
27
  style: normalStyle,
26
- selectable: !!selectable || !!userSelect
28
+ selectable: !!selectable || !!userSelect,
29
+ allowFontScaling
27
30
  }, [
28
31
  'user-select'
29
32
  ], {
30
33
  layoutRef
31
34
  });
32
- return (<Text {...innerProps}>
33
- {wrapChildren(props, {
34
- hasVarDec,
35
- varContext: varContextRef.current
36
- })}
37
- </Text>);
35
+ return createElement(Text, innerProps, wrapChildren(props, {
36
+ hasVarDec,
37
+ varContext: varContextRef.current
38
+ }));
38
39
  });
39
40
  _Text.displayName = 'MpxText';
40
41
  export default _Text;
@@ -9,10 +9,10 @@
9
9
  * ✘ show-confirm-bar
10
10
  * ✔ bindlinechange: No `heightRpx` info.
11
11
  */
12
- import { forwardRef } from 'react';
12
+ import { forwardRef, createElement } from 'react';
13
13
  import { Keyboard } from 'react-native';
14
14
  import Input from './mpx-input';
15
- import { omit } from './utils';
15
+ import { omit, extendObject } from './utils';
16
16
  const Textarea = forwardRef((props, ref) => {
17
17
  const restProps = omit(props, [
18
18
  'ref',
@@ -21,7 +21,12 @@ const Textarea = forwardRef((props, ref) => {
21
21
  'multiline',
22
22
  'confirm-hold'
23
23
  ]);
24
- return (<Input ref={ref} multiline confirm-type='next' bindblur={() => Keyboard.dismiss()} {...restProps}/>);
24
+ return createElement(Input, extendObject({
25
+ ref: ref,
26
+ multiline: true,
27
+ confirmType: 'next',
28
+ bindblur: () => Keyboard.dismiss()
29
+ }, restProps));
25
30
  });
26
31
  Textarea.displayName = 'MpxTextarea';
27
32
  export default Textarea;
@@ -5,13 +5,15 @@
5
5
  * ✔ hover-stay-time
6
6
  */
7
7
  import { View, StyleSheet, Image } from 'react-native';
8
- import { useRef, useState, useEffect, forwardRef } from 'react';
8
+ import { useRef, useState, useEffect, forwardRef, createElement } from 'react';
9
9
  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 } from './utils';
13
+ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle, extendObject, useHoverStyle } from './utils';
14
+ import { error } from '@mpxjs/utils';
14
15
  import LinearGradient from 'react-native-linear-gradient';
16
+ import { GestureDetector } from 'react-native-gesture-handler';
15
17
  const linearMap = new Map([
16
18
  ['top', 0],
17
19
  ['bottom', 180],
@@ -148,10 +150,7 @@ function backgroundPosition(imageProps, preImageInfo, imageSize, layoutInfo) {
148
150
  style[key] = val;
149
151
  }
150
152
  }
151
- imageProps.style = {
152
- ...imageProps.style,
153
- ...style
154
- };
153
+ extendObject(imageProps.style, style);
155
154
  }
156
155
  // background-size 转换
157
156
  function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
@@ -209,10 +208,7 @@ function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
209
208
  }
210
209
  }
211
210
  // 样式合并
212
- imageProps.style = {
213
- ...imageProps.style,
214
- ...dimensions
215
- };
211
+ extendObject(imageProps.style, dimensions);
216
212
  }
217
213
  // background-image转换为source
218
214
  function backgroundImage(imageProps, preImageInfo) {
@@ -385,10 +381,9 @@ function parseLinearGradient(text) {
385
381
  !isNaN(numberVal) && locations.push(numberVal);
386
382
  return prev;
387
383
  }, { colors: [], locations: [] });
388
- return {
389
- ...linearInfo,
384
+ return extendObject({}, linearInfo, {
390
385
  direction: direction.trim()
391
- };
386
+ });
392
387
  }
393
388
  function parseBgImage(text) {
394
389
  if (!text)
@@ -533,6 +528,11 @@ function wrapImage(imageStyle, innerStyle, enableFastImage) {
533
528
  </View>;
534
529
  }
535
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
536
  const children = wrapChildren(props, {
537
537
  hasVarDec,
538
538
  varContext,
@@ -546,23 +546,18 @@ function wrapWithChildren(props, { hasVarDec, enableBackground, textStyle, backg
546
546
  }
547
547
  const _View = forwardRef((viewProps, ref) => {
548
548
  const { textProps, innerProps: props = {} } = splitProps(viewProps);
549
- 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
- const [isHover, setIsHover] = useState(false);
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;
551
550
  // 默认样式
552
- const defaultStyle = {
553
- // flex 布局相关的默认样式
554
- ...style.display === 'flex' && {
551
+ const defaultStyle = style.display === 'flex'
552
+ ? {
555
553
  flexDirection: 'row',
556
554
  flexBasis: 'auto',
557
555
  flexShrink: 1,
558
556
  flexWrap: 'nowrap'
559
557
  }
560
- };
561
- const styleObj = {
562
- ...defaultStyle,
563
- ...style,
564
- ...(isHover ? hoverStyle : null)
565
- };
558
+ : {};
559
+ const { isHover, enableHoverStyle, gesture } = useHoverStyle({ hoverStyle, hoverStartTime, hoverStayTime });
560
+ const styleObj = extendObject({}, defaultStyle, style, isHover ? hoverStyle : {});
566
561
  const { normalStyle, hasSelfPercent, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
567
562
  enableVar,
568
563
  externalVarContext,
@@ -570,68 +565,22 @@ const _View = forwardRef((viewProps, ref) => {
570
565
  parentWidth,
571
566
  parentHeight
572
567
  });
573
- const { textStyle, backgroundStyle, innerStyle } = splitStyle(normalStyle);
574
- enableBackground = enableBackground || !!backgroundStyle;
575
- const enableBackgroundRef = useRef(enableBackground);
576
- if (enableBackgroundRef.current !== enableBackground) {
577
- throw new Error('[Mpx runtime error]: background use should be stable in the component lifecycle, or you can set [enable-background] with true.');
578
- }
568
+ const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle);
579
569
  const nodeRef = useRef(null);
580
570
  useNodesRef(props, ref, nodeRef, {
581
- defaultStyle
571
+ style: normalStyle
582
572
  });
583
- const dataRef = useRef({});
584
- useEffect(() => {
585
- return () => {
586
- dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
587
- dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
588
- };
589
- }, []);
590
- const setStartTimer = () => {
591
- dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
592
- dataRef.current.startTimer = setTimeout(() => {
593
- setIsHover(true);
594
- }, +hoverStartTime);
595
- };
596
- const setStayTimer = () => {
597
- dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
598
- dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
599
- dataRef.current.stayTimer = setTimeout(() => {
600
- setIsHover(false);
601
- }, +hoverStayTime);
602
- };
603
- function onTouchStart(e) {
604
- const { bindtouchstart } = props;
605
- bindtouchstart && bindtouchstart(e);
606
- setStartTimer();
607
- }
608
- function onTouchEnd(e) {
609
- const { bindtouchend } = props;
610
- bindtouchend && bindtouchend(e);
611
- setStayTimer();
612
- }
613
573
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
614
- const viewStyle = Object.assign({}, innerStyle, layoutStyle);
615
- enableAnimation = enableAnimation || !!animation;
616
- const enableAnimationRef = useRef(enableAnimation);
617
- if (enableAnimationRef.current !== enableAnimation) {
618
- throw new Error('[Mpx runtime error]: animation use should be stable in the component lifecycle, or you can set [enable-animation] with true.');
619
- }
620
- const finalStyle = enableAnimation
621
- ? useAnimationHooks({
622
- animation,
623
- style: viewStyle
624
- })
625
- : viewStyle;
626
- const innerProps = useInnerProps(props, {
574
+ const viewStyle = extendObject({}, innerStyle, layoutStyle);
575
+ const { enableStyleAnimation, animationStyle } = useAnimationHooks({
576
+ enableAnimation,
577
+ animation,
578
+ style: viewStyle
579
+ });
580
+ const innerProps = useInnerProps(props, extendObject({
627
581
  ref: nodeRef,
628
- style: finalStyle,
629
- ...layoutProps,
630
- ...(hoverStyle && {
631
- bindtouchstart: onTouchStart,
632
- bindtouchend: onTouchEnd
633
- })
634
- }, [
582
+ style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
583
+ }, layoutProps), [
635
584
  'hover-start-time',
636
585
  'hover-stay-time',
637
586
  'hover-style',
@@ -641,7 +590,7 @@ const _View = forwardRef((viewProps, ref) => {
641
590
  });
642
591
  const childNode = wrapWithChildren(props, {
643
592
  hasVarDec,
644
- enableBackground: enableBackgroundRef.current,
593
+ enableBackground,
645
594
  textStyle,
646
595
  backgroundStyle,
647
596
  varContext: varContextRef.current,
@@ -649,13 +598,12 @@ const _View = forwardRef((viewProps, ref) => {
649
598
  innerStyle,
650
599
  enableFastImage
651
600
  });
652
- return enableAnimation
653
- ? (<Animated.View {...innerProps}>
654
- {childNode}
655
- </Animated.View>)
656
- : (<View {...innerProps}>
657
- {childNode}
658
- </View>);
601
+ const BaseComponent = enableStyleAnimation
602
+ ? createElement(Animated.View, innerProps, childNode)
603
+ : createElement(View, innerProps, childNode);
604
+ return enableHoverStyle
605
+ ? createElement(GestureDetector, { gesture }, BaseComponent)
606
+ : BaseComponent;
659
607
  });
660
608
  _View.displayName = 'MpxView';
661
609
  export default _View;
@@ -1,19 +1,58 @@
1
- import { forwardRef, useEffect, useRef, useContext, useMemo } from 'react';
2
- import { noop, warn } 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, getFocusedNavigation, 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 } from './utils';
8
+ import { getCurrentPage, extendObject } from './utils';
9
9
  import { RouteContext } from './context';
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
+ });
10
35
  const _WebView = forwardRef((props, ref) => {
11
- const { src = '', bindmessage = noop, bindload = noop, binderror = noop } = props;
36
+ const { src, bindmessage, bindload, binderror } = props;
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'];
12
49
  if (props.style) {
13
50
  warn('The web-view component does not support the style prop.');
14
51
  }
15
52
  const pageId = useContext(RouteContext);
53
+ const [pageLoadErr, setPageLoadErr] = useState(false);
16
54
  const currentPage = useMemo(() => getCurrentPage(pageId), [pageId]);
55
+ const webViewRef = useRef(null);
17
56
  const defaultWebViewStyle = {
18
57
  position: 'absolute',
19
58
  left: 0,
@@ -21,31 +60,58 @@ const _WebView = forwardRef((props, ref) => {
21
60
  top: 0,
22
61
  bottom: 0
23
62
  };
24
- const webViewRef = useRef(null);
25
- useNodesRef(props, ref, webViewRef, {
26
- defaultStyle: defaultWebViewStyle
27
- });
28
- const _messageList = useRef([]);
29
- const handleUnload = () => {
30
- // 这里是 WebView 销毁前执行的逻辑
31
- bindmessage(getCustomEvent('messsage', {}, {
32
- detail: {
33
- data: _messageList.current
34
- },
35
- layoutRef: webViewRef
36
- }));
37
- };
38
- useEffect(() => {
39
- if (currentPage) {
40
- currentPage.__webViewUrl = src;
63
+ const canGoBack = useRef(false);
64
+ const onAndroidBackPress = useCallback(() => {
65
+ if (canGoBack.current) {
66
+ webViewRef.current?.goBack();
67
+ return true;
68
+ }
69
+ return false;
70
+ }, [canGoBack]);
71
+ const beforeRemoveHandle = useCallback((e) => {
72
+ if (canGoBack.current) {
73
+ webViewRef.current?.goBack();
74
+ e.preventDefault();
75
+ }
76
+ }, [canGoBack]);
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) {
41
94
  }
42
- }, [src, currentPage]);
95
+ })()`;
96
+ }
97
+ return '';
98
+ }, [hashParams]);
99
+ navigation?.addListener('beforeRemove', beforeRemoveHandle);
43
100
  useEffect(() => {
44
- // 组件卸载时执行
45
- return () => {
46
- handleUnload();
47
- };
101
+ if (__mpx_mode__ === 'android') {
102
+ BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
103
+ return () => {
104
+ BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
105
+ navigation?.removeListener('beforeRemove', beforeRemoveHandle);
106
+ };
107
+ }
48
108
  }, []);
109
+ useNodesRef(props, ref, webViewRef, {
110
+ style: defaultWebViewStyle
111
+ });
112
+ if (!src) {
113
+ return null;
114
+ }
49
115
  const _load = function (res) {
50
116
  const result = {
51
117
  type: 'load',
@@ -54,9 +120,10 @@ const _WebView = forwardRef((props, ref) => {
54
120
  src: res.nativeEvent?.url
55
121
  }
56
122
  };
57
- bindload(result);
123
+ bindload?.(result);
58
124
  };
59
125
  const _error = function (res) {
126
+ setPageLoadErr(true);
60
127
  const result = {
61
128
  type: 'error',
62
129
  timeStamp: res.timeStamp,
@@ -64,13 +131,55 @@ const _WebView = forwardRef((props, ref) => {
64
131
  src: ''
65
132
  }
66
133
  };
67
- binderror(result);
134
+ binderror && binderror(result);
135
+ };
136
+ const _reload = function () {
137
+ setPageLoadErr(false);
138
+ };
139
+ const injectedJavaScript = `
140
+ if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
141
+ var _documentTitle = document.title;
142
+ window.ReactNativeWebView.postMessage(JSON.stringify({
143
+ type: 'setTitle',
144
+ payload: {
145
+ _documentTitle: _documentTitle
146
+ }
147
+ }))
148
+ Object.defineProperty(document, 'title', {
149
+ set (val) {
150
+ _documentTitle = val
151
+ window.ReactNativeWebView.postMessage(JSON.stringify({
152
+ type: 'setTitle',
153
+ payload: {
154
+ _documentTitle: _documentTitle
155
+ }
156
+ }))
157
+ },
158
+ get () {
159
+ return _documentTitle
160
+ }
161
+ });
162
+ ${hashInjectedJavascript}
163
+ }
164
+ true;
165
+ `;
166
+ const sendMessage = function (params) {
167
+ return `
168
+ window.mpxWebviewMessageCallback(${params})
169
+ true;
170
+ `;
68
171
  };
69
172
  const _changeUrl = function (navState) {
70
- if (currentPage) {
173
+ if (navState.navigationType) { // navigationType这个事件在页面开始加载时和页面加载完成时都会被触发所以判断这个避免其他无效触发执行该逻辑
174
+ canGoBack.current = navState.canGoBack;
71
175
  currentPage.__webViewUrl = navState.url;
72
176
  }
73
177
  };
178
+ const _onLoadProgress = function (event) {
179
+ if (__mpx_mode__ === 'android') {
180
+ canGoBack.current = event.nativeEvent.canGoBack;
181
+ }
182
+ };
74
183
  const _message = function (res) {
75
184
  let data = {};
76
185
  let asyncCallback;
@@ -81,47 +190,97 @@ const _WebView = forwardRef((props, ref) => {
81
190
  data = JSON.parse(nativeEventData);
82
191
  }
83
192
  }
84
- catch (e) {
85
- data = {};
86
- }
193
+ catch (e) { }
194
+ const args = data.args;
87
195
  const postData = data.payload || {};
88
- switch (data.type) {
196
+ const params = Array.isArray(args) ? args : [postData];
197
+ const type = data.type;
198
+ switch (type) {
199
+ case 'setTitle':
200
+ { // case下不允许直接声明,包个块解决该问题
201
+ const title = postData._documentTitle;
202
+ if (title) {
203
+ navigation && navigation.setOptions({ title });
204
+ }
205
+ }
206
+ break;
89
207
  case 'postMessage':
90
- _messageList.current.push(postData.data);
208
+ bindmessage && bindmessage(getCustomEvent('messsage', {}, {
209
+ detail: {
210
+ data: params[0]?.data
211
+ }
212
+ }));
91
213
  asyncCallback = Promise.resolve({
92
214
  errMsg: 'invokeWebappApi:ok'
93
215
  });
94
216
  break;
95
217
  case 'navigateTo':
96
- asyncCallback = navObj.navigateTo(postData);
218
+ asyncCallback = navObj.navigateTo(...params);
97
219
  break;
98
220
  case 'navigateBack':
99
- asyncCallback = navObj.navigateBack(postData);
221
+ asyncCallback = navObj.navigateBack(...params);
100
222
  break;
101
223
  case 'redirectTo':
102
- asyncCallback = navObj.redirectTo(postData);
224
+ asyncCallback = navObj.redirectTo(...params);
103
225
  break;
104
226
  case 'switchTab':
105
- asyncCallback = navObj.switchTab(postData);
227
+ asyncCallback = navObj.switchTab(...params);
106
228
  break;
107
229
  case 'reLaunch':
108
- asyncCallback = navObj.reLaunch(postData);
230
+ asyncCallback = navObj.reLaunch(...params);
231
+ break;
232
+ default:
233
+ if (type) {
234
+ const implement = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations[type];
235
+ if (isFunction(implement)) {
236
+ asyncCallback = Promise.resolve(implement(...params));
237
+ }
238
+ else {
239
+ /* eslint-disable prefer-promise-reject-errors */
240
+ asyncCallback = Promise.reject({
241
+ errMsg: `未在apiImplementations中配置${type}方法`
242
+ });
243
+ }
244
+ }
109
245
  break;
110
246
  }
111
247
  asyncCallback && asyncCallback.then((res) => {
112
248
  if (webViewRef.current?.postMessage) {
113
- const test = JSON.stringify({
114
- type: data.type,
249
+ const result = JSON.stringify({
250
+ type,
115
251
  callbackId: data.callbackId,
116
252
  result: res
117
253
  });
118
- webViewRef.current.postMessage(test);
254
+ webViewRef.current.injectJavaScript(sendMessage(result));
255
+ }
256
+ }).catch((error) => {
257
+ if (webViewRef.current?.postMessage) {
258
+ const result = JSON.stringify({
259
+ type,
260
+ callbackId: data.callbackId,
261
+ error
262
+ });
263
+ webViewRef.current.injectJavaScript(sendMessage(result));
119
264
  }
120
265
  });
121
266
  };
122
- return (<Portal>
123
- <WebView style={defaultWebViewStyle} source={{ uri: src }} ref={webViewRef} onLoad={_load} onError={_error} onMessage={_message} onNavigationStateChange={_changeUrl} javaScriptEnabled={true}></WebView>
124
- </Portal>);
267
+ const events = {};
268
+ if (bindload) {
269
+ extendObject(events, {
270
+ onLoad: _load
271
+ });
272
+ }
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>);
125
284
  });
126
285
  _WebView.displayName = 'MpxWebview';
127
286
  export default _WebView;
@@ -30,6 +30,9 @@ 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
+ }
33
36
  return offset;
34
37
  });
35
38
  return [screenHeights, offsets];
@@ -37,15 +40,16 @@ export const createFaces = (itemHeight, visibleCount) => {
37
40
  const getOpacity = (index) => {
38
41
  const map = {
39
42
  0: 0,
40
- 1: 0.2,
41
- 2: 0.35,
42
- 3: 0.45,
43
- 4: 0.5
43
+ 1: 0.8,
44
+ 2: 0.9 // 0.35
45
+ // 3: 0.45, // 0.45
46
+ // 4: 0.5 // 0.5
44
47
  };
45
- return map[index] ?? Math.min(1, map[4] + index * 0.5);
48
+ return map[index] ?? Math.min(1, map[2] + index * 0.05);
46
49
  };
47
50
  const degrees = getDegreesRelativeCenter();
48
51
  const [screenHeight, offsets] = getScreenHeightsAndOffsets(degrees);
52
+ const scales = [0.973, 0.9, 0.8];
49
53
  return [
50
54
  // top items
51
55
  ...degrees
@@ -55,12 +59,13 @@ export const createFaces = (itemHeight, visibleCount) => {
55
59
  deg: degree,
56
60
  opacity: getOpacity(degrees.length - 1 - index),
57
61
  offsetY: -1 * offsets[index],
62
+ scale: scales[index],
58
63
  screenHeight: screenHeight[index]
59
64
  };
60
65
  })
61
66
  .reverse(),
62
67
  // center item
63
- { index: 0, deg: 0, opacity: 1, offsetY: 0, screenHeight: itemHeight },
68
+ { index: 0, deg: 0, opacity: 1, offsetY: 0, scale: 1, screenHeight: itemHeight },
64
69
  // bottom items
65
70
  ...degrees.map((degree, index) => {
66
71
  return {
@@ -68,6 +73,7 @@ export const createFaces = (itemHeight, visibleCount) => {
68
73
  deg: -1 * degree,
69
74
  opacity: getOpacity(degrees.length - 1 - index),
70
75
  offsetY: offsets[index],
76
+ scale: scales[index],
71
77
  screenHeight: screenHeight[index]
72
78
  };
73
79
  })
@@ -0,0 +1,9 @@
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
+ };