@mpxjs/webpack-plugin 2.9.73 → 2.10.0
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.
- package/lib/file-loader.js +5 -0
- package/lib/index.js +21 -3
- package/lib/platform/template/wx/component-config/input.js +1 -1
- package/lib/platform/template/wx/component-config/textarea.js +1 -1
- package/lib/platform/template/wx/component-config/unsupported.js +1 -1
- package/lib/platform/template/wx/component-config/video.js +28 -1
- package/lib/platform/template/wx/index.js +2 -2
- package/lib/react/processScript.js +6 -4
- package/lib/react/processTemplate.js +5 -3
- package/lib/runtime/components/react/KeyboardAvoidingView.tsx +108 -0
- package/lib/runtime/components/react/context.ts +18 -2
- package/lib/runtime/components/react/dist/KeyboardAvoidingView.jsx +89 -0
- package/lib/runtime/components/react/dist/context.js +1 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +1 -2
- package/lib/runtime/components/react/dist/mpx-button.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-icon/icons/cancel.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/clear.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/download.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/info.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/search.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/success.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/success_no_circle.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/waiting.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/warn.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +50 -0
- package/lib/runtime/components/react/dist/mpx-image.jsx +19 -18
- package/lib/runtime/components/react/dist/mpx-input.jsx +48 -19
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +16 -14
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +2 -1
- package/lib/runtime/components/react/dist/mpx-portal/index.jsx +30 -0
- package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +112 -0
- package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +41 -0
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +19 -7
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +11 -3
- package/lib/runtime/components/react/dist/mpx-video.jsx +248 -0
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +149 -50
- package/lib/runtime/components/react/dist/useAnimationHooks.js +4 -4
- package/lib/runtime/components/react/dist/utils.jsx +8 -3
- package/lib/runtime/components/react/getInnerListeners.ts +1 -2
- package/lib/runtime/components/react/mpx-button.tsx +1 -1
- package/lib/runtime/components/react/mpx-icon/icons/cancel.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/clear.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/download.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/info.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/search.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/success.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/success_no_circle.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/waiting.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/warn.png +0 -0
- package/lib/runtime/components/react/mpx-icon/index.tsx +111 -0
- package/lib/runtime/components/react/mpx-image.tsx +26 -14
- package/lib/runtime/components/react/mpx-input.tsx +52 -20
- package/lib/runtime/components/react/mpx-movable-view.tsx +19 -16
- package/lib/runtime/components/react/mpx-picker/time.tsx +2 -1
- package/lib/runtime/components/react/mpx-portal/index.tsx +39 -0
- package/lib/runtime/components/react/mpx-portal/portal-host.tsx +141 -0
- package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +64 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +1 -1
- package/lib/runtime/components/react/mpx-scroll-view.tsx +20 -8
- package/lib/runtime/components/react/mpx-swiper.tsx +3 -2
- package/lib/runtime/components/react/mpx-textarea.tsx +13 -3
- package/lib/runtime/components/react/mpx-video.tsx +388 -0
- package/lib/runtime/components/react/mpx-web-view.tsx +180 -49
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
- package/lib/runtime/components/react/types/global.d.ts +8 -0
- package/lib/runtime/components/react/useAnimationHooks.ts +4 -4
- package/lib/runtime/components/react/utils.tsx +12 -6
- package/lib/script-setup-compiler/index.js +6 -2
- package/lib/style-compiler/index.js +3 -4
- package/lib/style-compiler/strip-conditional-loader.js +127 -0
- package/lib/template-compiler/compiler.js +15 -8
- package/lib/template-compiler/index.js +4 -4
- package/lib/web/processTemplate.js +7 -5
- package/lib/wxs/loader.js +2 -2
- package/lib/wxs/pre-loader.js +2 -2
- package/package.json +7 -5
- package/lib/runtime/components/react/dist/mpx-icon.jsx +0 -41
- package/lib/runtime/components/react/mpx-icon.tsx +0 -102
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* ✘ placeholder-class
|
|
8
8
|
* ✔ disabled
|
|
9
9
|
* ✔ maxlength
|
|
10
|
-
*
|
|
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,
|
|
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
|
|
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 =
|
|
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
|
-
|
|
90
|
-
if (
|
|
91
|
-
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (typeof cursor === 'number') {
|
|
103
|
+
setSelection({ start: cursor, end: cursor });
|
|
92
104
|
}
|
|
93
|
-
else if (
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
207
|
-
|
|
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
|
-
|
|
237
|
-
|
|
264
|
+
onTouchStart: onInputTouchStart,
|
|
265
|
+
onFocus: onInputFocus,
|
|
266
|
+
onBlur: onInputBlur,
|
|
238
267
|
onKeyPress: bindconfirm && onKeyPress,
|
|
239
268
|
onSubmitEditing: bindconfirm && multiline && onSubmitEditing,
|
|
240
|
-
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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;
|
|
@@ -203,11 +203,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
203
203
|
updateScrollOptions(e, { scrollLeft, scrollTop });
|
|
204
204
|
onStartReached(e);
|
|
205
205
|
onEndReached(e);
|
|
206
|
-
|
|
207
|
-
for (const key in intersectionObservers) {
|
|
208
|
-
intersectionObservers[key].throttleMeasure();
|
|
209
|
-
}
|
|
210
|
-
}
|
|
206
|
+
updateIntersection();
|
|
211
207
|
}
|
|
212
208
|
function onScrollEnd(e) {
|
|
213
209
|
const { bindscrollend } = props;
|
|
@@ -226,6 +222,14 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
226
222
|
updateScrollOptions(e, { scrollLeft, scrollTop });
|
|
227
223
|
onStartReached(e);
|
|
228
224
|
onEndReached(e);
|
|
225
|
+
updateIntersection();
|
|
226
|
+
}
|
|
227
|
+
function updateIntersection() {
|
|
228
|
+
if (enableTriggerIntersectionObserver && intersectionObservers) {
|
|
229
|
+
for (const key in intersectionObservers) {
|
|
230
|
+
intersectionObservers[key].throttleMeasure();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
229
233
|
}
|
|
230
234
|
function scrollToOffset(x = 0, y = 0) {
|
|
231
235
|
if (scrollViewRef.current) {
|
|
@@ -284,10 +288,18 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
284
288
|
function onScrollDrag(e) {
|
|
285
289
|
const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
|
|
286
290
|
updateScrollOptions(e, { scrollLeft, scrollTop });
|
|
291
|
+
updateIntersection();
|
|
292
|
+
}
|
|
293
|
+
function onScrollDragStart(e) {
|
|
294
|
+
hasCallScrollToLower.current = false;
|
|
295
|
+
hasCallScrollToUpper.current = false;
|
|
296
|
+
onScrollDrag(e);
|
|
287
297
|
}
|
|
288
298
|
const scrollAdditionalProps = extendObject({
|
|
289
299
|
style: extendObject({}, innerStyle, layoutStyle),
|
|
290
300
|
pinchGestureEnabled: false,
|
|
301
|
+
alwaysBounceVertical: false,
|
|
302
|
+
alwaysBounceHorizontal: false,
|
|
291
303
|
horizontal: scrollX && !scrollY,
|
|
292
304
|
scrollEventThrottle: scrollEventThrottle,
|
|
293
305
|
scrollsToTop: enableBackToTop,
|
|
@@ -298,9 +310,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
298
310
|
onScroll: onScroll,
|
|
299
311
|
onContentSizeChange: onContentSizeChange,
|
|
300
312
|
bindtouchstart: ((enhanced && binddragstart) || bindtouchstart) && onScrollTouchStart,
|
|
301
|
-
bindtouchmove: ((enhanced && binddragging) ||
|
|
313
|
+
bindtouchmove: ((enhanced && binddragging) || bindtouchmove) && onScrollTouchMove,
|
|
302
314
|
bindtouchend: ((enhanced && binddragend) || bindtouchend) && onScrollTouchEnd,
|
|
303
|
-
onScrollBeginDrag:
|
|
315
|
+
onScrollBeginDrag: onScrollDragStart,
|
|
304
316
|
onScrollEndDrag: onScrollDrag,
|
|
305
317
|
onMomentumScrollEnd: onScrollEnd
|
|
306
318
|
}, (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.
|
|
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
|
|
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
|
-
|
|
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;
|