@mpxjs/webpack-plugin 2.10.2 → 2.10.3-beta.10
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/config.js +2 -1
- package/lib/dependencies/RecordPageConfigsMapDependency.js +45 -0
- package/lib/index.js +84 -52
- package/lib/platform/json/wx/index.js +6 -3
- package/lib/platform/style/wx/index.js +29 -16
- package/lib/platform/template/wx/component-config/button.js +19 -2
- package/lib/platform/template/wx/component-config/canvas.js +4 -0
- package/lib/platform/template/wx/component-config/checkbox-group.js +4 -0
- package/lib/platform/template/wx/component-config/checkbox.js +4 -0
- package/lib/platform/template/wx/component-config/cover-image.js +7 -1
- package/lib/platform/template/wx/component-config/cover-view.js +4 -0
- package/lib/platform/template/wx/component-config/fix-component-name.js +3 -2
- package/lib/platform/template/wx/component-config/form.js +7 -1
- package/lib/platform/template/wx/component-config/icon.js +4 -0
- package/lib/platform/template/wx/component-config/image.js +7 -1
- package/lib/platform/template/wx/component-config/input.js +17 -2
- package/lib/platform/template/wx/component-config/label.js +4 -0
- package/lib/platform/template/wx/component-config/movable-area.js +7 -1
- package/lib/platform/template/wx/component-config/movable-view.js +12 -3
- package/lib/platform/template/wx/component-config/navigator.js +4 -0
- package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
- package/lib/platform/template/wx/component-config/picker-view.js +7 -1
- package/lib/platform/template/wx/component-config/picker.js +7 -1
- package/lib/platform/template/wx/component-config/radio-group.js +4 -0
- package/lib/platform/template/wx/component-config/radio.js +4 -0
- package/lib/platform/template/wx/component-config/rich-text.js +4 -0
- package/lib/platform/template/wx/component-config/root-portal.js +4 -0
- package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
- package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
- package/lib/platform/template/wx/component-config/swiper.js +12 -3
- package/lib/platform/template/wx/component-config/switch.js +4 -0
- package/lib/platform/template/wx/component-config/text.js +7 -1
- package/lib/platform/template/wx/component-config/textarea.js +17 -2
- package/lib/platform/template/wx/component-config/unsupported.js +7 -0
- package/lib/platform/template/wx/component-config/video.js +10 -2
- package/lib/platform/template/wx/component-config/view.js +24 -2
- package/lib/platform/template/wx/component-config/web-view.js +4 -0
- package/lib/platform/template/wx/index.js +32 -13
- package/lib/react/index.js +0 -1
- package/lib/react/processJSON.js +13 -2
- package/lib/react/processScript.js +5 -3
- package/lib/react/processTemplate.js +18 -3
- package/lib/react/script-helper.js +18 -4
- package/lib/runtime/components/react/dist/mpx-input.jsx +15 -18
- package/lib/runtime/components/react/dist/{KeyboardAvoidingView.jsx → mpx-keyboard-avoiding-view.jsx} +25 -31
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +2 -2
- 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-swiper-item.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +10 -5
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +10 -7
- package/lib/runtime/components/react/dist/useAnimationHooks.js +46 -48
- package/lib/runtime/components/react/dist/utils.jsx +18 -7
- package/lib/runtime/components/react/mpx-input.tsx +17 -26
- package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx} +32 -41
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +2 -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-swiper-item.tsx +2 -2
- package/lib/runtime/components/react/mpx-swiper.tsx +4 -2
- package/lib/runtime/components/react/mpx-view.tsx +17 -10
- package/lib/runtime/components/react/mpx-web-view.tsx +15 -12
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
- package/lib/runtime/components/react/types/global.d.ts +1 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +46 -48
- package/lib/runtime/components/react/utils.tsx +23 -11
- package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
- package/lib/runtime/components/web/mpx-titlebar.vue +243 -0
- package/lib/runtime/optionProcessor.js +3 -2
- package/lib/style-compiler/index.js +8 -6
- package/lib/template-compiler/compiler.js +29 -14
- package/lib/utils/env.js +1 -1
- package/lib/utils/match-condition.js +14 -8
- package/lib/web/processJSON.js +1 -3
- package/lib/web/processMainScript.js +3 -1
- package/package.json +3 -3
- package/LICENSE +0 -433
- 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
|
@@ -9,7 +9,7 @@ const { dash2hump } = require('../../../utils/hump-dash')
|
|
|
9
9
|
|
|
10
10
|
module.exports = function getSpec ({ warn, error }) {
|
|
11
11
|
const spec = {
|
|
12
|
-
supportedModes: ['ali', 'swan', 'qq', 'tt', 'web', 'qa', 'jd', 'dd', 'ios', 'android'],
|
|
12
|
+
supportedModes: ['ali', 'swan', 'qq', 'tt', 'web', 'qa', 'jd', 'dd', 'ios', 'android', 'harmony'],
|
|
13
13
|
// props预处理
|
|
14
14
|
preProps: [],
|
|
15
15
|
// props后处理
|
|
@@ -347,18 +347,6 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
347
347
|
value
|
|
348
348
|
}
|
|
349
349
|
},
|
|
350
|
-
// tt ({ name, value }, { eventRules }) {
|
|
351
|
-
// const match = this.test.exec(name)
|
|
352
|
-
// const prefix = match[1]
|
|
353
|
-
// const eventName = match[2]
|
|
354
|
-
// const modifierStr = match[3] || ''
|
|
355
|
-
// const rEventName = runRules(eventRules, eventName, { mode: 'tt' })
|
|
356
|
-
// return {
|
|
357
|
-
// // 字节将所有事件转为小写
|
|
358
|
-
// name: prefix + rEventName.toLowerCase() + modifierStr,
|
|
359
|
-
// value
|
|
360
|
-
// }
|
|
361
|
-
// },
|
|
362
350
|
tt ({ name, value }, { eventRules }) {
|
|
363
351
|
const match = this.test.exec(name)
|
|
364
352
|
const prefix = match[1]
|
|
@@ -430,6 +418,21 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
430
418
|
name: rPrefix + rEventName + meta.modifierStr,
|
|
431
419
|
value
|
|
432
420
|
}
|
|
421
|
+
},
|
|
422
|
+
harmony ({ name, value }, { eventRules, el }) {
|
|
423
|
+
const match = this.test.exec(name)
|
|
424
|
+
const prefix = match[1]
|
|
425
|
+
const eventName = match[2]
|
|
426
|
+
const modifierStr = match[3] || ''
|
|
427
|
+
const meta = {
|
|
428
|
+
modifierStr
|
|
429
|
+
}
|
|
430
|
+
const rPrefix = runRules(spec.event.prefix, prefix, { mode: 'harmony' })
|
|
431
|
+
const rEventName = runRules(eventRules, eventName, { mode: 'harmony', data: { el } })
|
|
432
|
+
return {
|
|
433
|
+
name: rPrefix + rEventName + meta.modifierStr,
|
|
434
|
+
value
|
|
435
|
+
}
|
|
433
436
|
}
|
|
434
437
|
},
|
|
435
438
|
// 无障碍
|
|
@@ -565,6 +568,22 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
565
568
|
} else {
|
|
566
569
|
error(`React native environment does not support [${eventName}] event!`)
|
|
567
570
|
}
|
|
571
|
+
},
|
|
572
|
+
harmony (eventName) {
|
|
573
|
+
const eventMap = {
|
|
574
|
+
tap: 'tap',
|
|
575
|
+
longtap: 'longpress',
|
|
576
|
+
longpress: 'longpress',
|
|
577
|
+
touchstart: 'touchstart',
|
|
578
|
+
touchmove: 'touchmove',
|
|
579
|
+
touchend: 'touchend',
|
|
580
|
+
touchcancel: 'touchcancel'
|
|
581
|
+
}
|
|
582
|
+
if (eventMap[eventName]) {
|
|
583
|
+
return eventMap[eventName]
|
|
584
|
+
} else {
|
|
585
|
+
error(`React native environment does not support [${eventName}] event!`)
|
|
586
|
+
}
|
|
568
587
|
}
|
|
569
588
|
},
|
|
570
589
|
// web event escape
|
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
|
|
@@ -27,7 +29,7 @@ module.exports = function (script, {
|
|
|
27
29
|
output += `
|
|
28
30
|
import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPath)}
|
|
29
31
|
import { NavigationContainer, StackActions } from '@react-navigation/native'
|
|
30
|
-
${mode === 'ios' ? "import { createNativeStackNavigator as createStackNavigator } from '@react-navigation/native-stack'" : "import { createStackNavigator } from '@react-navigation/stack'"}
|
|
32
|
+
${mode === 'ios' || mode === 'harmony' ? "import { createNativeStackNavigator as createStackNavigator } from '@react-navigation/native-stack'" : "import { createStackNavigator } from '@react-navigation/stack'"}
|
|
31
33
|
import PortalHost from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/portal-host'
|
|
32
34
|
import { useHeaderHeight } from '@react-navigation/elements';
|
|
33
35
|
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
@@ -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
|
}
|
|
@@ -82,7 +82,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
82
82
|
const lineCount = useRef(0);
|
|
83
83
|
const [inputValue, setInputValue] = useState(defaultValue);
|
|
84
84
|
const [contentHeight, setContentHeight] = useState(0);
|
|
85
|
-
const [selection, setSelection] = useState({ start: -1, end:
|
|
85
|
+
const [selection, setSelection] = useState({ start: -1, end: tmpValue.current.length });
|
|
86
86
|
const styleObj = extendObject({ padding: 0, backgroundColor: '#fff' }, style, multiline && autoHeight
|
|
87
87
|
? { height: 'auto', minHeight: Math.max(style?.minHeight || 35, contentHeight) }
|
|
88
88
|
: {});
|
|
@@ -94,15 +94,17 @@ const Input = forwardRef((props, ref) => {
|
|
|
94
94
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
95
95
|
useEffect(() => {
|
|
96
96
|
if (inputValue !== value) {
|
|
97
|
-
|
|
97
|
+
const parsed = parseValue(value);
|
|
98
|
+
tmpValue.current = parsed;
|
|
99
|
+
setInputValue(parsed);
|
|
98
100
|
}
|
|
99
101
|
}, [value]);
|
|
100
102
|
useEffect(() => {
|
|
101
|
-
if (
|
|
102
|
-
setSelection({ start:
|
|
103
|
+
if (selectionStart > -1) {
|
|
104
|
+
setSelection({ start: selectionStart, end: selectionEnd === -1 ? tmpValue.current.length : selectionEnd });
|
|
103
105
|
}
|
|
104
|
-
else if (
|
|
105
|
-
setSelection({ start:
|
|
106
|
+
else if (typeof cursor === 'number') {
|
|
107
|
+
setSelection({ start: cursor, end: cursor });
|
|
106
108
|
}
|
|
107
109
|
}, [cursor, selectionStart, selectionEnd]);
|
|
108
110
|
// have not selection on the Android platformg
|
|
@@ -152,6 +154,9 @@ const Input = forwardRef((props, ref) => {
|
|
|
152
154
|
// sometimes the focus event occurs later than the keyboardWillShow event
|
|
153
155
|
setKeyboardAvoidContext();
|
|
154
156
|
};
|
|
157
|
+
const onTouchEnd = (evt) => {
|
|
158
|
+
evt.nativeEvent.origin = 'input';
|
|
159
|
+
};
|
|
155
160
|
const onFocus = (evt) => {
|
|
156
161
|
setKeyboardAvoidContext();
|
|
157
162
|
bindfocus && bindfocus(getCustomEvent('focus', evt, {
|
|
@@ -170,15 +175,6 @@ const Input = forwardRef((props, ref) => {
|
|
|
170
175
|
layoutRef
|
|
171
176
|
}, props));
|
|
172
177
|
};
|
|
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
178
|
const onSubmitEditing = (evt) => {
|
|
183
179
|
bindconfirm(getCustomEvent('confirm', evt, {
|
|
184
180
|
detail: {
|
|
@@ -220,6 +216,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
220
216
|
}
|
|
221
217
|
};
|
|
222
218
|
const resetValue = () => {
|
|
219
|
+
tmpValue.current = '';
|
|
223
220
|
setInputValue('');
|
|
224
221
|
};
|
|
225
222
|
const getValue = () => {
|
|
@@ -264,7 +261,7 @@ const Input = forwardRef((props, ref) => {
|
|
|
264
261
|
maxLength: maxlength === -1 ? undefined : maxlength,
|
|
265
262
|
editable: !disabled,
|
|
266
263
|
autoFocus: !!autoFocus || !!focus,
|
|
267
|
-
selection: selection,
|
|
264
|
+
selection: selectionStart > -1 || typeof cursor === 'number' ? selection : undefined,
|
|
268
265
|
selectionColor: cursorColor,
|
|
269
266
|
blurOnSubmit: !multiline && !confirmHold,
|
|
270
267
|
underlineColorAndroid: 'rgba(0,0,0,0)',
|
|
@@ -273,13 +270,13 @@ const Input = forwardRef((props, ref) => {
|
|
|
273
270
|
multiline: !!multiline
|
|
274
271
|
}, !!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType }, layoutProps, {
|
|
275
272
|
onTouchStart,
|
|
273
|
+
onTouchEnd,
|
|
276
274
|
onFocus,
|
|
277
275
|
onBlur,
|
|
278
276
|
onChange,
|
|
279
277
|
onSelectionChange,
|
|
280
278
|
onContentSizeChange,
|
|
281
|
-
|
|
282
|
-
onSubmitEditing: bindconfirm && multiline && onSubmitEditing
|
|
279
|
+
onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
|
|
283
280
|
}), [
|
|
284
281
|
'type',
|
|
285
282
|
'password',
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React, { useContext, useEffect
|
|
2
|
-
import { Keyboard,
|
|
3
|
-
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing
|
|
4
|
-
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
1
|
+
import React, { useContext, useEffect } from 'react';
|
|
2
|
+
import { Keyboard, View, Platform } from 'react-native';
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
|
|
5
4
|
import { KeyboardAvoidContext } from './context';
|
|
6
5
|
const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
7
6
|
const isIOS = Platform.OS === 'ios';
|
|
@@ -10,20 +9,10 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
10
9
|
const offset = useSharedValue(0);
|
|
11
10
|
const basic = useSharedValue('auto');
|
|
12
11
|
const keyboardAvoid = useContext(KeyboardAvoidContext);
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return Gesture.Tap()
|
|
18
|
-
.onEnd(() => {
|
|
19
|
-
runOnJS(dismiss)();
|
|
20
|
-
});
|
|
21
|
-
}, []);
|
|
22
|
-
const animatedStyle = useAnimatedStyle(() => {
|
|
23
|
-
return Object.assign({
|
|
24
|
-
transform: [{ translateY: -offset.value }]
|
|
25
|
-
}, isIOS ? {} : { flexBasis: basic.value });
|
|
26
|
-
});
|
|
12
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
13
|
+
transform: [{ translateY: -offset.value }],
|
|
14
|
+
flexBasis: basic.value
|
|
15
|
+
}));
|
|
27
16
|
const resetKeyboard = () => {
|
|
28
17
|
if (keyboardAvoid?.current) {
|
|
29
18
|
keyboardAvoid.current = null;
|
|
@@ -31,6 +20,11 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
31
20
|
offset.value = withTiming(0, { duration, easing });
|
|
32
21
|
basic.value = 'auto';
|
|
33
22
|
};
|
|
23
|
+
const onTouchEnd = ({ nativeEvent }) => {
|
|
24
|
+
if (nativeEvent.origin !== 'input') {
|
|
25
|
+
Keyboard.isVisible() && Keyboard.dismiss();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
34
28
|
useEffect(() => {
|
|
35
29
|
let subscriptions = [];
|
|
36
30
|
if (isIOS) {
|
|
@@ -46,7 +40,12 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
46
40
|
const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing;
|
|
47
41
|
const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing);
|
|
48
42
|
const value = aboveOffset > 0 ? belowValue : aboveValue;
|
|
49
|
-
offset.value = withTiming(value, { duration, easing })
|
|
43
|
+
offset.value = withTiming(value, { duration, easing }, (finished) => {
|
|
44
|
+
if (finished) {
|
|
45
|
+
// Set flexBasic after animation to trigger re-layout and reset layout information
|
|
46
|
+
basic.value = '99.99%';
|
|
47
|
+
}
|
|
48
|
+
});
|
|
50
49
|
});
|
|
51
50
|
});
|
|
52
51
|
}),
|
|
@@ -68,11 +67,7 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
68
67
|
const value = aboveOffset > 0 ? belowValue : aboveValue;
|
|
69
68
|
offset.value = withTiming(value, { duration, easing }, (finished) => {
|
|
70
69
|
if (finished) {
|
|
71
|
-
|
|
72
|
-
* In the Android environment, the layout information is not synchronized after the animation,
|
|
73
|
-
* which results in the inability to correctly trigger element events.
|
|
74
|
-
* Here, we utilize flexBasic to proactively trigger a re-layout
|
|
75
|
-
*/
|
|
70
|
+
// Set flexBasic after animation to trigger re-layout and reset layout information
|
|
76
71
|
basic.value = '99.99%';
|
|
77
72
|
}
|
|
78
73
|
});
|
|
@@ -85,15 +80,14 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
|
|
|
85
80
|
subscriptions.forEach(subscription => subscription.remove());
|
|
86
81
|
};
|
|
87
82
|
}, [keyboardAvoid]);
|
|
88
|
-
return (<
|
|
89
|
-
<View style={
|
|
90
|
-
<Animated.View style={[
|
|
83
|
+
return (<View style={style} onTouchEnd={onTouchEnd}>
|
|
84
|
+
<Animated.View style={[
|
|
91
85
|
contentContainerStyle,
|
|
92
86
|
animatedStyle
|
|
93
87
|
]}>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
</GestureDetector>);
|
|
88
|
+
{children}
|
|
89
|
+
</Animated.View>
|
|
90
|
+
</View>);
|
|
98
91
|
};
|
|
92
|
+
KeyboardAvoidingView.displayName = 'MpxKeyboardAvoidingView';
|
|
99
93
|
export default KeyboardAvoidingView;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
|
|
4
|
-
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS } from './utils';
|
|
4
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, isHarmony } from './utils';
|
|
5
5
|
import useNodesRef from './useNodesRef';
|
|
6
6
|
import PickerIndicator from './pickerViewIndicator';
|
|
7
7
|
import PickerMask from './pickerViewMask';
|
|
@@ -81,7 +81,7 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
81
81
|
y: initialIndex * itemRawH,
|
|
82
82
|
animated: false
|
|
83
83
|
});
|
|
84
|
-
}, isAndroid ? 200 : 0);
|
|
84
|
+
}, isAndroid || isHarmony ? 200 : 0);
|
|
85
85
|
activeIndex.current = initialIndex;
|
|
86
86
|
}, [itemRawH, maxIndex, initialIndex]);
|
|
87
87
|
const onContentSizeChange = useCallback((_w, h) => {
|
|
@@ -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;
|
|
@@ -2,7 +2,7 @@ import Animated, { useAnimatedStyle, interpolate } from 'react-native-reanimated
|
|
|
2
2
|
import { forwardRef, useRef, useContext } from 'react';
|
|
3
3
|
import useInnerProps from './getInnerListeners';
|
|
4
4
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
5
|
-
import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils';
|
|
5
|
+
import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout, isHarmony } from './utils';
|
|
6
6
|
import { SwiperContext } from './context';
|
|
7
7
|
const _SwiperItem = forwardRef((props, ref) => {
|
|
8
8
|
const { 'enable-var': enableVar, 'external-var-context': externalVarContext, style, customStyle, itemIndex } = props;
|
|
@@ -30,7 +30,7 @@ const _SwiperItem = forwardRef((props, ref) => {
|
|
|
30
30
|
'style'
|
|
31
31
|
], { layoutRef });
|
|
32
32
|
const itemAnimatedStyle = useAnimatedStyle(() => {
|
|
33
|
-
if (!step.value)
|
|
33
|
+
if (!step.value && !isHarmony)
|
|
34
34
|
return {};
|
|
35
35
|
const inputRange = [step.value, 0];
|
|
36
36
|
const outputRange = [0.7, 1];
|
|
@@ -70,7 +70,7 @@ const easeMap = {
|
|
|
70
70
|
easeInOutCubic: Easing.inOut(Easing.cubic)
|
|
71
71
|
};
|
|
72
72
|
const SwiperWrapper = forwardRef((props, ref) => {
|
|
73
|
-
const { 'indicator-dots': showsPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, style = {}, autoplay = false, circular = false } = props;
|
|
73
|
+
const { 'indicator-dots': showsPagination, 'indicator-color': dotColor = 'rgba(0, 0, 0, .3)', 'indicator-active-color': activeDotColor = '#000000', 'enable-var': enableVar = false, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'external-var-context': externalVarContext, style = {}, autoplay = false, circular = false, disableGesture = false } = props;
|
|
74
74
|
const easeingFunc = props['easing-function'] || 'default';
|
|
75
75
|
const easeDuration = props.duration || 500;
|
|
76
76
|
const horizontal = props.vertical !== undefined ? !props.vertical : true;
|
|
@@ -658,7 +658,7 @@ const SwiperWrapper = forwardRef((props, ref) => {
|
|
|
658
658
|
{showsPagination && renderPagination()}
|
|
659
659
|
</View>);
|
|
660
660
|
}
|
|
661
|
-
if (children.length === 1) {
|
|
661
|
+
if (children.length === 1 || disableGesture) {
|
|
662
662
|
return renderSwiper();
|
|
663
663
|
}
|
|
664
664
|
else {
|
|
@@ -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;
|