@mpxjs/webpack-plugin 2.10.3-beta.17 → 2.10.3-beta.19

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 (68) hide show
  1. package/lib/runtime/components/react/dist/context.js +5 -1
  2. package/lib/runtime/components/react/dist/event.config.js +0 -1
  3. package/lib/runtime/components/react/dist/getInnerListeners.js +148 -149
  4. package/lib/runtime/components/react/dist/mpx-async-suspense.jsx +145 -0
  5. package/lib/runtime/components/react/dist/mpx-button.jsx +11 -7
  6. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +2 -4
  7. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +23 -21
  8. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +9 -4
  9. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +9 -5
  10. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -2
  11. package/lib/runtime/components/react/dist/mpx-icon/icons/cancel.png +0 -0
  12. package/lib/runtime/components/react/dist/mpx-icon/icons/clear.png +0 -0
  13. package/lib/runtime/components/react/dist/mpx-icon/icons/download.png +0 -0
  14. package/lib/runtime/components/react/dist/mpx-icon/icons/info.png +0 -0
  15. package/lib/runtime/components/react/dist/mpx-icon/icons/search.png +0 -0
  16. package/lib/runtime/components/react/dist/mpx-icon/icons/success.png +0 -0
  17. package/lib/runtime/components/react/dist/mpx-icon/icons/success_no_circle.png +0 -0
  18. package/lib/runtime/components/react/dist/mpx-icon/icons/waiting.png +0 -0
  19. package/lib/runtime/components/react/dist/mpx-icon/icons/warn.png +0 -0
  20. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +9 -4
  21. package/lib/runtime/components/react/dist/mpx-image.jsx +92 -41
  22. package/lib/runtime/components/react/dist/mpx-inline-text.jsx +11 -0
  23. package/lib/runtime/components/react/dist/mpx-input.jsx +14 -13
  24. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +22 -7
  25. package/lib/runtime/components/react/dist/mpx-label.jsx +9 -5
  26. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +10 -5
  27. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +206 -80
  28. package/lib/runtime/components/react/dist/mpx-navigator.jsx +11 -3
  29. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +194 -68
  30. package/lib/runtime/components/react/dist/mpx-picker/dateData.js +17 -0
  31. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +178 -98
  32. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +79 -139
  33. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +190 -90
  34. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +60 -75
  35. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +100 -228
  36. package/lib/runtime/components/react/dist/{mpx-picker-view.jsx → mpx-picker-view/index.jsx} +16 -15
  37. package/lib/runtime/components/react/dist/{mpx-picker-view-column.jsx → mpx-picker-view-column/index.jsx} +95 -26
  38. package/lib/runtime/components/react/dist/{mpx-picker-view-column-item.jsx → mpx-picker-view-column/pickerViewColumnItem.jsx} +16 -16
  39. package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.jsx +20 -0
  40. package/lib/runtime/components/react/dist/{pickerFaces.js → mpx-picker-view-column/pickerViewFaces.js} +6 -0
  41. package/lib/runtime/components/react/dist/mpx-popup/index.jsx +61 -0
  42. package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +92 -0
  43. package/lib/runtime/components/react/dist/mpx-portal/index.jsx +5 -1
  44. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +3 -5
  45. package/lib/runtime/components/react/dist/mpx-progress.jsx +163 -0
  46. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +11 -4
  47. package/lib/runtime/components/react/dist/mpx-radio.jsx +9 -5
  48. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +12 -4
  49. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +317 -89
  50. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +7 -5
  51. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +11 -15
  52. package/lib/runtime/components/react/dist/mpx-slider.jsx +321 -0
  53. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +117 -0
  54. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  55. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +15 -14
  56. package/lib/runtime/components/react/dist/mpx-swiper.jsx +245 -121
  57. package/lib/runtime/components/react/dist/mpx-switch.jsx +10 -7
  58. package/lib/runtime/components/react/dist/mpx-text.jsx +43 -13
  59. package/lib/runtime/components/react/dist/mpx-video.jsx +12 -7
  60. package/lib/runtime/components/react/dist/mpx-view.jsx +34 -18
  61. package/lib/runtime/components/react/dist/mpx-web-view.jsx +40 -35
  62. package/lib/runtime/components/react/dist/useAnimationHooks.js +38 -91
  63. package/lib/runtime/components/react/dist/utils.jsx +215 -109
  64. package/lib/runtime/components/web/mpx-titlebar.vue +23 -18
  65. package/package.json +1 -1
  66. /package/lib/runtime/components/react/dist/{pickerVIewContext.js → mpx-picker-view/pickerVIewContext.js} +0 -0
  67. /package/lib/runtime/components/react/dist/{pickerViewIndicator.jsx → mpx-picker-view-column/pickerViewIndicator.jsx} +0 -0
  68. /package/lib/runtime/components/react/dist/{pickerViewMask.jsx → mpx-picker-view-column/pickerViewMask.jsx} +0 -0
@@ -23,6 +23,7 @@ import './CanvasGradient';
23
23
  import { createImage as canvasCreateImage } from './Image';
24
24
  import { createImageData as canvasCreateImageData } from './ImageData';
25
25
  import { useConstructorsRegistry } from './constructorsRegistry';
26
+ import Portal from '../mpx-portal';
26
27
  const stylesheet = StyleSheet.create({
27
28
  container: { overflow: 'hidden', flex: 0 },
28
29
  webview: {
@@ -41,7 +42,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
41
42
  const { style = {}, originWhitelist = ['*'], 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
42
43
  const [isLoaded, setIsLoaded] = useState(false);
43
44
  const nodeRef = useRef(null);
44
- const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(extendObject({}, style, stylesheet.container), {
45
+ const { normalStyle, hasSelfPercent, hasPositionFixed, setWidth, setHeight } = useTransformStyle(extendObject({}, style, stylesheet.container), {
45
46
  enableVar,
46
47
  externalVarContext,
47
48
  parentFontSize,
@@ -56,11 +57,10 @@ const _Canvas = forwardRef((props = {}, ref) => {
56
57
  });
57
58
  const { register } = useConstructorsRegistry();
58
59
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
59
- const innerProps = useInnerProps(props, {
60
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
60
61
  ref: nodeRef,
61
- style: extendObject({}, normalStyle, layoutStyle, { opacity: isLoaded ? 1 : 0 }),
62
- ...layoutProps
63
- }, [], {
62
+ style: extendObject({}, normalStyle, layoutStyle, { opacity: isLoaded ? 1 : 0 })
63
+ }), [], {
64
64
  layoutRef
65
65
  });
66
66
  const context2D = new CanvasRenderingContext2D(canvasRef.current);
@@ -111,10 +111,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
111
111
  const postMessage = useCallback(async (message) => {
112
112
  if (!canvasRef.current?.bus)
113
113
  return;
114
- const { type, payload } = await canvasRef.current.bus.post({
115
- id: ID(),
116
- ...message
117
- });
114
+ const { type, payload } = await canvasRef.current.bus.post(extendObject({ id: ID() }, message));
118
115
  switch (type) {
119
116
  case 'error': {
120
117
  const { binderror } = props;
@@ -143,7 +140,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
143
140
  canvasRef.current.listeners.splice(canvasRef.current.listeners.indexOf(listener), 1);
144
141
  };
145
142
  const onMessage = useCallback((e) => {
146
- let data = JSON.parse(e.nativeEvent.data);
143
+ const data = JSON.parse(e.nativeEvent.data);
147
144
  switch (data.type) {
148
145
  case 'error': {
149
146
  const { binderror } = props;
@@ -157,27 +154,27 @@ const _Canvas = forwardRef((props = {}, ref) => {
157
154
  break;
158
155
  }
159
156
  default: {
157
+ const newData = {};
158
+ // createLinearGradient 方法调用需要在 constructors 中需要注册 CanvasGradient
159
+ const constructor = constructors[data.meta.constructor];
160
160
  if (data.payload) {
161
- // createLinearGradient 方法调用需要在 constructors 中需要注册 CanvasGradient
162
- const constructor = constructors[data.meta.constructor];
163
161
  if (constructor) {
164
162
  const { args, payload } = data;
165
163
  // RN 端同步生成一个 CanvasGradient 的实例
166
164
  const object = constructor.constructLocally(canvasRef.current, ...args);
167
- Object.assign(object, payload, {
165
+ extendObject(object, payload, {
168
166
  [WEBVIEW_TARGET]: data.meta.target
169
167
  });
170
- data = {
171
- ...data,
168
+ extendObject(newData, data, {
172
169
  payload: object
173
- };
170
+ });
174
171
  }
175
172
  for (const listener of canvasRef.current.listeners) {
176
- listener(data.payload);
173
+ listener(constructor ? newData.payload : data.payload);
177
174
  }
178
175
  }
179
176
  if (canvasRef.current.bus) {
180
- canvasRef.current.bus.handle(data);
177
+ canvasRef.current.bus.handle(constructor && data.payload ? newData : data);
181
178
  }
182
179
  }
183
180
  }
@@ -193,9 +190,10 @@ const _Canvas = forwardRef((props = {}, ref) => {
193
190
  node: canvasRef.current,
194
191
  context: context2D
195
192
  });
196
- if (Platform.OS === 'android') {
193
+ let canvasComponent;
194
+ if (__mpx_mode__ === 'android') {
197
195
  const isAndroid9 = Platform.Version >= 28;
198
- return createElement(View, innerProps, createElement(WebView, {
196
+ canvasComponent = createElement(View, innerProps, createElement(WebView, {
199
197
  ref: (element) => {
200
198
  if (canvasRef.current) {
201
199
  canvasRef.current.webview = element;
@@ -218,7 +216,7 @@ const _Canvas = forwardRef((props = {}, ref) => {
218
216
  allowUniversalAccessFromFileURLs: true
219
217
  }));
220
218
  }
221
- return createElement(View, innerProps, createElement(WebView, {
219
+ canvasComponent = createElement(View, innerProps, createElement(WebView, {
222
220
  ref: (element) => {
223
221
  if (canvasRef.current) {
224
222
  canvasRef.current.webview = element;
@@ -231,6 +229,10 @@ const _Canvas = forwardRef((props = {}, ref) => {
231
229
  onLoad: onLoad,
232
230
  scrollEnabled: false
233
231
  }));
232
+ if (hasPositionFixed) {
233
+ canvasComponent = createElement(Portal, null, canvasComponent);
234
+ }
235
+ return canvasComponent;
234
236
  });
235
237
  _Canvas.displayName = 'mpxCanvas';
236
238
  export default _Canvas;
@@ -8,6 +8,7 @@ import { FormContext, CheckboxGroupContext } from './context';
8
8
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef';
10
10
  import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
11
+ import Portal from './mpx-portal';
11
12
  const CheckboxGroup = forwardRef((props, ref) => {
12
13
  const propsRef = useRef({});
13
14
  propsRef.current = props;
@@ -23,7 +24,7 @@ const CheckboxGroup = forwardRef((props, ref) => {
23
24
  flexWrap: 'wrap'
24
25
  };
25
26
  const styleObj = extendObject({}, defaultStyle, style);
26
- const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
27
+ const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
27
28
  const nodeRef = useRef(null);
28
29
  useNodesRef(props, ref, nodeRef, { style: normalStyle });
29
30
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
@@ -57,10 +58,10 @@ const CheckboxGroup = forwardRef((props, ref) => {
57
58
  }
58
59
  };
59
60
  }, []);
60
- const innerProps = useInnerProps(props, extendObject({
61
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
61
62
  ref: nodeRef,
62
63
  style: extendObject({}, normalStyle, layoutStyle)
63
- }, layoutProps), [
64
+ }), [
64
65
  'name'
65
66
  ], {
66
67
  layoutRef
@@ -81,10 +82,14 @@ const CheckboxGroup = forwardRef((props, ref) => {
81
82
  notifyChange
82
83
  };
83
84
  }, []);
84
- return createElement(View, innerProps, createElement(CheckboxGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
85
+ const finalComponent = createElement(View, innerProps, createElement(CheckboxGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
85
86
  hasVarDec,
86
87
  varContext: varContextRef.current
87
88
  })));
89
+ if (hasPositionFixed) {
90
+ return createElement(Portal, null, finalComponent);
91
+ }
92
+ return finalComponent;
88
93
  });
89
94
  CheckboxGroup.displayName = 'MpxCheckboxGroup';
90
95
  export default CheckboxGroup;
@@ -12,6 +12,7 @@ import useNodesRef from './useNodesRef';
12
12
  import Icon from './mpx-icon';
13
13
  import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
14
14
  import { CheckboxGroupContext, LabelContext } from './context';
15
+ import Portal from './mpx-portal';
15
16
  const styles = StyleSheet.create({
16
17
  container: {
17
18
  flexDirection: 'row',
@@ -63,7 +64,7 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
63
64
  bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props));
64
65
  onChange(evt);
65
66
  };
66
- const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
67
+ const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
67
68
  const nodeRef = useRef(null);
68
69
  useNodesRef(props, ref, nodeRef, {
69
70
  style: extendObject({}, defaultStyle, normalStyle),
@@ -82,10 +83,9 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
82
83
  if (labelContext) {
83
84
  labelContext.current.triggerChange = onChange;
84
85
  }
85
- const innerProps = useInnerProps(props, extendObject({
86
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
86
87
  ref: nodeRef,
87
- style: extendObject({}, innerStyle, layoutStyle)
88
- }, layoutProps, {
88
+ style: extendObject({}, innerStyle, layoutStyle),
89
89
  bindtap: !disabled && onTap
90
90
  }), [
91
91
  'value',
@@ -115,7 +115,7 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
115
115
  }
116
116
  }
117
117
  }, [checked]);
118
- return createElement(View, innerProps, createElement(View, { style: defaultStyle }, createElement(Icon, {
118
+ const finalComponent = createElement(View, innerProps, createElement(View, { style: defaultStyle }, createElement(Icon, {
119
119
  type: 'success_no_circle',
120
120
  size: 18,
121
121
  color: disabled ? '#ADADAD' : color,
@@ -126,6 +126,10 @@ const Checkbox = forwardRef((checkboxProps, ref) => {
126
126
  textStyle,
127
127
  textProps
128
128
  }));
129
+ if (hasPositionFixed) {
130
+ return createElement(Portal, null, finalComponent);
131
+ }
132
+ return finalComponent;
129
133
  });
130
134
  Checkbox.displayName = 'MpxCheckbox';
131
135
  export default Checkbox;
@@ -22,10 +22,10 @@ const _Form = forwardRef((fromProps, ref) => {
22
22
  const propsRef = useRef({});
23
23
  propsRef.current = props;
24
24
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: formRef });
25
- const innerProps = useInnerProps(props, extendObject({
25
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
26
26
  style: extendObject({}, innerStyle, layoutStyle),
27
27
  ref: formRef
28
- }, layoutProps), [
28
+ }), [
29
29
  'bindsubmit',
30
30
  'bindreset'
31
31
  ], { layoutRef });
@@ -17,6 +17,7 @@ import Cancel from './icons/cancel.png';
17
17
  import Download from './icons/download.png';
18
18
  import Search from './icons/search.png';
19
19
  import Clear from './icons/clear.png';
20
+ import Portal from '../mpx-portal';
20
21
  const IconTypeMap = new Map([
21
22
  ['success', Success],
22
23
  ['success_no_circle', SuccessNoCircle],
@@ -33,18 +34,22 @@ const Icon = forwardRef((props, ref) => {
33
34
  const source = IconTypeMap.get(type);
34
35
  const defaultStyle = { width: ~~size, height: ~~size };
35
36
  const styleObj = extendObject({}, defaultStyle, style);
36
- const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
37
+ const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
37
38
  const nodeRef = useRef(null);
38
39
  useNodesRef(props, ref, nodeRef, { style: normalStyle });
39
40
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
40
- const innerProps = useInnerProps(props, extendObject({
41
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
41
42
  ref: nodeRef,
42
43
  source,
43
44
  style: extendObject({}, normalStyle, layoutStyle, { tintColor: color })
44
- }, layoutProps), [], {
45
+ }), [], {
45
46
  layoutRef
46
47
  });
47
- return createElement(Image, innerProps);
48
+ const finalComponent = createElement(Image, innerProps);
49
+ if (hasPositionFixed) {
50
+ return createElement(Portal, null, finalComponent);
51
+ }
52
+ return finalComponent;
48
53
  });
49
54
  Icon.displayName = 'MpxIcon';
50
55
  export default Icon;
@@ -17,6 +17,7 @@ import { SvgCssUri } from 'react-native-svg/css';
17
17
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
18
18
  import useNodesRef from './useNodesRef';
19
19
  import { SVG_REGEXP, useLayout, useTransformStyle, renderImage, extendObject } from './utils';
20
+ import Portal from './mpx-portal';
20
21
  const DEFAULT_IMAGE_WIDTH = 320;
21
22
  const DEFAULT_IMAGE_HEIGHT = 240;
22
23
  const cropMode = [
@@ -39,7 +40,16 @@ const ModeMap = new Map([
39
40
  ...cropMode.map(mode => [mode, 'stretch'])
40
41
  ]);
41
42
  const isNumber = (value) => typeof value === 'number';
42
- const relativeCenteredSize = (viewSize, imageSize) => (viewSize - imageSize) / 2;
43
+ const relativeCenteredSize = (viewSize, imageSize) => {
44
+ return (viewSize - imageSize) / 2;
45
+ };
46
+ // 获取能完全显示图片的缩放比例:长宽方向的缩放比例最小值即为能完全展示的比例
47
+ function getFitScale(width1, height1, width2, height2) {
48
+ return Math.min(width2 / width1, height2 / height1);
49
+ }
50
+ function getFillScale(width1, height1, width2, height2) {
51
+ return Math.max(width2 / width1, height2 / height1);
52
+ }
43
53
  function noMeetCalcRule(isSvg, mode, viewWidth, viewHeight, ratio) {
44
54
  const isMeetSize = viewWidth && viewHeight && ratio;
45
55
  if (isSvg && !isMeetSize)
@@ -48,6 +58,16 @@ function noMeetCalcRule(isSvg, mode, viewWidth, viewHeight, ratio) {
48
58
  return true;
49
59
  return false;
50
60
  }
61
+ const getFixedWidth = (viewWidth, viewHeight, ratio) => {
62
+ if (!ratio)
63
+ return viewWidth;
64
+ const fixed = viewHeight / ratio;
65
+ return !fixed ? viewWidth : fixed;
66
+ };
67
+ const getFixedHeight = (viewWidth, viewHeight, ratio) => {
68
+ const fixed = viewWidth * ratio;
69
+ return !fixed ? viewHeight : fixed;
70
+ };
51
71
  const Image = forwardRef((props, ref) => {
52
72
  const { src = '', mode = 'scaleToFill', style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'enable-fast-image': enableFastImage, 'parent-width': parentWidth, 'parent-height': parentHeight, bindload, binderror } = props;
53
73
  const defaultStyle = {
@@ -55,7 +75,6 @@ const Image = forwardRef((props, ref) => {
55
75
  height: DEFAULT_IMAGE_HEIGHT
56
76
  };
57
77
  const styleObj = extendObject({}, defaultStyle, style, { overflow: 'hidden' });
58
- const state = useRef({});
59
78
  const nodeRef = useRef(null);
60
79
  useNodesRef(props, ref, nodeRef, {
61
80
  defaultStyle
@@ -69,17 +88,23 @@ const Image = forwardRef((props, ref) => {
69
88
  const onLayout = ({ nativeEvent: { layout: { width, height } } }) => {
70
89
  state.current.viewWidth = width;
71
90
  state.current.viewHeight = height;
91
+ // 实际渲染尺寸可能会指定的值不一致,误差低于 0.5 则认为没有变化
92
+ if (Math.abs(viewHeight - height) < 0.5 && Math.abs(viewWidth - width) < 0.5) {
93
+ if (state.current.imageWidth && state.current.imageHeight && state.current.ratio) {
94
+ if (!loaded)
95
+ setLoaded(true);
96
+ }
97
+ return;
98
+ }
72
99
  if (state.current.imageWidth && state.current.imageHeight && state.current.ratio) {
73
- setViewWidth(width);
74
- setViewHeight(height);
75
100
  setRatio(state.current.ratio);
76
101
  setImageWidth(state.current.imageWidth);
77
102
  setImageHeight(state.current.imageHeight);
78
- state.current = {};
103
+ setViewSize(state.current.viewWidth, state.current.viewHeight, state.current.ratio);
79
104
  setLoaded(true);
80
105
  }
81
106
  };
82
- const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
107
+ const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
83
108
  const { layoutRef, layoutStyle, layoutProps } = useLayout({
84
109
  props,
85
110
  hasSelfPercent,
@@ -95,43 +120,56 @@ const Image = forwardRef((props, ref) => {
95
120
  const [imageHeight, setImageHeight] = useState(0);
96
121
  const [ratio, setRatio] = useState(0);
97
122
  const [loaded, setLoaded] = useState(!isLayoutMode);
98
- const fixedHeight = useMemo(() => {
99
- const fixed = viewWidth * ratio;
100
- return !fixed ? viewHeight : fixed;
101
- }, [ratio, viewWidth, viewHeight]);
102
- const fixedWidth = useMemo(() => {
103
- if (!ratio)
104
- return viewWidth;
105
- const fixed = viewHeight / ratio;
106
- return !fixed ? viewWidth : fixed;
107
- }, [ratio, viewWidth, viewHeight]);
123
+ const state = useRef({
124
+ viewWidth,
125
+ viewHeight
126
+ });
127
+ function setViewSize(viewWidth, viewHeight, ratio) {
128
+ // 在特定模式下可预测 view 的变化,在onLayout触发时能以此避免重复render
129
+ switch (mode) {
130
+ case 'widthFix': {
131
+ setViewWidth(viewWidth);
132
+ const fixedHeight = getFixedHeight(viewWidth, viewHeight, ratio);
133
+ setViewHeight(fixedHeight);
134
+ break;
135
+ }
136
+ case 'heightFix': {
137
+ setViewHeight(viewHeight);
138
+ const fixedWidth = getFixedWidth(viewWidth, viewHeight, ratio);
139
+ setViewWidth(fixedWidth);
140
+ break;
141
+ }
142
+ default:
143
+ setViewHeight(viewHeight);
144
+ setViewWidth(viewWidth);
145
+ break;
146
+ }
147
+ }
108
148
  const modeStyle = useMemo(() => {
109
149
  if (noMeetCalcRule(isSvg, mode, viewWidth, viewHeight, ratio))
110
150
  return {};
111
151
  switch (mode) {
112
- case 'scaleToFill':
152
+ case 'scaleToFill': // wx 中 svg 图片的 scaleToFill 模式效果与 aspectFit 一致,不会就行图片缩放,此处保持一致
113
153
  case 'aspectFit':
114
154
  if (isSvg) {
115
- const scale = ratio <= 1
116
- ? imageWidth >= viewWidth ? viewWidth / imageWidth : imageWidth / viewWidth
117
- : imageHeight >= viewHeight ? viewHeight / imageHeight : imageHeight / viewHeight;
155
+ const scale = getFitScale(imageWidth, imageHeight, viewWidth, viewHeight);
118
156
  return {
119
157
  transform: [
120
- { scale },
121
- ratio <= 1 ? { translateY: -(imageHeight * scale - viewHeight) / 2 / scale } : { translateX: -(imageWidth * scale - viewWidth) / 2 / scale }
158
+ { translateY: relativeCenteredSize(viewHeight, imageHeight * scale) },
159
+ { translateX: relativeCenteredSize(viewWidth, imageWidth * scale) },
160
+ { scale }
122
161
  ]
123
162
  };
124
163
  }
125
164
  return {};
126
165
  case 'aspectFill':
127
166
  if (isSvg) {
128
- const scale = ratio >= 1
129
- ? imageWidth >= viewWidth ? viewWidth / imageWidth : imageWidth / viewWidth
130
- : imageHeight >= viewHeight ? viewHeight / imageHeight : imageHeight / viewHeight;
167
+ const scale = getFillScale(imageWidth, imageHeight, viewWidth, viewHeight);
131
168
  return {
132
169
  transform: [
133
- { scale },
134
- ratio >= 1 ? { translateY: -(imageHeight * scale - viewHeight) / 2 / scale } : { translateX: -(imageWidth * scale - viewWidth) / 2 / scale }
170
+ { translateY: relativeCenteredSize(viewHeight, imageHeight * scale) },
171
+ { translateX: relativeCenteredSize(viewWidth, imageWidth * scale) },
172
+ { scale }
135
173
  ]
136
174
  };
137
175
  }
@@ -139,9 +177,7 @@ const Image = forwardRef((props, ref) => {
139
177
  case 'widthFix':
140
178
  case 'heightFix':
141
179
  if (isSvg) {
142
- const scale = ratio >= 1
143
- ? imageWidth >= fixedWidth ? fixedWidth / imageWidth : imageWidth / fixedWidth
144
- : imageHeight >= fixedHeight ? fixedHeight / imageHeight : imageHeight / fixedHeight;
180
+ const scale = getFitScale(imageWidth, imageHeight, viewWidth, viewHeight);
145
181
  return {
146
182
  transform: [{ scale }]
147
183
  };
@@ -204,12 +240,23 @@ const Image = forwardRef((props, ref) => {
204
240
  default:
205
241
  return {};
206
242
  }
207
- }, [isSvg, mode, viewWidth, viewHeight, imageWidth, imageHeight, ratio, fixedWidth, fixedHeight]);
243
+ }, [isSvg, mode, viewWidth, viewHeight, imageWidth, imageHeight, ratio]);
208
244
  const onSvgLoad = (evt) => {
209
245
  const { width, height } = evt.nativeEvent.layout;
210
- setRatio(!width ? 0 : height / width);
211
- setImageWidth(width);
246
+ state.current.imageHeight = height;
212
247
  setImageHeight(height);
248
+ state.current.ratio = !width ? 0 : height / width;
249
+ if (isWidthFixMode
250
+ ? state.current.viewWidth
251
+ : isHeightFixMode
252
+ ? state.current.viewHeight
253
+ : state.current.viewWidth && state.current.viewHeight) {
254
+ setRatio(state.current.ratio);
255
+ setImageWidth(width);
256
+ setImageHeight(height);
257
+ setViewSize(state.current.viewWidth, state.current.viewHeight, state.current.ratio);
258
+ setLoaded(true);
259
+ }
213
260
  bindload && bindload(getCustomEvent('load', evt, {
214
261
  detail: { width, height },
215
262
  layoutRef
@@ -247,21 +294,21 @@ const Image = forwardRef((props, ref) => {
247
294
  : isHeightFixMode
248
295
  ? state.current.viewHeight
249
296
  : state.current.viewWidth && state.current.viewHeight) {
250
- state.current.viewWidth && setViewWidth(state.current.viewWidth);
251
- state.current.viewHeight && setViewHeight(state.current.viewHeight);
252
- setRatio(!width ? 0 : height / width);
297
+ setRatio(state.current.ratio);
253
298
  setImageWidth(width);
254
299
  setImageHeight(height);
255
- state.current = {};
300
+ setViewSize(state.current.viewWidth, state.current.viewHeight, state.current.ratio);
256
301
  setLoaded(true);
257
302
  }
303
+ }, () => {
304
+ setLoaded(true);
258
305
  });
259
306
  }
260
307
  }, [src, isSvg, isLayoutMode]);
261
- const innerProps = useInnerProps(props, extendObject({
308
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
262
309
  ref: nodeRef,
263
- style: extendObject({}, normalStyle, layoutStyle, isHeightFixMode ? { width: fixedWidth } : {}, isWidthFixMode ? { height: fixedHeight } : {})
264
- }, layoutProps), [
310
+ style: extendObject({}, normalStyle, layoutStyle, isHeightFixMode ? { width: viewWidth } : {}, isWidthFixMode ? { height: viewHeight } : {})
311
+ }), [
265
312
  'src',
266
313
  'mode',
267
314
  'svg'
@@ -286,7 +333,11 @@ const Image = forwardRef((props, ref) => {
286
333
  }, isCropMode ? modeStyle : {})
287
334
  }, isLayoutMode ? {} : innerProps), enableFastImage);
288
335
  const LayoutImage = createElement(View, innerProps, loaded && BaseImage);
289
- return isSvg ? SvgImage : isLayoutMode ? LayoutImage : BaseImage;
336
+ const finalComponent = isSvg ? SvgImage : isLayoutMode ? LayoutImage : BaseImage;
337
+ if (hasPositionFixed) {
338
+ return createElement(Portal, null, finalComponent);
339
+ }
340
+ return finalComponent;
290
341
  });
291
342
  Image.displayName = 'mpx-image';
292
343
  export default Image;
@@ -0,0 +1,11 @@
1
+ import { Text } from 'react-native';
2
+ import { createElement } from 'react';
3
+ import { extendObject } from './utils';
4
+ const InlineText = (props) => {
5
+ const { allowFontScaling = false } = props;
6
+ return createElement(Text, extendObject({}, props, {
7
+ allowFontScaling
8
+ }));
9
+ };
10
+ InlineText.displayName = 'MpxInlineText';
11
+ export default InlineText;
@@ -38,20 +38,18 @@
38
38
  * ✘ bind:onkeyboardheightchange
39
39
  */
40
40
  import { forwardRef, useRef, useState, useContext, useEffect, createElement } from 'react';
41
- import { Platform, TextInput } from 'react-native';
41
+ import { TextInput } from 'react-native';
42
42
  import { warn } from '@mpxjs/utils';
43
- import { useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils';
43
+ import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isIOS } from './utils';
44
44
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
45
45
  import useNodesRef from './useNodesRef';
46
46
  import { FormContext, KeyboardAvoidContext } from './context';
47
+ import Portal from './mpx-portal';
47
48
  const keyboardTypeMap = {
48
49
  text: 'default',
49
50
  number: 'numeric',
50
51
  idcard: 'default',
51
- digit: Platform.select({
52
- ios: 'decimal-pad',
53
- android: 'numeric'
54
- }) || ''
52
+ digit: isIOS ? 'decimal-pad' : 'numeric'
55
53
  };
56
54
  const Input = forwardRef((props, ref) => {
57
55
  const { style = {}, allowFontScaling = false, type = 'text', value, password, 'placeholder-style': placeholderStyle = {}, disabled, maxlength = 140, 'cursor-spacing': cursorSpacing = 0, 'auto-focus': autoFocus, focus, 'confirm-type': confirmType = 'done', 'confirm-hold': confirmHold = false, cursor, 'cursor-color': cursorColor, 'selection-start': selectionStart = -1, 'selection-end': selectionEnd = -1, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'adjust-position': adjustPosition = true, bindinput, bindfocus, bindblur, bindconfirm, bindselectionchange,
@@ -86,14 +84,14 @@ const Input = forwardRef((props, ref) => {
86
84
  const styleObj = extendObject({ padding: 0, backgroundColor: '#fff' }, style, multiline && autoHeight
87
85
  ? { height: 'auto', minHeight: Math.max(style?.minHeight || 35, contentHeight) }
88
86
  : {});
89
- const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
87
+ const { hasPositionFixed, hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
90
88
  const nodeRef = useRef(null);
91
89
  useNodesRef(props, ref, nodeRef, {
92
90
  style: normalStyle
93
91
  });
94
92
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
95
93
  useEffect(() => {
96
- if (inputValue !== value) {
94
+ if (value !== tmpValue.current) {
97
95
  const parsed = parseValue(value);
98
96
  tmpValue.current = parsed;
99
97
  setInputValue(parsed);
@@ -250,7 +248,7 @@ const Input = forwardRef((props, ref) => {
250
248
  ? nodeRef.current?.focus()
251
249
  : nodeRef.current?.blur();
252
250
  }, [focus]);
253
- const innerProps = useInnerProps(props, extendObject({
251
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
254
252
  ref: nodeRef,
255
253
  style: extendObject({}, normalStyle, layoutStyle),
256
254
  allowFontScaling,
@@ -267,8 +265,7 @@ const Input = forwardRef((props, ref) => {
267
265
  underlineColorAndroid: 'rgba(0,0,0,0)',
268
266
  textAlignVertical: textAlignVertical,
269
267
  placeholderTextColor: placeholderStyle?.color,
270
- multiline: !!multiline
271
- }, !!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType }, layoutProps, {
268
+ multiline: !!multiline,
272
269
  onTouchStart,
273
270
  onTouchEnd,
274
271
  onFocus,
@@ -277,7 +274,7 @@ const Input = forwardRef((props, ref) => {
277
274
  onSelectionChange,
278
275
  onContentSizeChange,
279
276
  onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
280
- }), [
277
+ }, !!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType }), [
281
278
  'type',
282
279
  'password',
283
280
  'placeholder-style',
@@ -293,7 +290,11 @@ const Input = forwardRef((props, ref) => {
293
290
  ], {
294
291
  layoutRef
295
292
  });
296
- return createElement(TextInput, innerProps);
293
+ const finalComponent = createElement(TextInput, innerProps);
294
+ if (hasPositionFixed) {
295
+ return createElement(Portal, null, finalComponent);
296
+ }
297
+ return finalComponent;
297
298
  });
298
299
  Input.displayName = 'MpxInput';
299
300
  export default Input;