@mpxjs/webpack-plugin 2.10.2 → 2.10.3
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/dependencies/RecordPageConfigsMapDependency.js +45 -0
- package/lib/index.js +12 -0
- package/lib/platform/style/wx/index.js +6 -4
- package/lib/platform/template/wx/component-config/view.js +12 -2
- package/lib/react/index.js +0 -1
- package/lib/react/processJSON.js +13 -2
- package/lib/react/processScript.js +4 -2
- package/lib/react/processTemplate.js +18 -3
- package/lib/react/script-helper.js +18 -4
- package/lib/runtime/components/react/dist/mpx-input.jsx +1 -11
- package/lib/runtime/components/react/dist/{KeyboardAvoidingView.jsx → mpx-keyboard-avoiding-view.jsx} +4 -3
- package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +10 -5
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +22 -0
- package/lib/runtime/components/react/dist/mpx-view.jsx +10 -5
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +2 -2
- package/lib/runtime/components/react/dist/useAnimationHooks.js +46 -48
- package/lib/runtime/components/react/dist/utils.jsx +17 -7
- package/lib/runtime/components/react/mpx-input.tsx +1 -19
- package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx} +4 -2
- package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +1 -2
- package/lib/runtime/components/react/mpx-scroll-view.tsx +13 -4
- package/lib/runtime/components/react/mpx-simple-view.tsx +32 -0
- package/lib/runtime/components/react/mpx-view.tsx +17 -10
- package/lib/runtime/components/react/mpx-web-view.tsx +7 -7
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +46 -48
- package/lib/runtime/components/react/utils.tsx +21 -10
- package/lib/runtime/optionProcessor.js +3 -2
- package/lib/style-compiler/index.js +8 -6
- package/lib/template-compiler/compiler.js +20 -12
- package/lib/utils/match-condition.js +14 -8
- package/lib/web/processJSON.js +1 -3
- package/package.json +3 -3
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const NullDependency = require('webpack/lib/dependencies/NullDependency')
|
|
2
|
+
const makeSerializable = require('webpack/lib/util/makeSerializable')
|
|
3
|
+
const isEmptyObject = require('../utils/is-empty-object')
|
|
4
|
+
|
|
5
|
+
class RecordPageConfigMapDependency extends NullDependency {
|
|
6
|
+
constructor (resourcePath, jsonObj) {
|
|
7
|
+
super()
|
|
8
|
+
this.resourcePath = resourcePath || ''
|
|
9
|
+
this.jsonObj = jsonObj || {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get type () {
|
|
13
|
+
return 'mpx record pageConfigsMap'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
mpxAction (module, compilation, callback) {
|
|
17
|
+
const mpx = compilation.__mpx__
|
|
18
|
+
const pagePath = mpx.pagesMap[this.resourcePath]
|
|
19
|
+
if (pagePath && !isEmptyObject(this.jsonObj)) mpx.pageConfigsMap[pagePath] = this.jsonObj
|
|
20
|
+
return callback()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
serialize (context) {
|
|
24
|
+
const { write } = context
|
|
25
|
+
write(this.resourcePath)
|
|
26
|
+
write(this.jsonObj)
|
|
27
|
+
super.serialize(context)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
deserialize (context) {
|
|
31
|
+
const { read } = context
|
|
32
|
+
this.pagePath = read()
|
|
33
|
+
this.jsonObj = read()
|
|
34
|
+
super.deserialize(context)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
RecordPageConfigMapDependency.Template = class RecordPageConfigMapDependencyTemplate {
|
|
39
|
+
apply () {
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
makeSerializable(RecordPageConfigMapDependency, '@mpxjs/webpack-plugin/lib/dependencies/RecordPageConfigMapDependency')
|
|
44
|
+
|
|
45
|
+
module.exports = RecordPageConfigMapDependency
|
package/lib/index.js
CHANGED
|
@@ -34,6 +34,7 @@ const FixDescriptionInfoPlugin = require('./resolver/FixDescriptionInfoPlugin')
|
|
|
34
34
|
// const RequireHeaderDependency = require('webpack/lib/dependencies/RequireHeaderDependency')
|
|
35
35
|
// const RemovedModuleDependency = require('./dependencies/RemovedModuleDependency')
|
|
36
36
|
const AppEntryDependency = require('./dependencies/AppEntryDependency')
|
|
37
|
+
const RecordPageConfigMapDependency = require('./dependencies/RecordPageConfigsMapDependency')
|
|
37
38
|
const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
|
|
38
39
|
const RecordGlobalComponentsDependency = require('./dependencies/RecordGlobalComponentsDependency')
|
|
39
40
|
const RecordIndependentDependency = require('./dependencies/RecordIndependentDependency')
|
|
@@ -617,6 +618,9 @@ class MpxWebpackPlugin {
|
|
|
617
618
|
compilation.dependencyFactories.set(RemoveEntryDependency, new NullFactory())
|
|
618
619
|
compilation.dependencyTemplates.set(RemoveEntryDependency, new RemoveEntryDependency.Template())
|
|
619
620
|
|
|
621
|
+
compilation.dependencyFactories.set(RecordPageConfigMapDependency, new NullFactory())
|
|
622
|
+
compilation.dependencyTemplates.set(RecordPageConfigMapDependency, new RecordPageConfigMapDependency.Template())
|
|
623
|
+
|
|
620
624
|
compilation.dependencyFactories.set(RecordResourceMapDependency, new NullFactory())
|
|
621
625
|
compilation.dependencyTemplates.set(RecordResourceMapDependency, new RecordResourceMapDependency.Template())
|
|
622
626
|
|
|
@@ -656,6 +660,8 @@ class MpxWebpackPlugin {
|
|
|
656
660
|
__vfs,
|
|
657
661
|
// app信息,便于获取appName
|
|
658
662
|
appInfo: {},
|
|
663
|
+
// pageConfig信息
|
|
664
|
+
pageConfigsMap: {},
|
|
659
665
|
// pages全局记录,无需区分主包分包
|
|
660
666
|
pagesMap: {},
|
|
661
667
|
// 组件资源记录,依照所属包进行记录
|
|
@@ -1641,6 +1647,12 @@ class MpxWebpackPlugin {
|
|
|
1641
1647
|
if (isReact(mpx.mode)) {
|
|
1642
1648
|
// 添加 @refresh reset 注释用于在 React HMR 时刷新组件
|
|
1643
1649
|
source.add('/* @refresh reset */\n')
|
|
1650
|
+
// 注入页面的配置,供screen前置设置导航情况
|
|
1651
|
+
if (isRuntime) {
|
|
1652
|
+
source.add('// inject pageconfigmap for screen\n' +
|
|
1653
|
+
'var context = (function() { return this })() || Function("return this")();\n')
|
|
1654
|
+
source.add(`context.__mpxPageConfigsMap = ${JSON.stringify(mpx.pageConfigsMap)};\n`)
|
|
1655
|
+
}
|
|
1644
1656
|
source.add(originalSource)
|
|
1645
1657
|
compilation.assets[chunkFile] = source
|
|
1646
1658
|
processedChunk.add(chunk)
|
|
@@ -47,7 +47,7 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
47
47
|
'flex-wrap': ['wrap', 'nowrap', 'wrap-reverse'],
|
|
48
48
|
'pointer-events': ['auto', 'box-none', 'box-only', 'none'],
|
|
49
49
|
'vertical-align': ['auto', 'top', 'bottom', 'center'],
|
|
50
|
-
position: ['relative', 'absolute'],
|
|
50
|
+
position: ['relative', 'absolute', 'fixed'],
|
|
51
51
|
'font-variant': ['small-caps', 'oldstyle-nums', 'lining-nums', 'tabular-nums', 'proportional-nums'],
|
|
52
52
|
'text-align': ['left', 'right', 'center', 'justify'],
|
|
53
53
|
'font-style': ['normal', 'italic'],
|
|
@@ -395,22 +395,22 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
395
395
|
case 'skewY':
|
|
396
396
|
case 'perspective':
|
|
397
397
|
// 单个值处理
|
|
398
|
+
// rotate 处理成 rotateZ
|
|
399
|
+
key = key === 'rotate' ? 'rotateZ' : key
|
|
398
400
|
transform.push({ [key]: val })
|
|
399
401
|
break
|
|
400
402
|
case 'matrix':
|
|
401
|
-
case 'matrix3d':
|
|
402
403
|
transform.push({ [key]: parseValues(val, ',').map(val => +val) })
|
|
403
404
|
break
|
|
404
405
|
case 'translate':
|
|
405
406
|
case 'scale':
|
|
406
407
|
case 'skew':
|
|
407
|
-
case 'rotate3d': // x y z angle
|
|
408
408
|
case 'translate3d': // x y 支持 z不支持
|
|
409
409
|
case 'scale3d': // x y 支持 z不支持
|
|
410
410
|
{
|
|
411
411
|
// 2 个以上的值处理
|
|
412
412
|
key = key.replace('3d', '')
|
|
413
|
-
const vals = parseValues(val, ',').splice(0,
|
|
413
|
+
const vals = parseValues(val, ',').splice(0, 3)
|
|
414
414
|
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
415
415
|
if (vals.length === 1 && key === 'scale') {
|
|
416
416
|
vals.push(vals[0])
|
|
@@ -426,6 +426,8 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
426
426
|
}
|
|
427
427
|
case 'translateZ':
|
|
428
428
|
case 'scaleZ':
|
|
429
|
+
case 'rotate3d': // x y z angle
|
|
430
|
+
case 'matrix3d':
|
|
429
431
|
default:
|
|
430
432
|
// 不支持的属性处理
|
|
431
433
|
unsupportedPropError({ prop, value, selector }, { mode })
|
|
@@ -25,11 +25,11 @@ module.exports = function ({ print }) {
|
|
|
25
25
|
},
|
|
26
26
|
ios (tag, { el }) {
|
|
27
27
|
el.isBuiltIn = true
|
|
28
|
-
return 'mpx-view'
|
|
28
|
+
return el.isSimple ? 'mpx-simple-view' : 'mpx-view'
|
|
29
29
|
},
|
|
30
30
|
android (tag, { el }) {
|
|
31
31
|
el.isBuiltIn = true
|
|
32
|
-
return 'mpx-view'
|
|
32
|
+
return el.isSimple ? 'mpx-simple-view' : 'mpx-view'
|
|
33
33
|
},
|
|
34
34
|
qa (tag) {
|
|
35
35
|
return 'div'
|
|
@@ -47,6 +47,16 @@ module.exports = function ({ print }) {
|
|
|
47
47
|
test: /^(hover-stop-propagation)$/,
|
|
48
48
|
android: androidPropLog,
|
|
49
49
|
ios: iosPropLog
|
|
50
|
+
}, {
|
|
51
|
+
test: /^(is-simple)$/,
|
|
52
|
+
android (prop, { el }) {
|
|
53
|
+
el.isSimple = true
|
|
54
|
+
return false
|
|
55
|
+
},
|
|
56
|
+
ios (prop, { el }) {
|
|
57
|
+
el.isSimple = true
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
50
60
|
}
|
|
51
61
|
],
|
|
52
62
|
// 组件事件中的差异部分
|
package/lib/react/index.js
CHANGED
package/lib/react/processJSON.js
CHANGED
|
@@ -12,6 +12,7 @@ const createJSONHelper = require('../json-compiler/helper')
|
|
|
12
12
|
const getRulesRunner = require('../platform/index')
|
|
13
13
|
const { RESOLVE_IGNORED_ERR } = require('../utils/const')
|
|
14
14
|
const RecordResourceMapDependency = require('../dependencies/RecordResourceMapDependency')
|
|
15
|
+
const RecordPageConfigsMapDependency = require('../dependencies/RecordPageConfigsMapDependency')
|
|
15
16
|
|
|
16
17
|
module.exports = function (jsonContent, {
|
|
17
18
|
loaderContext,
|
|
@@ -79,7 +80,6 @@ module.exports = function (jsonContent, {
|
|
|
79
80
|
})
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
const isApp = ctorType === 'app'
|
|
83
83
|
if (!jsonContent) {
|
|
84
84
|
return callback()
|
|
85
85
|
}
|
|
@@ -99,7 +99,7 @@ module.exports = function (jsonContent, {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
if (
|
|
102
|
+
if (ctorType !== 'app') {
|
|
103
103
|
rulesRunnerOptions.mainKey = ctorType
|
|
104
104
|
}
|
|
105
105
|
|
|
@@ -112,6 +112,17 @@ module.exports = function (jsonContent, {
|
|
|
112
112
|
return callback(e)
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
if (ctorType === 'page') {
|
|
116
|
+
const keysToExtract = ['navigationStyle']
|
|
117
|
+
const configObj = {}
|
|
118
|
+
keysToExtract.forEach(key => {
|
|
119
|
+
if (jsonObj[key]) {
|
|
120
|
+
configObj[key] = jsonObj[key]
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
loaderContext._module.addPresentationalDependency(new RecordPageConfigsMapDependency(parseRequest(loaderContext.resource).resourcePath, configObj))
|
|
124
|
+
}
|
|
125
|
+
|
|
115
126
|
const fs = loaderContext._compiler.inputFileSystem
|
|
116
127
|
|
|
117
128
|
const defaultTabbar = {
|
|
@@ -12,7 +12,9 @@ module.exports = function (script, {
|
|
|
12
12
|
outputPath,
|
|
13
13
|
builtInComponentsMap,
|
|
14
14
|
localComponentsMap,
|
|
15
|
-
localPagesMap
|
|
15
|
+
localPagesMap,
|
|
16
|
+
componentGenerics,
|
|
17
|
+
genericsInfo
|
|
16
18
|
}, callback) {
|
|
17
19
|
let scriptSrcMode = srcMode
|
|
18
20
|
const mode = loaderContext.getMpx().mode
|
|
@@ -68,7 +70,7 @@ global.__navigationHelper = {
|
|
|
68
70
|
jsonConfig
|
|
69
71
|
})
|
|
70
72
|
|
|
71
|
-
output += buildGlobalParams({ moduleId, scriptSrcMode, loaderContext, isProduction, ctorType, jsonConfig, componentsMap, outputPath })
|
|
73
|
+
output += buildGlobalParams({ moduleId, scriptSrcMode, loaderContext, isProduction, ctorType, jsonConfig, componentsMap, outputPath, genericsInfo, componentGenerics })
|
|
72
74
|
output += getRequireScript({ ctorType, script, loaderContext })
|
|
73
75
|
output += `export default global.__mpxOptionsMap[${JSON.stringify(moduleId)}]\n`
|
|
74
76
|
}
|
|
@@ -5,6 +5,8 @@ const loaderUtils = require('loader-utils')
|
|
|
5
5
|
const templateCompiler = require('../template-compiler/compiler')
|
|
6
6
|
const genNode = require('../template-compiler/gen-node-react')
|
|
7
7
|
const bindThis = require('../template-compiler/bind-this')
|
|
8
|
+
const isEmptyObject = require('../utils/is-empty-object')
|
|
9
|
+
const dash2hump = require('../utils/hump-dash').dash2hump
|
|
8
10
|
|
|
9
11
|
module.exports = function (template, {
|
|
10
12
|
loaderContext,
|
|
@@ -75,16 +77,15 @@ module.exports = function (template, {
|
|
|
75
77
|
defs,
|
|
76
78
|
decodeHTMLText,
|
|
77
79
|
externalClasses,
|
|
78
|
-
// todo 后续输出web也采用mpx的scoped处理
|
|
79
80
|
hasScoped: false,
|
|
80
81
|
moduleId,
|
|
81
82
|
filePath: rawResourcePath,
|
|
82
83
|
// react中模版i18n不需要特殊处理
|
|
83
84
|
i18n: null,
|
|
84
85
|
checkUsingComponents,
|
|
85
|
-
//
|
|
86
|
+
// rn模式下全局组件不会被合入usingComponents中,故globalComponents可以传空
|
|
86
87
|
globalComponents: [],
|
|
87
|
-
//
|
|
88
|
+
// rn模式下实现抽象组件
|
|
88
89
|
componentGenerics,
|
|
89
90
|
hasVirtualHost: matchCondition(resourcePath, autoVirtualHostRules),
|
|
90
91
|
forceProxyEvent: matchCondition(resourcePath, forceProxyEventRules),
|
|
@@ -148,6 +149,20 @@ ${e.stack}`)
|
|
|
148
149
|
if (meta.options) {
|
|
149
150
|
output += `global.currentInject.injectOptions = ${JSON.stringify(meta.options)};\n`
|
|
150
151
|
}
|
|
152
|
+
if (!isEmptyObject(componentGenerics)) {
|
|
153
|
+
output += 'global.currentInject.injectProperties = {\n'
|
|
154
|
+
output += ' generichash: String,\n'
|
|
155
|
+
|
|
156
|
+
Object.keys(componentGenerics).forEach(genericName => {
|
|
157
|
+
const defaultValue = componentGenerics[genericName].default
|
|
158
|
+
if (defaultValue) {
|
|
159
|
+
output += ` generic${dash2hump(genericName)}: { type: String, value: '${genericName}default' },\n`
|
|
160
|
+
} else {
|
|
161
|
+
output += ` generic${dash2hump(genericName)}: String,\n`
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
output += '}\n'
|
|
165
|
+
}
|
|
151
166
|
}
|
|
152
167
|
}
|
|
153
168
|
|
|
@@ -89,7 +89,8 @@ function buildGlobalParams ({
|
|
|
89
89
|
componentsMap,
|
|
90
90
|
pagesMap,
|
|
91
91
|
firstPage,
|
|
92
|
-
outputPath
|
|
92
|
+
outputPath,
|
|
93
|
+
genericsInfo
|
|
93
94
|
}) {
|
|
94
95
|
let content = ''
|
|
95
96
|
if (ctorType === 'app') {
|
|
@@ -115,9 +116,22 @@ global.currentInject.firstPage = ${JSON.stringify(firstPage)}\n`
|
|
|
115
116
|
delete pageConfig.usingComponents
|
|
116
117
|
content += `global.currentInject.pageConfig = ${JSON.stringify(pageConfig)}\n`
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
|
|
120
|
+
content += `
|
|
121
|
+
|
|
122
|
+
function getComponents() {
|
|
123
|
+
return ${shallowStringify(componentsMap)}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
global.currentInject.getComponents = getComponents\n`
|
|
127
|
+
if (genericsInfo) {
|
|
128
|
+
content += `
|
|
129
|
+
const genericHash = ${JSON.stringify(genericsInfo.hash)}\n
|
|
130
|
+
global.__mpxGenericsMap[genericHash] = function (name) {
|
|
131
|
+
return getComponents()[name]
|
|
132
|
+
}
|
|
133
|
+
\n`
|
|
134
|
+
}
|
|
121
135
|
if (ctorType === 'component') {
|
|
122
136
|
content += `global.currentInject.componentPath = '/' + ${JSON.stringify(outputPath)}\n`
|
|
123
137
|
}
|
|
@@ -170,15 +170,6 @@ const Input = forwardRef((props, ref) => {
|
|
|
170
170
|
layoutRef
|
|
171
171
|
}, props));
|
|
172
172
|
};
|
|
173
|
-
const onKeyPress = (evt) => {
|
|
174
|
-
evt.nativeEvent.key === 'Enter' &&
|
|
175
|
-
bindconfirm(getCustomEvent('confirm', evt, {
|
|
176
|
-
detail: {
|
|
177
|
-
value: tmpValue.current || ''
|
|
178
|
-
},
|
|
179
|
-
layoutRef
|
|
180
|
-
}, props));
|
|
181
|
-
};
|
|
182
173
|
const onSubmitEditing = (evt) => {
|
|
183
174
|
bindconfirm(getCustomEvent('confirm', evt, {
|
|
184
175
|
detail: {
|
|
@@ -278,8 +269,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
278
269
|
onChange,
|
|
279
270
|
onSelectionChange,
|
|
280
271
|
onContentSizeChange,
|
|
281
|
-
|
|
282
|
-
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
272
|
+
onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
|
|
283
273
|
}), [
|
|
284
274
|
'type',
|
|
285
275
|
'password',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useContext, useEffect, useMemo } from 'react';
|
|
2
2
|
import { Keyboard, Platform, View } from 'react-native';
|
|
3
|
-
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
|
|
4
4
|
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
5
5
|
import { KeyboardAvoidContext } from './context';
|
|
6
6
|
const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
@@ -16,8 +16,8 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
16
16
|
const gesture = useMemo(() => {
|
|
17
17
|
return Gesture.Tap()
|
|
18
18
|
.onEnd(() => {
|
|
19
|
-
|
|
20
|
-
});
|
|
19
|
+
dismiss();
|
|
20
|
+
}).runOnJS(true);
|
|
21
21
|
}, []);
|
|
22
22
|
const animatedStyle = useAnimatedStyle(() => {
|
|
23
23
|
return Object.assign({
|
|
@@ -96,4 +96,5 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
96
96
|
</View>
|
|
97
97
|
</GestureDetector>);
|
|
98
98
|
};
|
|
99
|
+
KeyboardAvoidingView.displayName = 'MpxKeyboardAvoidingView';
|
|
99
100
|
export default KeyboardAvoidingView;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
|
|
2
2
|
import { View, StyleSheet } from 'react-native';
|
|
3
|
-
import { extendObject } from '../utils';
|
|
4
3
|
const _PortalManager = forwardRef((props, ref) => {
|
|
5
4
|
const [state, setState] = useState({
|
|
6
5
|
portals: []
|
|
@@ -14,7 +13,7 @@ const _PortalManager = forwardRef((props, ref) => {
|
|
|
14
13
|
setState((prevState) => ({
|
|
15
14
|
portals: prevState.portals.map((item) => {
|
|
16
15
|
if (item.key === key) {
|
|
17
|
-
return
|
|
16
|
+
return Object.assign({}, item, { children });
|
|
18
17
|
}
|
|
19
18
|
return item;
|
|
20
19
|
})
|
|
@@ -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 = 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;
|
|
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, 'scroll-event-throttle': scrollEventThrottle = 0, __selectRef } = props;
|
|
45
45
|
const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
|
|
46
46
|
const waitForHandlers = flatGesture(waitFor);
|
|
47
47
|
const [refreshing, setRefreshing] = useState(true);
|
|
@@ -54,7 +54,6 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
54
54
|
scrollTop: 0,
|
|
55
55
|
visibleLength: 0
|
|
56
56
|
});
|
|
57
|
-
const scrollEventThrottle = 50;
|
|
58
57
|
const hasCallScrollToUpper = useRef(true);
|
|
59
58
|
const hasCallScrollToLower = useRef(false);
|
|
60
59
|
const initialTimeout = useRef(null);
|
|
@@ -83,6 +82,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
83
82
|
};
|
|
84
83
|
}, []);
|
|
85
84
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
|
|
85
|
+
const lastOffset = useRef(0);
|
|
86
86
|
if (scrollX && scrollY) {
|
|
87
87
|
warn('scroll-x and scroll-y cannot be set to true at the same time, Mpx will use the value of scroll-y as the criterion');
|
|
88
88
|
}
|
|
@@ -133,7 +133,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
133
133
|
function onStartReached(e) {
|
|
134
134
|
const { bindscrolltoupper } = props;
|
|
135
135
|
const { offset } = scrollOptions.current;
|
|
136
|
-
|
|
136
|
+
const isScrollingBackward = offset < lastOffset.current;
|
|
137
|
+
if (bindscrolltoupper && (offset <= upperThreshold) && isScrollingBackward) {
|
|
137
138
|
if (!hasCallScrollToUpper.current) {
|
|
138
139
|
bindscrolltoupper(getCustomEvent('scrolltoupper', e, {
|
|
139
140
|
detail: {
|
|
@@ -152,12 +153,13 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
152
153
|
const { bindscrolltolower } = props;
|
|
153
154
|
const { contentLength, visibleLength, offset } = scrollOptions.current;
|
|
154
155
|
const distanceFromEnd = contentLength - visibleLength - offset;
|
|
155
|
-
|
|
156
|
+
const isScrollingForward = offset > lastOffset.current;
|
|
157
|
+
if (bindscrolltolower && (distanceFromEnd < lowerThreshold) && isScrollingForward) {
|
|
156
158
|
if (!hasCallScrollToLower.current) {
|
|
157
159
|
hasCallScrollToLower.current = true;
|
|
158
160
|
bindscrolltolower(getCustomEvent('scrolltolower', e, {
|
|
159
161
|
detail: {
|
|
160
|
-
direction: scrollX ? 'right' : '
|
|
162
|
+
direction: scrollX ? 'right' : 'bottom'
|
|
161
163
|
},
|
|
162
164
|
layoutRef
|
|
163
165
|
}, props));
|
|
@@ -206,6 +208,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
206
208
|
onStartReached(e);
|
|
207
209
|
onEndReached(e);
|
|
208
210
|
updateIntersection();
|
|
211
|
+
// 在 onStartReached、onEndReached 执行完后更新 lastOffset
|
|
212
|
+
lastOffset.current = scrollOptions.current.offset;
|
|
209
213
|
}
|
|
210
214
|
function onScrollEnd(e) {
|
|
211
215
|
const { bindscrollend } = props;
|
|
@@ -225,6 +229,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
225
229
|
onStartReached(e);
|
|
226
230
|
onEndReached(e);
|
|
227
231
|
updateIntersection();
|
|
232
|
+
lastOffset.current = scrollOptions.current.offset;
|
|
228
233
|
}
|
|
229
234
|
function updateIntersection() {
|
|
230
235
|
if (enableTriggerIntersectionObserver && intersectionObservers) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { View } from 'react-native';
|
|
2
|
+
import { createElement, forwardRef, useRef } from 'react';
|
|
3
|
+
import useNodesRef from './useNodesRef';
|
|
4
|
+
import { extendObject, splitProps, splitStyle, wrapChildren } from './utils';
|
|
5
|
+
const _View2 = forwardRef((simpleViewProps, ref) => {
|
|
6
|
+
const nodeRef = useRef(null);
|
|
7
|
+
const { textProps, innerProps: props = {} } = splitProps(simpleViewProps);
|
|
8
|
+
const { textStyle, innerStyle = {} } = splitStyle(props.style || {});
|
|
9
|
+
useNodesRef(props, ref, nodeRef, {
|
|
10
|
+
style: innerStyle || {}
|
|
11
|
+
});
|
|
12
|
+
return createElement(View, extendObject({}, props, {
|
|
13
|
+
style: innerStyle,
|
|
14
|
+
ref: nodeRef
|
|
15
|
+
}), wrapChildren(props, {
|
|
16
|
+
hasVarDec: false,
|
|
17
|
+
textStyle: textStyle,
|
|
18
|
+
textProps
|
|
19
|
+
}));
|
|
20
|
+
});
|
|
21
|
+
_View2.displayName = 'MpxSimpleView';
|
|
22
|
+
export default _View2;
|
|
@@ -14,6 +14,7 @@ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wra
|
|
|
14
14
|
import { error } from '@mpxjs/utils';
|
|
15
15
|
import LinearGradient from 'react-native-linear-gradient';
|
|
16
16
|
import { GestureDetector } from 'react-native-gesture-handler';
|
|
17
|
+
import Portal from './mpx-portal';
|
|
17
18
|
const linearMap = new Map([
|
|
18
19
|
['top', 0],
|
|
19
20
|
['bottom', 180],
|
|
@@ -555,7 +556,7 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
555
556
|
const enableHover = !!hoverStyle;
|
|
556
557
|
const { isHover, gesture } = useHover({ enableHover, hoverStartTime, hoverStayTime });
|
|
557
558
|
const styleObj = extendObject({}, defaultStyle, style, isHover ? hoverStyle : {});
|
|
558
|
-
const { normalStyle, hasSelfPercent, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
|
|
559
|
+
const { normalStyle, hasSelfPercent, hasPositionFixed, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, {
|
|
559
560
|
enableVar,
|
|
560
561
|
externalVarContext,
|
|
561
562
|
parentFontSize,
|
|
@@ -600,12 +601,16 @@ const _View = forwardRef((viewProps, ref) => {
|
|
|
600
601
|
innerStyle,
|
|
601
602
|
enableFastImage
|
|
602
603
|
});
|
|
603
|
-
|
|
604
|
+
let finalComponent = enableStyleAnimation
|
|
604
605
|
? createElement(Animated.View, innerProps, childNode)
|
|
605
606
|
: createElement(View, innerProps, childNode);
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
607
|
+
if (enableHover) {
|
|
608
|
+
finalComponent = createElement(GestureDetector, { gesture: gesture }, finalComponent);
|
|
609
|
+
}
|
|
610
|
+
if (hasPositionFixed) {
|
|
611
|
+
finalComponent = createElement(Portal, null, finalComponent);
|
|
612
|
+
}
|
|
613
|
+
return finalComponent;
|
|
609
614
|
});
|
|
610
615
|
_View.displayName = 'MpxView';
|
|
611
616
|
export default _View;
|
|
@@ -45,7 +45,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
45
45
|
button: 'Reload'
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
-
const currentErrorText = errorText[mpx.i18n
|
|
48
|
+
const currentErrorText = errorText[mpx.i18n?.locale || 'zh-CN'];
|
|
49
49
|
if (props.style) {
|
|
50
50
|
warn('The web-view component does not support the style prop.');
|
|
51
51
|
}
|
|
@@ -277,7 +277,7 @@ const _WebView = forwardRef((props, ref) => {
|
|
|
277
277
|
setIsLoaded(false);
|
|
278
278
|
}
|
|
279
279
|
};
|
|
280
|
-
return (<Portal
|
|
280
|
+
return (<Portal>
|
|
281
281
|
{pageLoadErr
|
|
282
282
|
? (<View style={[styles.loadErrorContext, defaultWebViewStyle]}>
|
|
283
283
|
<View style={styles.loadErrorText}><Text style={{ fontSize: 14, color: '#999999' }}>{currentErrorText.text}</Text></View>
|