@mpxjs/webpack-plugin 2.9.73 → 2.10.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 (82) hide show
  1. package/lib/file-loader.js +5 -0
  2. package/lib/index.js +21 -3
  3. package/lib/platform/template/wx/component-config/input.js +1 -1
  4. package/lib/platform/template/wx/component-config/textarea.js +1 -1
  5. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  6. package/lib/platform/template/wx/component-config/video.js +28 -1
  7. package/lib/platform/template/wx/index.js +2 -2
  8. package/lib/react/processScript.js +6 -4
  9. package/lib/react/processTemplate.js +5 -3
  10. package/lib/runtime/components/react/KeyboardAvoidingView.tsx +108 -0
  11. package/lib/runtime/components/react/context.ts +18 -2
  12. package/lib/runtime/components/react/dist/KeyboardAvoidingView.jsx +89 -0
  13. package/lib/runtime/components/react/dist/context.js +1 -0
  14. package/lib/runtime/components/react/dist/event.config.js +1 -0
  15. package/lib/runtime/components/react/dist/getInnerListeners.js +8 -5
  16. package/lib/runtime/components/react/dist/mpx-button.jsx +1 -1
  17. package/lib/runtime/components/react/dist/mpx-icon/icons/cancel.png +0 -0
  18. package/lib/runtime/components/react/dist/mpx-icon/icons/clear.png +0 -0
  19. package/lib/runtime/components/react/dist/mpx-icon/icons/download.png +0 -0
  20. package/lib/runtime/components/react/dist/mpx-icon/icons/info.png +0 -0
  21. package/lib/runtime/components/react/dist/mpx-icon/icons/search.png +0 -0
  22. package/lib/runtime/components/react/dist/mpx-icon/icons/success.png +0 -0
  23. package/lib/runtime/components/react/dist/mpx-icon/icons/success_no_circle.png +0 -0
  24. package/lib/runtime/components/react/dist/mpx-icon/icons/waiting.png +0 -0
  25. package/lib/runtime/components/react/dist/mpx-icon/icons/warn.png +0 -0
  26. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +50 -0
  27. package/lib/runtime/components/react/dist/mpx-image.jsx +19 -18
  28. package/lib/runtime/components/react/dist/mpx-input.jsx +48 -19
  29. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +16 -14
  30. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +2 -1
  31. package/lib/runtime/components/react/dist/mpx-portal/index.jsx +30 -0
  32. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +112 -0
  33. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +41 -0
  34. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  35. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +20 -9
  36. package/lib/runtime/components/react/dist/mpx-swiper.jsx +3 -2
  37. package/lib/runtime/components/react/dist/mpx-textarea.jsx +11 -3
  38. package/lib/runtime/components/react/dist/mpx-video.jsx +248 -0
  39. package/lib/runtime/components/react/dist/mpx-web-view.jsx +149 -50
  40. package/lib/runtime/components/react/dist/useAnimationHooks.js +4 -4
  41. package/lib/runtime/components/react/dist/utils.jsx +8 -3
  42. package/lib/runtime/components/react/event.config.ts +2 -0
  43. package/lib/runtime/components/react/getInnerListeners.ts +8 -5
  44. package/lib/runtime/components/react/mpx-button.tsx +1 -1
  45. package/lib/runtime/components/react/mpx-icon/icons/cancel.png +0 -0
  46. package/lib/runtime/components/react/mpx-icon/icons/clear.png +0 -0
  47. package/lib/runtime/components/react/mpx-icon/icons/download.png +0 -0
  48. package/lib/runtime/components/react/mpx-icon/icons/info.png +0 -0
  49. package/lib/runtime/components/react/mpx-icon/icons/search.png +0 -0
  50. package/lib/runtime/components/react/mpx-icon/icons/success.png +0 -0
  51. package/lib/runtime/components/react/mpx-icon/icons/success_no_circle.png +0 -0
  52. package/lib/runtime/components/react/mpx-icon/icons/waiting.png +0 -0
  53. package/lib/runtime/components/react/mpx-icon/icons/warn.png +0 -0
  54. package/lib/runtime/components/react/mpx-icon/index.tsx +111 -0
  55. package/lib/runtime/components/react/mpx-image.tsx +26 -14
  56. package/lib/runtime/components/react/mpx-input.tsx +52 -20
  57. package/lib/runtime/components/react/mpx-movable-view.tsx +19 -16
  58. package/lib/runtime/components/react/mpx-picker/time.tsx +2 -1
  59. package/lib/runtime/components/react/mpx-portal/index.tsx +39 -0
  60. package/lib/runtime/components/react/mpx-portal/portal-host.tsx +141 -0
  61. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +64 -0
  62. package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
  63. package/lib/runtime/components/react/mpx-scroll-view.tsx +22 -10
  64. package/lib/runtime/components/react/mpx-swiper.tsx +3 -2
  65. package/lib/runtime/components/react/mpx-textarea.tsx +13 -3
  66. package/lib/runtime/components/react/mpx-video.tsx +388 -0
  67. package/lib/runtime/components/react/mpx-web-view.tsx +180 -49
  68. package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
  69. package/lib/runtime/components/react/types/global.d.ts +8 -0
  70. package/lib/runtime/components/react/useAnimationHooks.ts +4 -4
  71. package/lib/runtime/components/react/utils.tsx +12 -6
  72. package/lib/script-setup-compiler/index.js +6 -2
  73. package/lib/style-compiler/index.js +3 -4
  74. package/lib/style-compiler/strip-conditional-loader.js +127 -0
  75. package/lib/template-compiler/compiler.js +19 -8
  76. package/lib/template-compiler/index.js +4 -4
  77. package/lib/web/processTemplate.js +7 -5
  78. package/lib/wxs/loader.js +2 -2
  79. package/lib/wxs/pre-loader.js +2 -2
  80. package/package.json +7 -5
  81. package/lib/runtime/components/react/dist/mpx-icon.jsx +0 -41
  82. package/lib/runtime/components/react/mpx-icon.tsx +0 -102
@@ -268,24 +268,25 @@ const Image = forwardRef((props, ref) => {
268
268
  ], {
269
269
  layoutRef
270
270
  });
271
- return createElement(View, innerProps, isSvg
272
- ? createElement(SvgCssUri, {
273
- uri: src,
274
- onLayout: onSvgLoad,
275
- onError: binderror && onSvgError,
276
- style: extendObject({ transformOrigin: 'top left' }, modeStyle)
277
- })
278
- : loaded && renderImage({
279
- source: { uri: src },
280
- resizeMode: resizeMode,
281
- onLoad: bindload && onImageLoad,
282
- onError: binderror && onImageError,
283
- style: extendObject({
284
- transformOrigin: 'top left',
285
- width: isCropMode ? imageWidth : '100%',
286
- height: isCropMode ? imageHeight : '100%'
287
- }, isCropMode ? modeStyle : {})
288
- }, enableFastImage));
271
+ const SvgImage = createElement(View, innerProps, createElement(SvgCssUri, {
272
+ uri: src,
273
+ onLayout: onSvgLoad,
274
+ onError: binderror && onSvgError,
275
+ style: extendObject({ transformOrigin: 'top left' }, modeStyle)
276
+ }));
277
+ const BaseImage = renderImage(extendObject({
278
+ source: { uri: src },
279
+ resizeMode: resizeMode,
280
+ onLoad: bindload && onImageLoad,
281
+ onError: binderror && onImageError,
282
+ style: extendObject({
283
+ transformOrigin: 'top left',
284
+ width: isCropMode ? imageWidth : '100%',
285
+ height: isCropMode ? imageHeight : '100%'
286
+ }, isCropMode ? modeStyle : {})
287
+ }, isLayoutMode ? {} : innerProps), enableFastImage);
288
+ const LayoutImage = createElement(View, innerProps, loaded && BaseImage);
289
+ return isSvg ? SvgImage : isLayoutMode ? LayoutImage : BaseImage;
289
290
  });
290
291
  Image.displayName = 'mpx-image';
291
292
  export default Image;
@@ -7,7 +7,7 @@
7
7
  * ✘ placeholder-class
8
8
  * ✔ disabled
9
9
  * ✔ maxlength
10
- * cursor-spacing
10
+ * cursor-spacing
11
11
  * ✔ auto-focus
12
12
  * ✔ focus
13
13
  * ✔ confirm-type
@@ -37,7 +37,7 @@
37
37
  * ✘ bind:keyboardcompositionend
38
38
  * ✘ bind:onkeyboardheightchange
39
39
  */
40
- import { forwardRef, useMemo, useRef, useState, useContext, useEffect, createElement } from 'react';
40
+ import { forwardRef, useRef, useState, useContext, useEffect, createElement } from 'react';
41
41
  import { Platform, TextInput } from 'react-native';
42
42
  import { warn } from '@mpxjs/utils';
43
43
  import { parseInlineStyle, useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils';
@@ -54,17 +54,28 @@ const keyboardTypeMap = {
54
54
  }) || ''
55
55
  };
56
56
  const Input = forwardRef((props, ref) => {
57
- const { style = {}, allowFontScaling = false, type = 'text', value, password, 'placeholder-style': placeholderStyle, disabled, maxlength = 140, '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,
57
+ 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,
58
58
  // private
59
59
  multiline, 'auto-height': autoHeight, bindlinechange } = props;
60
60
  const formContext = useContext(FormContext);
61
- const setKeyboardAvoidEnabled = useContext(KeyboardAvoidContext);
61
+ const keyboardAvoid = useContext(KeyboardAvoidContext);
62
62
  let formValuesMap;
63
63
  if (formContext) {
64
64
  formValuesMap = formContext.formValuesMap;
65
65
  }
66
+ const parseValue = (value) => {
67
+ if (typeof value === 'string') {
68
+ if (value.length > maxlength && maxlength >= 0) {
69
+ return value.slice(0, maxlength);
70
+ }
71
+ return value;
72
+ }
73
+ if (typeof value === 'number')
74
+ return value + '';
75
+ return '';
76
+ };
66
77
  const keyboardType = keyboardTypeMap[type];
67
- const defaultValue = type === 'number' && value ? value + '' : value;
78
+ const defaultValue = parseValue(value);
68
79
  const placeholderTextColor = parseInlineStyle(placeholderStyle)?.color;
69
80
  const textAlignVertical = multiline ? 'top' : 'auto';
70
81
  const tmpValue = useRef(defaultValue);
@@ -72,6 +83,7 @@ const Input = forwardRef((props, ref) => {
72
83
  const lineCount = useRef(0);
73
84
  const [inputValue, setInputValue] = useState(defaultValue);
74
85
  const [contentHeight, setContentHeight] = useState(0);
86
+ const [selection, setSelection] = useState({ start: -1, end: -1 });
75
87
  const styleObj = extendObject({ padding: 0, backgroundColor: '#fff' }, style, multiline && autoHeight
76
88
  ? { minHeight: Math.max(style?.minHeight || 35, contentHeight) }
77
89
  : {});
@@ -83,15 +95,15 @@ const Input = forwardRef((props, ref) => {
83
95
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
84
96
  useEffect(() => {
85
97
  if (inputValue !== value) {
86
- setInputValue(value);
98
+ setInputValue(parseValue(value));
87
99
  }
88
100
  }, [value]);
89
- const selection = useMemo(() => {
90
- if (selectionStart >= 0 && selectionEnd >= 0) {
91
- return { start: selectionStart, end: selectionEnd };
101
+ useEffect(() => {
102
+ if (typeof cursor === 'number') {
103
+ setSelection({ start: cursor, end: cursor });
92
104
  }
93
- else if (typeof cursor === 'number') {
94
- return { start: cursor, end: cursor };
105
+ else if (selectionStart >= 0 && selectionEnd >= 0 && selectionStart !== selectionEnd) {
106
+ setSelection({ start: selectionStart, end: selectionEnd });
95
107
  }
96
108
  }, [cursor, selectionStart, selectionEnd]);
97
109
  const onTextInput = ({ nativeEvent }) => {
@@ -119,8 +131,21 @@ const Input = forwardRef((props, ref) => {
119
131
  setInputValue(tmpValue.current);
120
132
  }
121
133
  };
134
+ const setKeyboardAvoidContext = () => {
135
+ if (adjustPosition && keyboardAvoid?.current) {
136
+ extendObject(keyboardAvoid.current, {
137
+ cursorSpacing,
138
+ ref: nodeRef
139
+ });
140
+ }
141
+ };
142
+ const onInputTouchStart = () => {
143
+ // sometimes the focus event occurs later than the keyboardWillShow event
144
+ setKeyboardAvoidContext();
145
+ };
122
146
  const onInputFocus = (evt) => {
123
- bindfocus(getCustomEvent('focus', evt, {
147
+ setKeyboardAvoidContext();
148
+ bindfocus && bindfocus(getCustomEvent('focus', evt, {
124
149
  detail: {
125
150
  value: tmpValue.current || ''
126
151
  },
@@ -128,7 +153,7 @@ const Input = forwardRef((props, ref) => {
128
153
  }, props));
129
154
  };
130
155
  const onInputBlur = (evt) => {
131
- bindblur(getCustomEvent('blur', evt, {
156
+ bindblur && bindblur(getCustomEvent('blur', evt, {
132
157
  detail: {
133
158
  value: tmpValue.current || '',
134
159
  cursor: cursorIndex.current
@@ -154,7 +179,8 @@ const Input = forwardRef((props, ref) => {
154
179
  }, props));
155
180
  };
156
181
  const onSelectionChange = (evt) => {
157
- bindselectionchange(getCustomEvent('selectionchange', evt, {
182
+ setSelection(evt.nativeEvent.selection);
183
+ bindselectionchange && bindselectionchange(getCustomEvent('selectionchange', evt, {
158
184
  detail: {
159
185
  selectionStart: evt.nativeEvent.selection.start,
160
186
  selectionEnd: evt.nativeEvent.selection.end
@@ -203,8 +229,10 @@ const Input = forwardRef((props, ref) => {
203
229
  };
204
230
  }, []);
205
231
  useEffect(() => {
206
- setKeyboardAvoidEnabled?.(adjustPosition);
207
- }, [adjustPosition]);
232
+ if (focus) {
233
+ setKeyboardAvoidContext();
234
+ }
235
+ }, [focus]);
208
236
  useUpdateEffect(() => {
209
237
  if (!nodeRef?.current) {
210
238
  return;
@@ -233,11 +261,12 @@ const Input = forwardRef((props, ref) => {
233
261
  placeholderTextColor: placeholderTextColor,
234
262
  multiline: !!multiline
235
263
  }, layoutProps, {
236
- onFocus: bindfocus && onInputFocus,
237
- onBlur: bindblur && onInputBlur,
264
+ onTouchStart: onInputTouchStart,
265
+ onFocus: onInputFocus,
266
+ onBlur: onInputBlur,
238
267
  onKeyPress: bindconfirm && onKeyPress,
239
268
  onSubmitEditing: bindconfirm && multiline && onSubmitEditing,
240
- onSelectionChange: bindselectionchange && onSelectionChange,
269
+ onSelectionChange: onSelectionChange,
241
270
  onTextInput: onTextInput,
242
271
  onChange: onChange,
243
272
  onContentSizeChange: onContentSizeChange
@@ -22,7 +22,7 @@ import { StyleSheet } from 'react-native';
22
22
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
23
23
  import useNodesRef from './useNodesRef';
24
24
  import { MovableAreaContext } from './context';
25
- import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, flatGesture, extendObject, omit } from './utils';
25
+ import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, flatGesture, extendObject, omit, useNavigation } from './utils';
26
26
  import { GestureDetector, Gesture } from 'react-native-gesture-handler';
27
27
  import Animated, { useSharedValue, useAnimatedStyle, withDecay, runOnJS, runOnUI, useAnimatedReaction, withSpring } from 'react-native-reanimated';
28
28
  import { collectDataset, noop } from '@mpxjs/utils';
@@ -43,6 +43,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
43
43
  propsRef.current = (props || {});
44
44
  const { x = 0, y = 0, inertia = false, disabled = false, animation = true, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend } = props;
45
45
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(Object.assign({}, style, styles.container), { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
46
+ const navigation = useNavigation();
46
47
  const prevSimultaneousHandlersRef = useRef(originSimultaneousHandlers || []);
47
48
  const prevWaitForHandlersRef = useRef(waitFor || []);
48
49
  const gestureSwitch = useRef(false);
@@ -229,40 +230,41 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
229
230
  setHeight(height || 0);
230
231
  }
231
232
  nodeRef.current?.measure((x, y, width, height) => {
232
- layoutRef.current = { x, y, width, height, offsetLeft: 0, offsetTop: 0 };
233
+ const { y: navigationY = 0 } = navigation?.layout || {};
234
+ layoutRef.current = { x, y: y - navigationY, width, height, offsetLeft: 0, offsetTop: 0 };
233
235
  resetBoundaryAndCheck({ width, height });
234
236
  });
235
237
  props.onLayout && props.onLayout(e);
236
238
  };
237
- const extendEvent = useCallback((e, obj) => {
239
+ const extendEvent = useCallback((e, type) => {
240
+ const { y: navigationY = 0 } = navigation?.layout || {};
238
241
  const touchArr = [e.changedTouches, e.allTouches];
239
242
  touchArr.forEach(touches => {
240
243
  touches && touches.forEach((item) => {
241
244
  item.pageX = item.absoluteX;
242
- item.pageY = item.absoluteY;
245
+ item.pageY = item.absoluteY - navigationY;
246
+ item.clientX = item.absoluteX;
247
+ item.clientY = item.absoluteY - navigationY;
243
248
  });
244
249
  });
245
250
  Object.assign(e, {
246
- touches: e.allTouches,
247
- detail: {
248
- x: e.changedTouches[0].absoluteX,
249
- y: e.changedTouches[0].absoluteY
250
- },
251
+ touches: type === 'end' ? [] : e.allTouches,
251
252
  currentTarget: {
252
253
  id: props.id || '',
253
254
  dataset: collectDataset(props),
254
255
  offsetLeft: 0,
255
256
  offsetTop: 0
256
- }
257
- }, obj);
257
+ },
258
+ detail: {}
259
+ });
258
260
  }, []);
259
261
  const triggerStartOnJS = ({ e }) => {
260
- extendEvent(e);
262
+ extendEvent(e, 'start');
261
263
  bindtouchstart && bindtouchstart(e);
262
264
  catchtouchstart && catchtouchstart(e);
263
265
  };
264
266
  const triggerMoveOnJS = ({ e, hasTouchmove, hasCatchTouchmove, touchEvent }) => {
265
- extendEvent(e);
267
+ extendEvent(e, 'move');
266
268
  if (hasTouchmove) {
267
269
  if (touchEvent === 'htouchmove') {
268
270
  bindhtouchmove && bindhtouchmove(e);
@@ -283,7 +285,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
283
285
  }
284
286
  };
285
287
  const triggerEndOnJS = ({ e }) => {
286
- extendEvent(e);
288
+ extendEvent(e, 'end');
287
289
  bindtouchend && bindtouchend(e);
288
290
  catchtouchend && catchtouchend(e);
289
291
  };
@@ -1,5 +1,6 @@
1
1
  import { View, Text, Modal, TouchableWithoutFeedback } from 'react-native';
2
- import { PickerView, Portal } from '@ant-design/react-native';
2
+ import Portal from '../mpx-portal/index';
3
+ import { PickerView } from '@ant-design/react-native';
3
4
  import React, { forwardRef, useState, useRef, useEffect } from 'react';
4
5
  import useNodesRef from '../useNodesRef'; // 引入辅助函数
5
6
  // 可见应用窗口的大小。
@@ -0,0 +1,30 @@
1
+ import { useContext, useEffect, useRef } from 'react';
2
+ import { PortalContext, RouteContext, VarContext } from '../context';
3
+ import PortalHost, { portal } from './portal-host';
4
+ const Portal = ({ children }) => {
5
+ const manager = useContext(PortalContext);
6
+ const keyRef = useRef(null);
7
+ const { pageId } = useContext(RouteContext) || {};
8
+ const varContext = useContext(VarContext);
9
+ if (varContext) {
10
+ children = (<VarContext.Provider value={varContext} key='varContextWrap'>{children}</VarContext.Provider>);
11
+ }
12
+ useEffect(() => {
13
+ manager.update(keyRef.current, children);
14
+ }, [children]);
15
+ useEffect(() => {
16
+ if (!manager) {
17
+ throw new Error('Looks like you forgot to wrap your root component with `PortalHost` component from `@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index`.\n\n');
18
+ }
19
+ keyRef.current = manager.mount(children, null, pageId);
20
+ return () => {
21
+ manager.unmount(keyRef.current);
22
+ };
23
+ }, []);
24
+ return null;
25
+ };
26
+ Portal.Host = PortalHost;
27
+ Portal.add = portal.add;
28
+ Portal.remove = portal.remove;
29
+ Portal.update = portal.update;
30
+ export default Portal;
@@ -0,0 +1,112 @@
1
+ import { useEffect, useRef, useMemo, useContext } from 'react';
2
+ import { View, DeviceEventEmitter, NativeEventEmitter, StyleSheet } from 'react-native';
3
+ import PortalManager from './portal-manager';
4
+ import { PortalContext, RouteContext } from '../context';
5
+ // events
6
+ const addType = 'MPX_RN_ADD_PORTAL';
7
+ const removeType = 'MPX_RN_REMOVE_PORTAL';
8
+ const updateType = 'MPX_RN_UPDATE_PORTAL';
9
+ // fix react native web does not support DeviceEventEmitter
10
+ const TopViewEventEmitter = DeviceEventEmitter || new NativeEventEmitter();
11
+ const styles = StyleSheet.create({
12
+ container: {
13
+ flex: 1
14
+ }
15
+ });
16
+ class PortalGuard {
17
+ nextKey = 10000;
18
+ add = (e, id) => {
19
+ const key = this.nextKey++;
20
+ TopViewEventEmitter.emit(addType, e, key, id);
21
+ return key;
22
+ };
23
+ remove = (key) => {
24
+ TopViewEventEmitter.emit(removeType, key);
25
+ };
26
+ update = (key, e) => {
27
+ TopViewEventEmitter.emit(updateType, key, e);
28
+ };
29
+ }
30
+ /**
31
+ * portal
32
+ */
33
+ export const portal = new PortalGuard();
34
+ const PortalHost = ({ children }) => {
35
+ const _nextKey = useRef(0);
36
+ const manager = useRef(null);
37
+ const queue = useRef([]);
38
+ const { pageId } = useContext(RouteContext) || {};
39
+ const mount = (children, _key, id) => {
40
+ if (id !== pageId)
41
+ return;
42
+ const key = _key || _nextKey.current++;
43
+ if (manager.current) {
44
+ manager.current.mount(key, children);
45
+ }
46
+ else {
47
+ queue.current.push({ type: 'mount', key, children });
48
+ }
49
+ return key;
50
+ };
51
+ const unmount = (key) => {
52
+ if (manager.current) {
53
+ manager.current.unmount(key);
54
+ }
55
+ else {
56
+ queue.current.push({ type: 'unmount', key, children });
57
+ }
58
+ };
59
+ const update = (key, children) => {
60
+ if (manager.current) {
61
+ manager.current.update(key, children);
62
+ }
63
+ else {
64
+ const operation = { type: 'mount', key, children };
65
+ const index = queue.current.findIndex((q) => q.type === 'mount' && q.key === key);
66
+ if (index > -1) {
67
+ queue.current[index] = operation;
68
+ }
69
+ else {
70
+ queue.current.push(operation);
71
+ }
72
+ }
73
+ };
74
+ const subScriptions = useMemo(() => {
75
+ return [
76
+ TopViewEventEmitter.addListener(addType, mount),
77
+ TopViewEventEmitter.addListener(removeType, unmount),
78
+ TopViewEventEmitter.addListener(updateType, update)
79
+ ];
80
+ }, []);
81
+ useEffect(() => {
82
+ while (queue.current.length && manager.current) {
83
+ const operation = queue.current.shift();
84
+ if (!operation)
85
+ return;
86
+ switch (operation.type) {
87
+ case 'mount':
88
+ manager.current.mount(operation.key, operation.children);
89
+ break;
90
+ case 'unmount':
91
+ manager.current.unmount(operation.key);
92
+ break;
93
+ }
94
+ }
95
+ return () => {
96
+ subScriptions.forEach((subScription) => {
97
+ subScription.remove();
98
+ });
99
+ };
100
+ }, []);
101
+ return (<PortalContext.Provider value={{
102
+ mount,
103
+ update,
104
+ unmount
105
+ }}>
106
+ <View style={styles.container} collapsable={false}>
107
+ {children}
108
+ </View>
109
+ <PortalManager ref={manager}/>
110
+ </PortalContext.Provider>);
111
+ };
112
+ export default PortalHost;
@@ -0,0 +1,41 @@
1
+ import { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import { extendObject } from '../utils';
4
+ const _PortalManager = forwardRef((props, ref) => {
5
+ const [state, setState] = useState({
6
+ portals: []
7
+ });
8
+ const mount = useCallback((key, children) => {
9
+ setState((prevState) => ({
10
+ portals: [...prevState.portals, { key, children }]
11
+ }));
12
+ }, [state]);
13
+ const update = useCallback((key, children) => {
14
+ setState((prevState) => ({
15
+ portals: prevState.portals.map((item) => {
16
+ if (item.key === key) {
17
+ return extendObject({}, item, { children });
18
+ }
19
+ return item;
20
+ })
21
+ }));
22
+ }, [state]);
23
+ const unmount = useCallback((key) => {
24
+ setState((prevState) => ({
25
+ portals: prevState.portals.filter((item) => item.key !== key)
26
+ }));
27
+ }, []);
28
+ useImperativeHandle(ref, () => ({
29
+ mount,
30
+ update,
31
+ unmount,
32
+ portals: state.portals
33
+ }));
34
+ return (<>
35
+ {state.portals.map(({ key, children }, i) => (<View key={key} collapsable={false} // Need collapsable=false here to clip the elevations
36
+ style={[StyleSheet.absoluteFill, { zIndex: 1000 + i, pointerEvents: 'box-none' }]}>
37
+ {children}
38
+ </View>))}
39
+ </>);
40
+ });
41
+ export default _PortalManager;
@@ -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/index';
6
6
  import { warn } from '@mpxjs/utils';
7
7
  const _RootPortal = (props) => {
8
8
  const { children, enable = true } = props;
@@ -31,8 +31,7 @@
31
31
  * ✔ bindscrolltolower
32
32
  * ✔ bindscroll
33
33
  */
34
- import { ScrollView } from 'react-native-gesture-handler';
35
- import { RefreshControl } from 'react-native';
34
+ import { ScrollView, RefreshControl } from 'react-native-gesture-handler';
36
35
  import { useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react';
37
36
  import { useAnimatedRef } from 'react-native-reanimated';
38
37
  import { warn } from '@mpxjs/utils';
@@ -203,11 +202,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
203
202
  updateScrollOptions(e, { scrollLeft, scrollTop });
204
203
  onStartReached(e);
205
204
  onEndReached(e);
206
- if (enableTriggerIntersectionObserver && intersectionObservers) {
207
- for (const key in intersectionObservers) {
208
- intersectionObservers[key].throttleMeasure();
209
- }
210
- }
205
+ updateIntersection();
211
206
  }
212
207
  function onScrollEnd(e) {
213
208
  const { bindscrollend } = props;
@@ -226,6 +221,14 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
226
221
  updateScrollOptions(e, { scrollLeft, scrollTop });
227
222
  onStartReached(e);
228
223
  onEndReached(e);
224
+ updateIntersection();
225
+ }
226
+ function updateIntersection() {
227
+ if (enableTriggerIntersectionObserver && intersectionObservers) {
228
+ for (const key in intersectionObservers) {
229
+ intersectionObservers[key].throttleMeasure();
230
+ }
231
+ }
229
232
  }
230
233
  function scrollToOffset(x = 0, y = 0) {
231
234
  if (scrollViewRef.current) {
@@ -284,10 +287,18 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
284
287
  function onScrollDrag(e) {
285
288
  const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
286
289
  updateScrollOptions(e, { scrollLeft, scrollTop });
290
+ updateIntersection();
291
+ }
292
+ function onScrollDragStart(e) {
293
+ hasCallScrollToLower.current = false;
294
+ hasCallScrollToUpper.current = false;
295
+ onScrollDrag(e);
287
296
  }
288
297
  const scrollAdditionalProps = extendObject({
289
298
  style: extendObject({}, innerStyle, layoutStyle),
290
299
  pinchGestureEnabled: false,
300
+ alwaysBounceVertical: false,
301
+ alwaysBounceHorizontal: false,
291
302
  horizontal: scrollX && !scrollY,
292
303
  scrollEventThrottle: scrollEventThrottle,
293
304
  scrollsToTop: enableBackToTop,
@@ -298,9 +309,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
298
309
  onScroll: onScroll,
299
310
  onContentSizeChange: onContentSizeChange,
300
311
  bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) && onScrollTouchStart,
301
- bindtouchmove: ((enhanced && binddragging) || bindtouchend) && onScrollTouchMove,
312
+ bindtouchmove: ((enhanced && binddragging) || bindtouchmove) && onScrollTouchMove,
302
313
  bindtouchend: ((enhanced && binddragend) || bindtouchend) && onScrollTouchEnd,
303
- onScrollBeginDrag: onScrollDrag,
314
+ onScrollBeginDrag: onScrollDragStart,
304
315
  onScrollEndDrag: onScrollDrag,
305
316
  onMomentumScrollEnd: onScrollEnd
306
317
  }, (simultaneousHandlers ? { simultaneousHandlers } : {}), (waitForHandlers ? { waitFor: waitForHandlers } : {}), layoutProps);
@@ -63,7 +63,7 @@ const activeDotStyle = {
63
63
  };
64
64
  const longPressRatio = 100;
65
65
  const easeMap = {
66
- default: Easing.linear,
66
+ default: Easing.inOut(Easing.cubic),
67
67
  linear: Easing.linear,
68
68
  easeInCubic: Easing.in(Easing.cubic),
69
69
  easeOutCubic: Easing.out(Easing.cubic),
@@ -413,7 +413,8 @@ const SwiperWrapper = forwardRef((props, ref) => {
413
413
  let isCriticalItem = false;
414
414
  // 真实滚动到的偏移量坐标
415
415
  let moveToTargetPos = 0;
416
- const currentOffset = translation < 0 ? offset.value - preMarginShared.value : offset.value + preMarginShared.value;
416
+ const tmp = !circularShared.value ? 0 : preMarginShared.value;
417
+ const currentOffset = translation < 0 ? offset.value - tmp : offset.value + tmp;
417
418
  const computedIndex = Math.abs(currentOffset) / step.value;
418
419
  const moveToIndex = translation < 0 ? Math.ceil(computedIndex) : Math.floor(computedIndex);
419
420
  // 实际应该定位的索引值
@@ -13,20 +13,28 @@ import { forwardRef, createElement } from 'react';
13
13
  import { Keyboard } from 'react-native';
14
14
  import Input from './mpx-input';
15
15
  import { omit, extendObject } from './utils';
16
+ const DEFAULT_TEXTAREA_WIDTH = 300;
17
+ const DEFAULT_TEXTAREA_HEIGHT = 150;
16
18
  const Textarea = forwardRef((props, ref) => {
19
+ const { style = {} } = props;
17
20
  const restProps = omit(props, [
18
21
  'ref',
19
22
  'type',
23
+ 'style',
20
24
  'password',
21
25
  'multiline',
22
26
  'confirm-hold'
23
27
  ]);
24
- return createElement(Input, extendObject({
28
+ return createElement(Input, extendObject(restProps, {
25
29
  ref: ref,
26
30
  multiline: true,
27
31
  confirmType: 'next',
28
- bindblur: () => Keyboard.dismiss()
29
- }, restProps));
32
+ bindblur: () => Keyboard.dismiss(),
33
+ style: extendObject({
34
+ width: DEFAULT_TEXTAREA_WIDTH,
35
+ height: DEFAULT_TEXTAREA_HEIGHT
36
+ }, style)
37
+ }));
30
38
  });
31
39
  Textarea.displayName = 'MpxTextarea';
32
40
  export default Textarea;