@mpxjs/webpack-plugin 2.10.1 → 2.10.2
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/index.js +11 -1
- package/lib/platform/template/wx/component-config/input.js +1 -1
- package/lib/platform/template/wx/component-config/textarea.js +1 -1
- package/lib/react/processScript.js +3 -2
- package/lib/runtime/components/react/KeyboardAvoidingView.tsx +30 -18
- package/lib/runtime/components/react/context.ts +3 -4
- package/lib/runtime/components/react/dist/KeyboardAvoidingView.jsx +23 -13
- package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-input.jsx +54 -44
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +7 -4
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +4 -3
- package/lib/runtime/components/react/dist/utils.jsx +0 -14
- package/lib/runtime/components/react/mpx-image.tsx +2 -2
- package/lib/runtime/components/react/mpx-input.tsx +66 -54
- package/lib/runtime/components/react/mpx-scroll-view.tsx +8 -4
- package/lib/runtime/components/react/mpx-textarea.tsx +10 -6
- package/lib/runtime/components/react/mpx-web-view.tsx +5 -3
- package/lib/runtime/components/react/utils.tsx +0 -14
- package/lib/template-compiler/compiler.js +2 -2
- package/package.json +4 -4
package/lib/index.js
CHANGED
|
@@ -1598,7 +1598,7 @@ class MpxWebpackPlugin {
|
|
|
1598
1598
|
name: 'MpxWebpackPlugin',
|
|
1599
1599
|
stage: compilation.PROCESS_ASSETS_STAGE_ADDITIONS
|
|
1600
1600
|
}, () => {
|
|
1601
|
-
if (isWeb(mpx.mode)
|
|
1601
|
+
if (isWeb(mpx.mode)) return
|
|
1602
1602
|
|
|
1603
1603
|
if (this.options.generateBuildMap) {
|
|
1604
1604
|
const pagesMap = compilation.__mpx__.pagesMap
|
|
@@ -1637,6 +1637,16 @@ class MpxWebpackPlugin {
|
|
|
1637
1637
|
|
|
1638
1638
|
const originalSource = compilation.assets[chunkFile]
|
|
1639
1639
|
const source = new ConcatSource()
|
|
1640
|
+
|
|
1641
|
+
if (isReact(mpx.mode)) {
|
|
1642
|
+
// 添加 @refresh reset 注释用于在 React HMR 时刷新组件
|
|
1643
|
+
source.add('/* @refresh reset */\n')
|
|
1644
|
+
source.add(originalSource)
|
|
1645
|
+
compilation.assets[chunkFile] = source
|
|
1646
|
+
processedChunk.add(chunk)
|
|
1647
|
+
return
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1640
1650
|
source.add(`\nvar ${globalObject} = {};\n`)
|
|
1641
1651
|
|
|
1642
1652
|
relativeChunks.forEach((relativeChunk, index) => {
|
|
@@ -92,7 +92,7 @@ module.exports = function ({ print }) {
|
|
|
92
92
|
qa: qaPropLog
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
|
-
test: /^(
|
|
95
|
+
test: /^(always-embed|hold-keyboard|safe-password-.+)$/,
|
|
96
96
|
ios: iosPropLog,
|
|
97
97
|
android: androidPropLog
|
|
98
98
|
}
|
|
@@ -78,7 +78,7 @@ module.exports = function ({ print }) {
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
|
-
test: /^(
|
|
81
|
+
test: /^(always-embed|hold-keyboard|disable-default-padding|adjust-keyboard-to|fixed|show-confirm-bar)$/,
|
|
82
82
|
ios: iosPropLog,
|
|
83
83
|
android: androidPropLog
|
|
84
84
|
}
|
|
@@ -15,6 +15,7 @@ module.exports = function (script, {
|
|
|
15
15
|
localPagesMap
|
|
16
16
|
}, callback) {
|
|
17
17
|
let scriptSrcMode = srcMode
|
|
18
|
+
const mode = loaderContext.getMpx().mode
|
|
18
19
|
if (script) {
|
|
19
20
|
scriptSrcMode = script.mode || scriptSrcMode
|
|
20
21
|
} else {
|
|
@@ -26,7 +27,7 @@ module.exports = function (script, {
|
|
|
26
27
|
output += `
|
|
27
28
|
import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPath)}
|
|
28
29
|
import { NavigationContainer, StackActions } from '@react-navigation/native'
|
|
29
|
-
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
|
30
|
+
${mode === 'ios' ? "import { createNativeStackNavigator as createStackNavigator } from '@react-navigation/native-stack'" : "import { createStackNavigator } from '@react-navigation/stack'"}
|
|
30
31
|
import PortalHost from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/portal-host'
|
|
31
32
|
import { useHeaderHeight } from '@react-navigation/elements';
|
|
32
33
|
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
@@ -34,7 +35,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
|
34
35
|
|
|
35
36
|
global.__navigationHelper = {
|
|
36
37
|
NavigationContainer: NavigationContainer,
|
|
37
|
-
createStackNavigator:
|
|
38
|
+
createStackNavigator: createStackNavigator,
|
|
38
39
|
useHeaderHeight: useHeaderHeight,
|
|
39
40
|
StackActions: StackActions,
|
|
40
41
|
GestureHandlerRootView: GestureHandlerRootView,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React, { ReactNode, useContext, useEffect } from 'react'
|
|
1
|
+
import React, { ReactNode, useContext, useEffect, useMemo } from 'react'
|
|
2
2
|
import { DimensionValue, EmitterSubscription, Keyboard, Platform, View, ViewStyle } from 'react-native'
|
|
3
|
-
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated'
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, runOnJS } from 'react-native-reanimated'
|
|
4
|
+
import { GestureDetector, Gesture } from 'react-native-gesture-handler'
|
|
4
5
|
import { KeyboardAvoidContext } from './context'
|
|
5
|
-
import { extendObject } from './utils'
|
|
6
6
|
|
|
7
7
|
type KeyboardAvoidViewProps = {
|
|
8
8
|
children?: ReactNode
|
|
@@ -19,6 +19,17 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
|
|
|
19
19
|
const basic = useSharedValue('auto')
|
|
20
20
|
const keyboardAvoid = useContext(KeyboardAvoidContext)
|
|
21
21
|
|
|
22
|
+
const dismiss = () => {
|
|
23
|
+
Keyboard.isVisible() && Keyboard.dismiss()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const gesture = useMemo(() => {
|
|
27
|
+
return Gesture.Tap()
|
|
28
|
+
.onEnd(() => {
|
|
29
|
+
runOnJS(dismiss)()
|
|
30
|
+
})
|
|
31
|
+
}, [])
|
|
32
|
+
|
|
22
33
|
const animatedStyle = useAnimatedStyle(() => {
|
|
23
34
|
return Object.assign(
|
|
24
35
|
{
|
|
@@ -29,10 +40,9 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
|
|
|
29
40
|
})
|
|
30
41
|
|
|
31
42
|
const resetKeyboard = () => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
43
|
+
if (keyboardAvoid?.current) {
|
|
44
|
+
keyboardAvoid.current = null
|
|
45
|
+
}
|
|
36
46
|
offset.value = withTiming(0, { duration, easing })
|
|
37
47
|
basic.value = 'auto'
|
|
38
48
|
}
|
|
@@ -48,7 +58,7 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
|
|
|
48
58
|
const { ref, cursorSpacing = 0 } = keyboardAvoid.current
|
|
49
59
|
setTimeout(() => {
|
|
50
60
|
ref?.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
|
|
51
|
-
const aboveOffset =
|
|
61
|
+
const aboveOffset = pageY + height - endCoordinates.screenY
|
|
52
62
|
const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing
|
|
53
63
|
const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing)
|
|
54
64
|
const value = aboveOffset > 0 ? belowValue : aboveValue
|
|
@@ -92,16 +102,18 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
|
|
|
92
102
|
}, [keyboardAvoid])
|
|
93
103
|
|
|
94
104
|
return (
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
<GestureDetector gesture={gesture}>
|
|
106
|
+
<View style={style}>
|
|
107
|
+
<Animated.View
|
|
108
|
+
style={[
|
|
109
|
+
contentContainerStyle,
|
|
110
|
+
animatedStyle
|
|
111
|
+
]}
|
|
112
|
+
>
|
|
113
|
+
{children}
|
|
114
|
+
</Animated.View>
|
|
115
|
+
</View>
|
|
116
|
+
</GestureDetector>
|
|
105
117
|
)
|
|
106
118
|
}
|
|
107
119
|
|
|
@@ -5,10 +5,9 @@ export type LabelContextValue = MutableRefObject<{
|
|
|
5
5
|
triggerChange: (evt: NativeSyntheticEvent<TouchEvent>) => void
|
|
6
6
|
}>
|
|
7
7
|
|
|
8
|
-
export type KeyboardAvoidContextValue = MutableRefObject<
|
|
9
|
-
cursorSpacing: number
|
|
10
|
-
|
|
11
|
-
}>
|
|
8
|
+
export type KeyboardAvoidContextValue = MutableRefObject<
|
|
9
|
+
{ cursorSpacing: number, ref: MutableRefObject<any> } | null
|
|
10
|
+
>
|
|
12
11
|
|
|
13
12
|
export interface GroupValue {
|
|
14
13
|
[key: string]: { checked: boolean; setValue: Dispatch<SetStateAction<boolean>> }
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React, { useContext, useEffect } from 'react';
|
|
1
|
+
import React, { useContext, useEffect, useMemo } from 'react';
|
|
2
2
|
import { Keyboard, Platform, View } from 'react-native';
|
|
3
|
-
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, runOnJS } from 'react-native-reanimated';
|
|
4
|
+
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
4
5
|
import { KeyboardAvoidContext } from './context';
|
|
5
|
-
import { extendObject } from './utils';
|
|
6
6
|
const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
7
7
|
const isIOS = Platform.OS === 'ios';
|
|
8
8
|
const duration = isIOS ? 250 : 300;
|
|
@@ -10,16 +10,24 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
10
10
|
const offset = useSharedValue(0);
|
|
11
11
|
const basic = useSharedValue('auto');
|
|
12
12
|
const keyboardAvoid = useContext(KeyboardAvoidContext);
|
|
13
|
+
const dismiss = () => {
|
|
14
|
+
Keyboard.isVisible() && Keyboard.dismiss();
|
|
15
|
+
};
|
|
16
|
+
const gesture = useMemo(() => {
|
|
17
|
+
return Gesture.Tap()
|
|
18
|
+
.onEnd(() => {
|
|
19
|
+
runOnJS(dismiss)();
|
|
20
|
+
});
|
|
21
|
+
}, []);
|
|
13
22
|
const animatedStyle = useAnimatedStyle(() => {
|
|
14
23
|
return Object.assign({
|
|
15
24
|
transform: [{ translateY: -offset.value }]
|
|
16
25
|
}, isIOS ? {} : { flexBasis: basic.value });
|
|
17
26
|
});
|
|
18
27
|
const resetKeyboard = () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
28
|
+
if (keyboardAvoid?.current) {
|
|
29
|
+
keyboardAvoid.current = null;
|
|
30
|
+
}
|
|
23
31
|
offset.value = withTiming(0, { duration, easing });
|
|
24
32
|
basic.value = 'auto';
|
|
25
33
|
};
|
|
@@ -34,7 +42,7 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
34
42
|
const { ref, cursorSpacing = 0 } = keyboardAvoid.current;
|
|
35
43
|
setTimeout(() => {
|
|
36
44
|
ref?.current?.measure((x, y, width, height, pageX, pageY) => {
|
|
37
|
-
const aboveOffset =
|
|
45
|
+
const aboveOffset = pageY + height - endCoordinates.screenY;
|
|
38
46
|
const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing;
|
|
39
47
|
const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing);
|
|
40
48
|
const value = aboveOffset > 0 ? belowValue : aboveValue;
|
|
@@ -77,13 +85,15 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
77
85
|
subscriptions.forEach(subscription => subscription.remove());
|
|
78
86
|
};
|
|
79
87
|
}, [keyboardAvoid]);
|
|
80
|
-
return (<
|
|
81
|
-
<
|
|
88
|
+
return (<GestureDetector gesture={gesture}>
|
|
89
|
+
<View style={style}>
|
|
90
|
+
<Animated.View style={[
|
|
82
91
|
contentContainerStyle,
|
|
83
92
|
animatedStyle
|
|
84
93
|
]}>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
{children}
|
|
95
|
+
</Animated.View>
|
|
96
|
+
</View>
|
|
97
|
+
</GestureDetector>);
|
|
88
98
|
};
|
|
89
99
|
export default KeyboardAvoidingView;
|
|
@@ -272,7 +272,7 @@ const Image = forwardRef((props, ref) => {
|
|
|
272
272
|
uri: src,
|
|
273
273
|
onLayout: onSvgLoad,
|
|
274
274
|
onError: binderror && onSvgError,
|
|
275
|
-
style: extendObject({ transformOrigin: 'top
|
|
275
|
+
style: extendObject({ transformOrigin: 'left top' }, modeStyle)
|
|
276
276
|
}));
|
|
277
277
|
const BaseImage = renderImage(extendObject({
|
|
278
278
|
source: { uri: src },
|
|
@@ -280,7 +280,7 @@ const Image = forwardRef((props, ref) => {
|
|
|
280
280
|
onLoad: bindload && onImageLoad,
|
|
281
281
|
onError: binderror && onImageError,
|
|
282
282
|
style: extendObject({
|
|
283
|
-
transformOrigin: 'top
|
|
283
|
+
transformOrigin: 'left top',
|
|
284
284
|
width: isCropMode ? imageWidth : '100%',
|
|
285
285
|
height: isCropMode ? imageHeight : '100%'
|
|
286
286
|
}, isCropMode ? modeStyle : {})
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ✔ password
|
|
5
5
|
* ✔ placeholder
|
|
6
6
|
* - placeholder-style: Only support color.
|
|
7
|
-
*
|
|
7
|
+
* - placeholder-class: Only support color.
|
|
8
8
|
* ✔ disabled
|
|
9
9
|
* ✔ maxlength
|
|
10
10
|
* ✔ cursor-spacing
|
|
@@ -40,7 +40,7 @@
|
|
|
40
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
|
-
import {
|
|
43
|
+
import { useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils';
|
|
44
44
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
45
45
|
import useNodesRef from './useNodesRef';
|
|
46
46
|
import { FormContext, KeyboardAvoidContext } from './context';
|
|
@@ -54,7 +54,7 @@ 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, '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,
|
|
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);
|
|
@@ -76,7 +76,6 @@ const Input = forwardRef((props, ref) => {
|
|
|
76
76
|
};
|
|
77
77
|
const keyboardType = keyboardTypeMap[type];
|
|
78
78
|
const defaultValue = parseValue(value);
|
|
79
|
-
const placeholderTextColor = parseInlineStyle(placeholderStyle)?.color;
|
|
80
79
|
const textAlignVertical = multiline ? 'top' : 'auto';
|
|
81
80
|
const tmpValue = useRef(defaultValue);
|
|
82
81
|
const cursorIndex = useRef(0);
|
|
@@ -85,7 +84,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
85
84
|
const [contentHeight, setContentHeight] = useState(0);
|
|
86
85
|
const [selection, setSelection] = useState({ start: -1, end: -1 });
|
|
87
86
|
const styleObj = extendObject({ padding: 0, backgroundColor: '#fff' }, style, multiline && autoHeight
|
|
88
|
-
? { minHeight: Math.max(style?.minHeight || 35, contentHeight) }
|
|
87
|
+
? { height: 'auto', minHeight: Math.max(style?.minHeight || 35, contentHeight) }
|
|
89
88
|
: {});
|
|
90
89
|
const { hasSelfPercent, normalStyle, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
91
90
|
const nodeRef = useRef(null);
|
|
@@ -106,44 +105,54 @@ const Input = forwardRef((props, ref) => {
|
|
|
106
105
|
setSelection({ start: selectionStart, end: selectionEnd });
|
|
107
106
|
}
|
|
108
107
|
}, [cursor, selectionStart, selectionEnd]);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
// have not selection on the Android platformg
|
|
109
|
+
const getCursorIndex = (changedSelection, prevValue, curValue) => {
|
|
110
|
+
if (changedSelection)
|
|
111
|
+
return changedSelection.end;
|
|
112
|
+
if (!prevValue || !curValue || prevValue.length === curValue.length)
|
|
113
|
+
return curValue.length;
|
|
114
|
+
const prevStr = prevValue.substring(cursorIndex.current);
|
|
115
|
+
const curStr = curValue.substring(cursorIndex.current);
|
|
116
|
+
return cursorIndex.current + curStr.length - prevStr.length;
|
|
114
117
|
};
|
|
115
118
|
const onChange = (evt) => {
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
const { text, selection } = evt.nativeEvent;
|
|
120
|
+
// will trigger twice on the Android platformg, prevent the second trigger
|
|
121
|
+
if (tmpValue.current === text)
|
|
118
122
|
return;
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
const index = getCursorIndex(selection, tmpValue.current, text);
|
|
124
|
+
tmpValue.current = text;
|
|
125
|
+
cursorIndex.current = index;
|
|
126
|
+
if (bindinput) {
|
|
127
|
+
const result = bindinput(getCustomEvent('input', evt, {
|
|
128
|
+
detail: {
|
|
129
|
+
value: tmpValue.current,
|
|
130
|
+
cursor: cursorIndex.current
|
|
131
|
+
},
|
|
132
|
+
layoutRef
|
|
133
|
+
}, props));
|
|
134
|
+
if (typeof result === 'string') {
|
|
135
|
+
tmpValue.current = result;
|
|
136
|
+
setInputValue(result);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
setInputValue(tmpValue.current);
|
|
140
|
+
}
|
|
129
141
|
}
|
|
130
142
|
else {
|
|
131
143
|
setInputValue(tmpValue.current);
|
|
132
144
|
}
|
|
133
145
|
};
|
|
134
146
|
const setKeyboardAvoidContext = () => {
|
|
135
|
-
if (adjustPosition && keyboardAvoid
|
|
136
|
-
|
|
137
|
-
cursorSpacing,
|
|
138
|
-
ref: nodeRef
|
|
139
|
-
});
|
|
147
|
+
if (adjustPosition && keyboardAvoid) {
|
|
148
|
+
keyboardAvoid.current = { cursorSpacing, ref: nodeRef };
|
|
140
149
|
}
|
|
141
150
|
};
|
|
142
|
-
const
|
|
151
|
+
const onTouchStart = () => {
|
|
143
152
|
// sometimes the focus event occurs later than the keyboardWillShow event
|
|
144
153
|
setKeyboardAvoidContext();
|
|
145
154
|
};
|
|
146
|
-
const
|
|
155
|
+
const onFocus = (evt) => {
|
|
147
156
|
setKeyboardAvoidContext();
|
|
148
157
|
bindfocus && bindfocus(getCustomEvent('focus', evt, {
|
|
149
158
|
detail: {
|
|
@@ -152,7 +161,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
152
161
|
layoutRef
|
|
153
162
|
}, props));
|
|
154
163
|
};
|
|
155
|
-
const
|
|
164
|
+
const onBlur = (evt) => {
|
|
156
165
|
bindblur && bindblur(getCustomEvent('blur', evt, {
|
|
157
166
|
detail: {
|
|
158
167
|
value: tmpValue.current || '',
|
|
@@ -179,11 +188,14 @@ const Input = forwardRef((props, ref) => {
|
|
|
179
188
|
}, props));
|
|
180
189
|
};
|
|
181
190
|
const onSelectionChange = (evt) => {
|
|
182
|
-
|
|
191
|
+
const { selection } = evt.nativeEvent;
|
|
192
|
+
const { start, end } = selection;
|
|
193
|
+
cursorIndex.current = start;
|
|
194
|
+
setSelection(selection);
|
|
183
195
|
bindselectionchange && bindselectionchange(getCustomEvent('selectionchange', evt, {
|
|
184
196
|
detail: {
|
|
185
|
-
selectionStart:
|
|
186
|
-
selectionEnd:
|
|
197
|
+
selectionStart: start,
|
|
198
|
+
selectionEnd: end
|
|
187
199
|
},
|
|
188
200
|
layoutRef
|
|
189
201
|
}, props));
|
|
@@ -252,24 +264,22 @@ const Input = forwardRef((props, ref) => {
|
|
|
252
264
|
maxLength: maxlength === -1 ? undefined : maxlength,
|
|
253
265
|
editable: !disabled,
|
|
254
266
|
autoFocus: !!autoFocus || !!focus,
|
|
255
|
-
returnKeyType: confirmType,
|
|
256
267
|
selection: selection,
|
|
257
268
|
selectionColor: cursorColor,
|
|
258
269
|
blurOnSubmit: !multiline && !confirmHold,
|
|
259
270
|
underlineColorAndroid: 'rgba(0,0,0,0)',
|
|
260
271
|
textAlignVertical: textAlignVertical,
|
|
261
|
-
placeholderTextColor:
|
|
272
|
+
placeholderTextColor: placeholderStyle?.color,
|
|
262
273
|
multiline: !!multiline
|
|
263
|
-
}, layoutProps, {
|
|
264
|
-
onTouchStart
|
|
265
|
-
onFocus
|
|
266
|
-
onBlur
|
|
274
|
+
}, !!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType }, layoutProps, {
|
|
275
|
+
onTouchStart,
|
|
276
|
+
onFocus,
|
|
277
|
+
onBlur,
|
|
278
|
+
onChange,
|
|
279
|
+
onSelectionChange,
|
|
280
|
+
onContentSizeChange,
|
|
267
281
|
onKeyPress: bindconfirm && onKeyPress,
|
|
268
|
-
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
269
|
-
onSelectionChange: onSelectionChange,
|
|
270
|
-
onTextInput: onTextInput,
|
|
271
|
-
onChange: onChange,
|
|
272
|
-
onContentSizeChange: onContentSizeChange
|
|
282
|
+
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
273
283
|
}), [
|
|
274
284
|
'type',
|
|
275
285
|
'password',
|
|
@@ -41,7 +41,7 @@ import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, ext
|
|
|
41
41
|
import { IntersectionObserverContext, ScrollViewContext } from './context';
|
|
42
42
|
const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
43
43
|
const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
|
|
44
|
-
const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, __selectRef } = props;
|
|
44
|
+
const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, __selectRef } = props;
|
|
45
45
|
const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
|
|
46
46
|
const waitForHandlers = flatGesture(waitFor);
|
|
47
47
|
const [refreshing, setRefreshing] = useState(true);
|
|
@@ -73,7 +73,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
73
73
|
pagingEnabled,
|
|
74
74
|
fastDeceleration: false,
|
|
75
75
|
decelerationDisabled: false,
|
|
76
|
-
scrollTo
|
|
76
|
+
scrollTo
|
|
77
77
|
},
|
|
78
78
|
gestureRef: scrollViewRef
|
|
79
79
|
});
|
|
@@ -112,6 +112,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
112
112
|
}
|
|
113
113
|
firstScrollIntoViewChange.current = true;
|
|
114
114
|
}, [scrollIntoView]);
|
|
115
|
+
function scrollTo({ top = 0, left = 0, animated = false }) {
|
|
116
|
+
scrollToOffset(left, top, animated);
|
|
117
|
+
}
|
|
115
118
|
function handleScrollIntoView() {
|
|
116
119
|
const refs = __selectRef(`#${scrollIntoView}`, 'node');
|
|
117
120
|
if (!refs)
|
|
@@ -230,9 +233,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
230
233
|
}
|
|
231
234
|
}
|
|
232
235
|
}
|
|
233
|
-
function scrollToOffset(x = 0, y = 0) {
|
|
236
|
+
function scrollToOffset(x = 0, y = 0, animated = scrollWithAnimation) {
|
|
234
237
|
if (scrollViewRef.current) {
|
|
235
|
-
scrollViewRef.current.scrollTo({ x, y, animated
|
|
238
|
+
scrollViewRef.current.scrollTo({ x, y, animated });
|
|
236
239
|
scrollOptions.current.scrollLeft = x;
|
|
237
240
|
scrollOptions.current.scrollTop = y;
|
|
238
241
|
snapScrollLeft.current = x;
|
|
@@ -3,33 +3,33 @@
|
|
|
3
3
|
* Subtraction:
|
|
4
4
|
* type, password, confirm-hold
|
|
5
5
|
* Addition:
|
|
6
|
-
*
|
|
6
|
+
* ✔ confirm-type
|
|
7
7
|
* ✔ auto-height
|
|
8
8
|
* ✘ fixed
|
|
9
9
|
* ✘ show-confirm-bar
|
|
10
10
|
* ✔ bindlinechange: No `heightRpx` info.
|
|
11
11
|
*/
|
|
12
12
|
import { forwardRef, createElement } from 'react';
|
|
13
|
-
import { Keyboard } from 'react-native';
|
|
14
13
|
import Input from './mpx-input';
|
|
15
14
|
import { omit, extendObject } from './utils';
|
|
16
15
|
const DEFAULT_TEXTAREA_WIDTH = 300;
|
|
17
16
|
const DEFAULT_TEXTAREA_HEIGHT = 150;
|
|
18
17
|
const Textarea = forwardRef((props, ref) => {
|
|
19
|
-
const { style = {} } = props;
|
|
18
|
+
const { style = {}, 'confirm-type': confirmType = 'return' } = props;
|
|
20
19
|
const restProps = omit(props, [
|
|
21
20
|
'ref',
|
|
22
21
|
'type',
|
|
23
22
|
'style',
|
|
24
23
|
'password',
|
|
25
24
|
'multiline',
|
|
25
|
+
'confirm-type',
|
|
26
26
|
'confirm-hold'
|
|
27
27
|
]);
|
|
28
28
|
return createElement(Input, extendObject(restProps, {
|
|
29
|
-
ref
|
|
29
|
+
ref,
|
|
30
|
+
confirmType,
|
|
30
31
|
multiline: true,
|
|
31
|
-
|
|
32
|
-
bindblur: () => Keyboard.dismiss(),
|
|
32
|
+
'confirm-type': confirmType,
|
|
33
33
|
style: extendObject({
|
|
34
34
|
width: DEFAULT_TEXTAREA_WIDTH,
|
|
35
35
|
height: DEFAULT_TEXTAREA_HEIGHT
|
|
@@ -155,8 +155,8 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
155
155
|
switch (type) {
|
|
156
156
|
case 'setTitle':
|
|
157
157
|
{ // case下不允许直接声明,包个块解决该问题
|
|
158
|
-
const title = postData._documentTitle;
|
|
159
|
-
if (title) {
|
|
158
|
+
const title = postData._documentTitle?.trim();
|
|
159
|
+
if (title !== undefined) {
|
|
160
160
|
navigation && navigation.setOptions({ title });
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -252,6 +252,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
252
252
|
};
|
|
253
253
|
const onLoadEnd = function (res) {
|
|
254
254
|
if (__mpx_mode__ === 'android') {
|
|
255
|
+
res.persist();
|
|
255
256
|
setTimeout(() => {
|
|
256
257
|
onLoadEndHandle(res);
|
|
257
258
|
}, 0);
|
|
@@ -282,7 +283,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
282
283
|
<View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
|
|
283
284
|
<View style={styles.loadErrorButton} onTouchEnd={_reload}><Text style={{ fontSize: 12, color: '#666666' }}>{currentErrorText.button}</Text></View>
|
|
284
285
|
</View>)
|
|
285
|
-
: (<WebView style={defaultWebViewStyle} source={{ uri: src }} ref={webViewRef} javaScriptEnabled={true} onNavigationStateChange={_changeUrl} onMessage={_message} injectedJavaScript={injectedJavaScript} onLoadProgress={_onLoadProgress} onLoadEnd={onLoadEnd} onHttpError={onHttpError} onError={onError} onLoadStart={onLoadStart} allowsBackForwardNavigationGestures={
|
|
286
|
+
: (<WebView style={defaultWebViewStyle} pointerEvents={isLoaded ? 'auto' : 'none'} source={{ uri: src }} ref={webViewRef} javaScriptEnabled={true} onNavigationStateChange={_changeUrl} onMessage={_message} injectedJavaScript={injectedJavaScript} onLoadProgress={_onLoadProgress} onLoadEnd={onLoadEnd} onHttpError={onHttpError} onError={onError} onLoadStart={onLoadStart} allowsBackForwardNavigationGestures={true}></WebView>)}
|
|
286
287
|
</Portal>);
|
|
287
288
|
});
|
|
288
289
|
_WebView.displayName = 'MpxWebview';
|
|
@@ -67,20 +67,6 @@ export const useUpdateEffect = (effect, deps) => {
|
|
|
67
67
|
}
|
|
68
68
|
}, deps);
|
|
69
69
|
};
|
|
70
|
-
/**
|
|
71
|
-
* 解析行内样式
|
|
72
|
-
* @param inlineStyle
|
|
73
|
-
* @returns
|
|
74
|
-
*/
|
|
75
|
-
export const parseInlineStyle = (inlineStyle = '') => {
|
|
76
|
-
return inlineStyle.split(';').reduce((styleObj, style) => {
|
|
77
|
-
const [k, v, ...rest] = style.split(':');
|
|
78
|
-
if (rest.length || !v || !k)
|
|
79
|
-
return styleObj;
|
|
80
|
-
const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase());
|
|
81
|
-
return extendObject(styleObj, { [key]: global.__formatValue(v.trim()) });
|
|
82
|
-
}, {});
|
|
83
|
-
};
|
|
84
70
|
export const parseUrl = (cssUrl = '') => {
|
|
85
71
|
if (!cssUrl)
|
|
86
72
|
return;
|
|
@@ -411,7 +411,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
|
|
|
411
411
|
onLayout: onSvgLoad,
|
|
412
412
|
onError: binderror && onSvgError,
|
|
413
413
|
style: extendObject(
|
|
414
|
-
{ transformOrigin: 'top
|
|
414
|
+
{ transformOrigin: 'left top' },
|
|
415
415
|
modeStyle
|
|
416
416
|
)
|
|
417
417
|
})
|
|
@@ -426,7 +426,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
|
|
|
426
426
|
onError: binderror && onImageError,
|
|
427
427
|
style: extendObject(
|
|
428
428
|
{
|
|
429
|
-
transformOrigin: 'top
|
|
429
|
+
transformOrigin: 'left top',
|
|
430
430
|
width: isCropMode ? imageWidth : '100%',
|
|
431
431
|
height: isCropMode ? imageHeight : '100%'
|
|
432
432
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ✔ password
|
|
5
5
|
* ✔ placeholder
|
|
6
6
|
* - placeholder-style: Only support color.
|
|
7
|
-
*
|
|
7
|
+
* - placeholder-class: Only support color.
|
|
8
8
|
* ✔ disabled
|
|
9
9
|
* ✔ maxlength
|
|
10
10
|
* ✔ cursor-spacing
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
TextInputSubmitEditingEventData
|
|
55
55
|
} from 'react-native'
|
|
56
56
|
import { warn } from '@mpxjs/utils'
|
|
57
|
-
import {
|
|
57
|
+
import { useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils'
|
|
58
58
|
import useInnerProps, { getCustomEvent } from './getInnerListeners'
|
|
59
59
|
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
60
60
|
import { FormContext, FormFieldValue, KeyboardAvoidContext } from './context'
|
|
@@ -73,6 +73,8 @@ type InputStyle = Omit<
|
|
|
73
73
|
|
|
74
74
|
type Type = 'text' | 'number' | 'idcard' | 'digit'
|
|
75
75
|
|
|
76
|
+
type ConfirmType = 'done' | 'send' | 'search' | 'next' | 'go' | 'return'
|
|
77
|
+
|
|
76
78
|
export interface InputProps {
|
|
77
79
|
name?: string
|
|
78
80
|
style?: InputStyle & Record<string, any>
|
|
@@ -85,13 +87,13 @@ export interface InputProps {
|
|
|
85
87
|
maxlength?: number
|
|
86
88
|
'auto-focus'?: boolean
|
|
87
89
|
focus?: boolean
|
|
88
|
-
'confirm-type'?:
|
|
90
|
+
'confirm-type'?: ConfirmType
|
|
89
91
|
'confirm-hold'?: boolean
|
|
90
92
|
cursor?: number
|
|
91
93
|
'cursor-color'?: string
|
|
92
94
|
'selection-start'?: number
|
|
93
95
|
'selection-end'?: number
|
|
94
|
-
'placeholder-style'?: string
|
|
96
|
+
'placeholder-style'?: { color?: string }
|
|
95
97
|
'enable-offset'?: boolean,
|
|
96
98
|
'enable-var'?: boolean
|
|
97
99
|
'external-var-context'?: Record<string, any>
|
|
@@ -133,7 +135,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
133
135
|
type = 'text',
|
|
134
136
|
value,
|
|
135
137
|
password,
|
|
136
|
-
'placeholder-style': placeholderStyle,
|
|
138
|
+
'placeholder-style': placeholderStyle = {},
|
|
137
139
|
disabled,
|
|
138
140
|
maxlength = 140,
|
|
139
141
|
'cursor-spacing': cursorSpacing = 0,
|
|
@@ -185,10 +187,9 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
185
187
|
|
|
186
188
|
const keyboardType = keyboardTypeMap[type]
|
|
187
189
|
const defaultValue = parseValue(value)
|
|
188
|
-
const placeholderTextColor = parseInlineStyle(placeholderStyle)?.color
|
|
189
190
|
const textAlignVertical = multiline ? 'top' : 'auto'
|
|
190
191
|
|
|
191
|
-
const tmpValue = useRef<string
|
|
192
|
+
const tmpValue = useRef<string>(defaultValue)
|
|
192
193
|
const cursorIndex = useRef<number>(0)
|
|
193
194
|
const lineCount = useRef<number>(0)
|
|
194
195
|
|
|
@@ -200,7 +201,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
200
201
|
{ padding: 0, backgroundColor: '#fff' },
|
|
201
202
|
style,
|
|
202
203
|
multiline && autoHeight
|
|
203
|
-
? { minHeight: Math.max((style as any)?.minHeight || 35, contentHeight) }
|
|
204
|
+
? { height: 'auto', minHeight: Math.max((style as any)?.minHeight || 35, contentHeight) }
|
|
204
205
|
: {}
|
|
205
206
|
)
|
|
206
207
|
|
|
@@ -232,55 +233,64 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
232
233
|
}
|
|
233
234
|
}, [cursor, selectionStart, selectionEnd])
|
|
234
235
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
236
|
+
// have not selection on the Android platformg
|
|
237
|
+
const getCursorIndex = (
|
|
238
|
+
changedSelection: TextInputSelectionChangeEventData['selection'] | undefined,
|
|
239
|
+
prevValue: string,
|
|
240
|
+
curValue: string
|
|
241
|
+
) => {
|
|
242
|
+
if (changedSelection) return changedSelection.end
|
|
243
|
+
if (!prevValue || !curValue || prevValue.length === curValue.length) return curValue.length
|
|
244
|
+
const prevStr = prevValue.substring(cursorIndex.current)
|
|
245
|
+
const curStr = curValue.substring(cursorIndex.current)
|
|
246
|
+
return cursorIndex.current + curStr.length - prevStr.length
|
|
242
247
|
}
|
|
243
248
|
|
|
244
|
-
const onChange = (evt: NativeSyntheticEvent<TextInputChangeEventData>) => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
const onChange = (evt: NativeSyntheticEvent<TextInputChangeEventData & TextInputSelectionChangeEventData>) => {
|
|
250
|
+
const { text, selection } = evt.nativeEvent
|
|
251
|
+
// will trigger twice on the Android platformg, prevent the second trigger
|
|
252
|
+
if (tmpValue.current === text) return
|
|
253
|
+
const index = getCursorIndex(selection, tmpValue.current, text)
|
|
254
|
+
tmpValue.current = text
|
|
255
|
+
cursorIndex.current = index
|
|
256
|
+
if (bindinput) {
|
|
257
|
+
const result = bindinput(
|
|
258
|
+
getCustomEvent(
|
|
259
|
+
'input',
|
|
260
|
+
evt,
|
|
261
|
+
{
|
|
262
|
+
detail: {
|
|
263
|
+
value: tmpValue.current,
|
|
264
|
+
cursor: cursorIndex.current
|
|
265
|
+
},
|
|
266
|
+
layoutRef
|
|
255
267
|
},
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
props
|
|
268
|
+
props
|
|
269
|
+
)
|
|
259
270
|
)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
271
|
+
if (typeof result === 'string') {
|
|
272
|
+
tmpValue.current = result
|
|
273
|
+
setInputValue(result)
|
|
274
|
+
} else {
|
|
275
|
+
setInputValue(tmpValue.current)
|
|
276
|
+
}
|
|
264
277
|
} else {
|
|
265
278
|
setInputValue(tmpValue.current)
|
|
266
279
|
}
|
|
267
280
|
}
|
|
268
281
|
|
|
269
282
|
const setKeyboardAvoidContext = () => {
|
|
270
|
-
if (adjustPosition && keyboardAvoid
|
|
271
|
-
|
|
272
|
-
cursorSpacing,
|
|
273
|
-
ref: nodeRef
|
|
274
|
-
})
|
|
283
|
+
if (adjustPosition && keyboardAvoid) {
|
|
284
|
+
keyboardAvoid.current = { cursorSpacing, ref: nodeRef }
|
|
275
285
|
}
|
|
276
286
|
}
|
|
277
287
|
|
|
278
|
-
const
|
|
288
|
+
const onTouchStart = () => {
|
|
279
289
|
// sometimes the focus event occurs later than the keyboardWillShow event
|
|
280
290
|
setKeyboardAvoidContext()
|
|
281
291
|
}
|
|
282
292
|
|
|
283
|
-
const
|
|
293
|
+
const onFocus = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
284
294
|
setKeyboardAvoidContext()
|
|
285
295
|
bindfocus && bindfocus(
|
|
286
296
|
getCustomEvent(
|
|
@@ -297,7 +307,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
297
307
|
)
|
|
298
308
|
}
|
|
299
309
|
|
|
300
|
-
const
|
|
310
|
+
const onBlur = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
301
311
|
bindblur && bindblur(
|
|
302
312
|
getCustomEvent(
|
|
303
313
|
'blur',
|
|
@@ -348,15 +358,18 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
348
358
|
}
|
|
349
359
|
|
|
350
360
|
const onSelectionChange = (evt: NativeSyntheticEvent<TextInputSelectionChangeEventData>) => {
|
|
351
|
-
|
|
361
|
+
const { selection } = evt.nativeEvent
|
|
362
|
+
const { start, end } = selection
|
|
363
|
+
cursorIndex.current = start
|
|
364
|
+
setSelection(selection)
|
|
352
365
|
bindselectionchange && bindselectionchange(
|
|
353
366
|
getCustomEvent(
|
|
354
367
|
'selectionchange',
|
|
355
368
|
evt,
|
|
356
369
|
{
|
|
357
370
|
detail: {
|
|
358
|
-
selectionStart:
|
|
359
|
-
selectionEnd:
|
|
371
|
+
selectionStart: start,
|
|
372
|
+
selectionEnd: end
|
|
360
373
|
},
|
|
361
374
|
layoutRef
|
|
362
375
|
},
|
|
@@ -444,26 +457,25 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
|
|
|
444
457
|
maxLength: maxlength === -1 ? undefined : maxlength,
|
|
445
458
|
editable: !disabled,
|
|
446
459
|
autoFocus: !!autoFocus || !!focus,
|
|
447
|
-
returnKeyType: confirmType,
|
|
448
460
|
selection: selection,
|
|
449
461
|
selectionColor: cursorColor,
|
|
450
462
|
blurOnSubmit: !multiline && !confirmHold,
|
|
451
463
|
underlineColorAndroid: 'rgba(0,0,0,0)',
|
|
452
464
|
textAlignVertical: textAlignVertical,
|
|
453
|
-
placeholderTextColor:
|
|
465
|
+
placeholderTextColor: placeholderStyle?.color,
|
|
454
466
|
multiline: !!multiline
|
|
455
467
|
},
|
|
468
|
+
!!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType },
|
|
456
469
|
layoutProps,
|
|
457
470
|
{
|
|
458
|
-
onTouchStart
|
|
459
|
-
onFocus
|
|
460
|
-
onBlur
|
|
471
|
+
onTouchStart,
|
|
472
|
+
onFocus,
|
|
473
|
+
onBlur,
|
|
474
|
+
onChange,
|
|
475
|
+
onSelectionChange,
|
|
476
|
+
onContentSizeChange,
|
|
461
477
|
onKeyPress: bindconfirm && onKeyPress,
|
|
462
|
-
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
463
|
-
onSelectionChange: onSelectionChange,
|
|
464
|
-
onTextInput: onTextInput,
|
|
465
|
-
onChange: onChange,
|
|
466
|
-
onContentSizeChange: onContentSizeChange
|
|
478
|
+
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
467
479
|
}
|
|
468
480
|
),
|
|
469
481
|
[
|
|
@@ -124,7 +124,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
124
124
|
'paging-enabled': pagingEnabled = false,
|
|
125
125
|
'upper-threshold': upperThreshold = 50,
|
|
126
126
|
'lower-threshold': lowerThreshold = 50,
|
|
127
|
-
'scroll-with-animation': scrollWithAnimation,
|
|
127
|
+
'scroll-with-animation': scrollWithAnimation = false,
|
|
128
128
|
'refresher-enabled': refresherEnabled,
|
|
129
129
|
'refresher-default-style': refresherDefaultStyle,
|
|
130
130
|
'refresher-background': refresherBackground,
|
|
@@ -189,7 +189,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
189
189
|
pagingEnabled,
|
|
190
190
|
fastDeceleration: false,
|
|
191
191
|
decelerationDisabled: false,
|
|
192
|
-
scrollTo
|
|
192
|
+
scrollTo
|
|
193
193
|
},
|
|
194
194
|
gestureRef: scrollViewRef
|
|
195
195
|
})
|
|
@@ -236,6 +236,10 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
236
236
|
firstScrollIntoViewChange.current = true
|
|
237
237
|
}, [scrollIntoView])
|
|
238
238
|
|
|
239
|
+
function scrollTo ({ top = 0, left = 0, animated = false } : { top?: number; left?: number; animated?: boolean }) {
|
|
240
|
+
scrollToOffset(left, top, animated)
|
|
241
|
+
}
|
|
242
|
+
|
|
239
243
|
function handleScrollIntoView () {
|
|
240
244
|
const refs = __selectRef!(`#${scrollIntoView}`, 'node')
|
|
241
245
|
if (!refs) return
|
|
@@ -371,9 +375,9 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
|
|
|
371
375
|
}
|
|
372
376
|
}
|
|
373
377
|
}
|
|
374
|
-
function scrollToOffset (x = 0, y = 0) {
|
|
378
|
+
function scrollToOffset (x = 0, y = 0, animated = scrollWithAnimation) {
|
|
375
379
|
if (scrollViewRef.current) {
|
|
376
|
-
scrollViewRef.current.scrollTo({ x, y, animated
|
|
380
|
+
scrollViewRef.current.scrollTo({ x, y, animated })
|
|
377
381
|
scrollOptions.current.scrollLeft = x
|
|
378
382
|
scrollOptions.current.scrollTop = y
|
|
379
383
|
snapScrollLeft.current = x
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* Subtraction:
|
|
4
4
|
* type, password, confirm-hold
|
|
5
5
|
* Addition:
|
|
6
|
-
*
|
|
6
|
+
* ✔ confirm-type
|
|
7
7
|
* ✔ auto-height
|
|
8
8
|
* ✘ fixed
|
|
9
9
|
* ✘ show-confirm-bar
|
|
10
10
|
* ✔ bindlinechange: No `heightRpx` info.
|
|
11
11
|
*/
|
|
12
12
|
import { JSX, forwardRef, createElement } from 'react'
|
|
13
|
-
import {
|
|
13
|
+
import { TextInput } from 'react-native'
|
|
14
14
|
import Input, { InputProps, PrivateInputProps } from './mpx-input'
|
|
15
15
|
import { omit, extendObject } from './utils'
|
|
16
16
|
import { HandlerRef } from './useNodesRef'
|
|
@@ -25,7 +25,10 @@ const DEFAULT_TEXTAREA_HEIGHT = 150
|
|
|
25
25
|
|
|
26
26
|
const Textarea = forwardRef<HandlerRef<TextInput, TextareProps>, TextareProps>(
|
|
27
27
|
(props, ref): JSX.Element => {
|
|
28
|
-
const {
|
|
28
|
+
const {
|
|
29
|
+
style = {},
|
|
30
|
+
'confirm-type': confirmType = 'return'
|
|
31
|
+
} = props
|
|
29
32
|
|
|
30
33
|
const restProps = omit(props, [
|
|
31
34
|
'ref',
|
|
@@ -33,16 +36,17 @@ const Textarea = forwardRef<HandlerRef<TextInput, TextareProps>, TextareProps>(
|
|
|
33
36
|
'style',
|
|
34
37
|
'password',
|
|
35
38
|
'multiline',
|
|
39
|
+
'confirm-type',
|
|
36
40
|
'confirm-hold'
|
|
37
41
|
])
|
|
38
42
|
|
|
39
43
|
return createElement(
|
|
40
44
|
Input,
|
|
41
45
|
extendObject(restProps, {
|
|
42
|
-
ref
|
|
46
|
+
ref,
|
|
47
|
+
confirmType,
|
|
43
48
|
multiline: true,
|
|
44
|
-
|
|
45
|
-
bindblur: () => Keyboard.dismiss(),
|
|
49
|
+
'confirm-type': confirmType,
|
|
46
50
|
style: extendObject({
|
|
47
51
|
width: DEFAULT_TEXTAREA_WIDTH,
|
|
48
52
|
height: DEFAULT_TEXTAREA_HEIGHT
|
|
@@ -207,8 +207,8 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
207
207
|
switch (type) {
|
|
208
208
|
case 'setTitle':
|
|
209
209
|
{ // case下不允许直接声明,包个块解决该问题
|
|
210
|
-
const title = postData._documentTitle
|
|
211
|
-
if (title) {
|
|
210
|
+
const title = postData._documentTitle?.trim()
|
|
211
|
+
if (title !== undefined) {
|
|
212
212
|
navigation && navigation.setOptions({ title })
|
|
213
213
|
}
|
|
214
214
|
}
|
|
@@ -303,6 +303,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
303
303
|
}
|
|
304
304
|
const onLoadEnd = function (res: WebViewEvent) {
|
|
305
305
|
if (__mpx_mode__ === 'android') {
|
|
306
|
+
res.persist()
|
|
306
307
|
setTimeout(() => {
|
|
307
308
|
onLoadEndHandle(res)
|
|
308
309
|
}, 0)
|
|
@@ -338,6 +339,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
338
339
|
)
|
|
339
340
|
: (<WebView
|
|
340
341
|
style={ defaultWebViewStyle }
|
|
342
|
+
pointerEvents={ isLoaded ? 'auto' : 'none' }
|
|
341
343
|
source={{ uri: src }}
|
|
342
344
|
ref={webViewRef}
|
|
343
345
|
javaScriptEnabled={true}
|
|
@@ -349,7 +351,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
349
351
|
onHttpError={onHttpError}
|
|
350
352
|
onError={onError}
|
|
351
353
|
onLoadStart={onLoadStart}
|
|
352
|
-
allowsBackForwardNavigationGestures={
|
|
354
|
+
allowsBackForwardNavigationGestures={true}
|
|
353
355
|
></WebView>)}
|
|
354
356
|
</Portal>
|
|
355
357
|
)
|
|
@@ -80,20 +80,6 @@ export const useUpdateEffect = (effect: any, deps: any) => {
|
|
|
80
80
|
}, deps)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
/**
|
|
84
|
-
* 解析行内样式
|
|
85
|
-
* @param inlineStyle
|
|
86
|
-
* @returns
|
|
87
|
-
*/
|
|
88
|
-
export const parseInlineStyle = (inlineStyle = ''): Record<string, string> => {
|
|
89
|
-
return inlineStyle.split(';').reduce((styleObj, style) => {
|
|
90
|
-
const [k, v, ...rest] = style.split(':')
|
|
91
|
-
if (rest.length || !v || !k) return styleObj
|
|
92
|
-
const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase())
|
|
93
|
-
return extendObject(styleObj, { [key]: global.__formatValue(v.trim()) })
|
|
94
|
-
}, {})
|
|
95
|
-
}
|
|
96
|
-
|
|
97
83
|
export const parseUrl = (cssUrl = '') => {
|
|
98
84
|
if (!cssUrl) return
|
|
99
85
|
const match = cssUrl.match(URL_REGEX)
|
|
@@ -38,7 +38,7 @@ const endTag = new RegExp(('^<\\/' + qnameCapture + '[^>]*>'))
|
|
|
38
38
|
const doctype = /^<!DOCTYPE [^>]+>/i
|
|
39
39
|
const comment = /^<!--/
|
|
40
40
|
const conditionalComment = /^<!\[/
|
|
41
|
-
const specialClassReg = /^mpx-((cover-)?view|button|navigator|picker-view)$/
|
|
41
|
+
const specialClassReg = /^mpx-((cover-)?view|button|navigator|picker-view|input|textarea)$/
|
|
42
42
|
let IS_REGEX_CAPTURING_BROKEN = false
|
|
43
43
|
'x'.replace(/x(.)?/g, function (m, g) {
|
|
44
44
|
IS_REGEX_CAPTURING_BROKEN = g === ''
|
|
@@ -1104,7 +1104,7 @@ function processStyleReact (el, options) {
|
|
|
1104
1104
|
}
|
|
1105
1105
|
|
|
1106
1106
|
if (specialClassReg.test(el.tag)) {
|
|
1107
|
-
const staticClassNames = ['hover', 'indicator', 'mask']
|
|
1107
|
+
const staticClassNames = ['hover', 'indicator', 'mask', 'placeholder']
|
|
1108
1108
|
staticClassNames.forEach((className) => {
|
|
1109
1109
|
let staticClass = el.attrsMap[className + '-class'] || ''
|
|
1110
1110
|
let staticStyle = getAndRemoveAttr(el, className + '-style').val || ''
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/webpack-plugin",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.2",
|
|
4
4
|
"description": "mpx compile core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mpx"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@better-scroll/wheel": "^2.5.1",
|
|
29
29
|
"@better-scroll/zoom": "^2.5.1",
|
|
30
30
|
"@mpxjs/template-engine": "^2.8.7",
|
|
31
|
-
"@mpxjs/utils": "^2.10.
|
|
31
|
+
"@mpxjs/utils": "^2.10.2",
|
|
32
32
|
"acorn": "^8.11.3",
|
|
33
33
|
"acorn-walk": "^7.2.0",
|
|
34
34
|
"async": "^2.6.0",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@ant-design/react-native": "^5.2.2",
|
|
86
86
|
"@d11/react-native-fast-image": "^8.6.12",
|
|
87
|
-
"@mpxjs/api-proxy": "^2.10.
|
|
87
|
+
"@mpxjs/api-proxy": "^2.10.2",
|
|
88
88
|
"@types/babel-traverse": "^6.25.4",
|
|
89
89
|
"@types/babel-types": "^7.0.4",
|
|
90
90
|
"@types/react": "^18.2.79",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"engines": {
|
|
102
102
|
"node": ">=14.14.0"
|
|
103
103
|
},
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "4445de7c3ce29fb0166d3bb77a1a0460e41a32d3"
|
|
105
105
|
}
|