@mpxjs/webpack-plugin 2.9.40 → 2.9.41
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 +63 -97
- package/lib/dependencies/DynamicEntryDependency.js +13 -4
- package/lib/dependencies/{RecordVueContentDependency.js → RecordLoaderContentDependency.js} +5 -5
- package/lib/dependencies/ResolveDependency.js +2 -2
- package/lib/helpers.js +5 -1
- package/lib/index.js +59 -45
- package/lib/json-compiler/helper.js +6 -3
- package/lib/json-compiler/index.js +9 -7
- package/lib/loader.js +43 -97
- package/lib/native-loader.js +0 -1
- package/lib/platform/index.js +3 -0
- package/lib/platform/style/wx/index.js +414 -0
- package/lib/platform/template/wx/component-config/button.js +36 -0
- package/lib/platform/template/wx/component-config/image.js +15 -0
- package/lib/platform/template/wx/component-config/input.js +41 -0
- package/lib/platform/template/wx/component-config/scroll-view.js +27 -1
- package/lib/platform/template/wx/component-config/swiper-item.js +13 -1
- package/lib/platform/template/wx/component-config/swiper.js +25 -1
- package/lib/platform/template/wx/component-config/text.js +15 -0
- package/lib/platform/template/wx/component-config/textarea.js +39 -0
- package/lib/platform/template/wx/component-config/unsupported.js +18 -0
- package/lib/platform/template/wx/component-config/view.js +14 -0
- package/lib/platform/template/wx/index.js +88 -4
- package/lib/react/index.js +104 -0
- package/lib/react/processJSON.js +361 -0
- package/lib/react/processMainScript.js +21 -0
- package/lib/react/processScript.js +70 -0
- package/lib/react/processStyles.js +69 -0
- package/lib/react/processTemplate.js +152 -0
- package/lib/react/script-helper.js +133 -0
- package/lib/react/style-helper.js +91 -0
- package/lib/resolver/PackageEntryPlugin.js +1 -0
- package/lib/runtime/components/react/event.config.ts +32 -0
- package/lib/runtime/components/react/getInnerListeners.ts +289 -0
- package/lib/runtime/components/react/getInnerListeners.type.ts +68 -0
- package/lib/runtime/components/react/mpx-button.tsx +402 -0
- package/lib/runtime/components/react/mpx-image/index.tsx +351 -0
- package/lib/runtime/components/react/mpx-image/svg.tsx +21 -0
- package/lib/runtime/components/react/mpx-input.tsx +389 -0
- package/lib/runtime/components/react/mpx-scroll-view.tsx +412 -0
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +398 -0
- package/lib/runtime/components/react/mpx-swiper/index.tsx +68 -0
- package/lib/runtime/components/react/mpx-swiper/type.ts +69 -0
- package/lib/runtime/components/react/mpx-swiper-item.tsx +42 -0
- package/lib/runtime/components/react/mpx-text.tsx +106 -0
- package/lib/runtime/components/react/mpx-textarea.tsx +46 -0
- package/lib/runtime/components/react/mpx-view.tsx +397 -0
- package/lib/runtime/components/react/useNodesRef.ts +39 -0
- package/lib/runtime/components/react/utils.ts +92 -0
- package/lib/runtime/optionProcessorReact.d.ts +9 -0
- package/lib/runtime/optionProcessorReact.js +21 -0
- package/lib/runtime/stringify.wxs +10 -28
- package/lib/style-compiler/index.js +2 -1
- package/lib/template-compiler/compiler.js +280 -37
- package/lib/template-compiler/gen-node-react.js +95 -0
- package/lib/template-compiler/index.js +15 -24
- package/lib/utils/env.js +17 -0
- package/lib/utils/make-map.js +1 -1
- package/lib/utils/shallow-stringify.js +12 -12
- package/lib/web/index.js +123 -0
- package/lib/web/processJSON.js +3 -3
- package/lib/web/processMainScript.js +25 -23
- package/lib/web/processScript.js +12 -16
- package/lib/web/processTemplate.js +13 -12
- package/lib/web/script-helper.js +14 -22
- package/package.json +4 -3
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const loaderUtils = require('loader-utils')
|
|
2
|
+
const createHelpers = require('../helpers')
|
|
3
|
+
const parseRequest = require('../utils/parse-request')
|
|
4
|
+
const shallowStringify = require('../utils/shallow-stringify')
|
|
5
|
+
|
|
6
|
+
function stringifyRequest (loaderContext, request) {
|
|
7
|
+
return loaderUtils.stringifyRequest(loaderContext, request)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// function getAsyncChunkName (chunkName) {
|
|
11
|
+
// if (chunkName && typeof chunkName !== 'boolean') {
|
|
12
|
+
// return `/* webpackChunkName: "${chunkName}" */`
|
|
13
|
+
// }
|
|
14
|
+
// return ''
|
|
15
|
+
// }
|
|
16
|
+
|
|
17
|
+
function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig }) {
|
|
18
|
+
let firstPage = ''
|
|
19
|
+
const pagesMap = {}
|
|
20
|
+
Object.keys(localPagesMap).forEach((pagePath) => {
|
|
21
|
+
const pageCfg = localPagesMap[pagePath]
|
|
22
|
+
const pageRequest = stringifyRequest(loaderContext, pageCfg.resource)
|
|
23
|
+
// if (pageCfg.async) {
|
|
24
|
+
// pagesMap[pagePath] = `lazy(function(){return import(${getAsyncChunkName(pageCfg.async)} ${pageRequest}).then(function(res){return getComponent(res, {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})})})`
|
|
25
|
+
// } else {
|
|
26
|
+
// 为了保持小程序中app->page->component的js执行顺序,所有的page和component都改为require引入
|
|
27
|
+
pagesMap[pagePath] = `getComponent(require(${pageRequest}), {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})`
|
|
28
|
+
// }
|
|
29
|
+
if (pagePath === jsonConfig.entryPagePath) {
|
|
30
|
+
firstPage = pagePath
|
|
31
|
+
}
|
|
32
|
+
if (!firstPage && pageCfg.isFirst) {
|
|
33
|
+
firstPage = pagePath
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
return {
|
|
37
|
+
pagesMap,
|
|
38
|
+
firstPage
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function buildComponentsMap ({ localComponentsMap, builtInComponentsMap, loaderContext, jsonConfig }) {
|
|
43
|
+
const componentsMap = {}
|
|
44
|
+
if (localComponentsMap) {
|
|
45
|
+
Object.keys(localComponentsMap).forEach((componentName) => {
|
|
46
|
+
const componentCfg = localComponentsMap[componentName]
|
|
47
|
+
const componentRequest = stringifyRequest(loaderContext, componentCfg.resource)
|
|
48
|
+
// RN中暂不支持异步加载
|
|
49
|
+
// if (componentCfg.async) {
|
|
50
|
+
// componentsMap[componentName] = `lazy(function(){return import(${getAsyncChunkName(componentCfg.async)}${componentRequest}).then(function(res){return getComponent(res, {displayName: ${JSON.stringify(componentName)}})})})`
|
|
51
|
+
// } else {
|
|
52
|
+
componentsMap[componentName] = `getComponent(require(${componentRequest}), {displayName: ${JSON.stringify(componentName)}})`
|
|
53
|
+
// }
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
if (builtInComponentsMap) {
|
|
57
|
+
Object.keys(builtInComponentsMap).forEach((componentName) => {
|
|
58
|
+
const componentCfg = builtInComponentsMap[componentName]
|
|
59
|
+
const componentRequest = stringifyRequest(loaderContext, componentCfg.resource)
|
|
60
|
+
componentsMap[componentName] = `getComponent(require(${componentRequest}), {__mpxBuiltIn: true})`
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
return componentsMap
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getRequireScript ({ script, ctorType, loaderContext }) {
|
|
67
|
+
let content = ' /** script content **/\n'
|
|
68
|
+
const { getRequire } = createHelpers(loaderContext)
|
|
69
|
+
const { resourcePath, queryObj } = parseRequest(loaderContext.resource)
|
|
70
|
+
const extraOptions = {
|
|
71
|
+
...script.src
|
|
72
|
+
? { ...queryObj, resourcePath }
|
|
73
|
+
: null,
|
|
74
|
+
ctorType,
|
|
75
|
+
lang: script.lang || 'js'
|
|
76
|
+
}
|
|
77
|
+
content += ` ${getRequire('script', script, extraOptions)}\n`
|
|
78
|
+
return content
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function buildGlobalParams ({
|
|
82
|
+
moduleId,
|
|
83
|
+
scriptSrcMode,
|
|
84
|
+
loaderContext,
|
|
85
|
+
isProduction,
|
|
86
|
+
ctorType,
|
|
87
|
+
jsonConfig,
|
|
88
|
+
componentsMap,
|
|
89
|
+
pagesMap,
|
|
90
|
+
firstPage
|
|
91
|
+
}) {
|
|
92
|
+
let content = ''
|
|
93
|
+
if (ctorType === 'app') {
|
|
94
|
+
content += `
|
|
95
|
+
global.getApp = function () {}
|
|
96
|
+
global.getCurrentPages = function () {}
|
|
97
|
+
global.__networkTimeout = ${JSON.stringify(jsonConfig.networkTimeout)}
|
|
98
|
+
global.__mpxGenericsMap = {}
|
|
99
|
+
global.__mpxOptionsMap = {}
|
|
100
|
+
global.__style = ${JSON.stringify(jsonConfig.style || 'v1')}
|
|
101
|
+
global.__mpxPageConfig = ${JSON.stringify(jsonConfig.window)}
|
|
102
|
+
global.__getAppComponents = function () {
|
|
103
|
+
return ${shallowStringify(componentsMap)}
|
|
104
|
+
}
|
|
105
|
+
global.currentInject.getPages = function () {
|
|
106
|
+
return ${shallowStringify(pagesMap)}
|
|
107
|
+
}
|
|
108
|
+
global.currentInject.firstPage = ${JSON.stringify(firstPage)}\n`
|
|
109
|
+
} else {
|
|
110
|
+
if (ctorType === 'page') {
|
|
111
|
+
const pageConfig = Object.assign({}, jsonConfig)
|
|
112
|
+
delete pageConfig.usingComponents
|
|
113
|
+
content += `global.currentInject.pageConfig = ${JSON.stringify(pageConfig)}\n`
|
|
114
|
+
}
|
|
115
|
+
content += `global.currentInject.getComponents = function () {
|
|
116
|
+
return ${shallowStringify(componentsMap)}
|
|
117
|
+
}\n`
|
|
118
|
+
}
|
|
119
|
+
content += `global.currentModuleId = ${JSON.stringify(moduleId)}\n`
|
|
120
|
+
content += `global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
|
|
121
|
+
if (!isProduction) {
|
|
122
|
+
content += `global.currentResource = ${JSON.stringify(loaderContext.resourcePath)}\n`
|
|
123
|
+
}
|
|
124
|
+
return content
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = {
|
|
128
|
+
buildPagesMap,
|
|
129
|
+
buildComponentsMap,
|
|
130
|
+
getRequireScript,
|
|
131
|
+
buildGlobalParams,
|
|
132
|
+
stringifyRequest
|
|
133
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const postcss = require('postcss')
|
|
2
|
+
const selectorParser = require('postcss-selector-parser')
|
|
3
|
+
const getRulesRunner = require('../platform/index')
|
|
4
|
+
const dash2hump = require('../utils/hump-dash').dash2hump
|
|
5
|
+
const rpxRegExp = /^\s*(\d+(\.\d+)?)rpx\s*$/
|
|
6
|
+
const pxRegExp = /^\s*(\d+(\.\d+)?)(px)?\s*$/
|
|
7
|
+
const cssPrefixExp = /^-(webkit|moz|ms|o)-/
|
|
8
|
+
function getClassMap ({ content, filename, mode, srcMode }) {
|
|
9
|
+
const classMap = {}
|
|
10
|
+
|
|
11
|
+
const root = postcss.parse(content, {
|
|
12
|
+
from: filename
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
function formatValue (value) {
|
|
16
|
+
let matched
|
|
17
|
+
let needStringify = true
|
|
18
|
+
if ((matched = pxRegExp.exec(value))) {
|
|
19
|
+
value = matched[1]
|
|
20
|
+
needStringify = false
|
|
21
|
+
} else if ((matched = rpxRegExp.exec(value))) {
|
|
22
|
+
value = `this.__rpx(${matched[1]})`
|
|
23
|
+
needStringify = false
|
|
24
|
+
}
|
|
25
|
+
return needStringify ? JSON.stringify(value) : value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const rulesRunner = getRulesRunner({
|
|
29
|
+
mode,
|
|
30
|
+
srcMode,
|
|
31
|
+
type: 'style',
|
|
32
|
+
testKey: 'prop',
|
|
33
|
+
warn: (msg) => {
|
|
34
|
+
console.warn('[style compiler warn]: ' + msg)
|
|
35
|
+
},
|
|
36
|
+
error: (msg) => {
|
|
37
|
+
console.error('[style compiler error]: ' + msg)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
root.walkRules(rule => {
|
|
42
|
+
const classMapValue = {}
|
|
43
|
+
rule.walkDecls(({ prop, value }) => {
|
|
44
|
+
if (cssPrefixExp.test(prop) || cssPrefixExp.test(value)) return
|
|
45
|
+
let newData = rulesRunner({ prop, value })
|
|
46
|
+
if (!newData) return
|
|
47
|
+
if (!Array.isArray(newData)) {
|
|
48
|
+
newData = [newData]
|
|
49
|
+
}
|
|
50
|
+
newData.forEach(item => {
|
|
51
|
+
prop = dash2hump(item.prop)
|
|
52
|
+
value = item.value
|
|
53
|
+
if (Array.isArray(value)) {
|
|
54
|
+
value = value.map(item => formatValue(item))
|
|
55
|
+
} else if (typeof value === 'object') {
|
|
56
|
+
for (const key in value) {
|
|
57
|
+
value[key] = formatValue(value[key])
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
value = formatValue(value)
|
|
61
|
+
}
|
|
62
|
+
classMapValue[prop] = value
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const classMapKeys = []
|
|
67
|
+
|
|
68
|
+
selectorParser(selectors => {
|
|
69
|
+
selectors.each(selector => {
|
|
70
|
+
if (selector.nodes.length === 1 && selector.nodes[0].type === 'class') {
|
|
71
|
+
classMapKeys.push(selector.nodes[0].value)
|
|
72
|
+
} else {
|
|
73
|
+
rule.error('Only single class selector is supported in react native mode temporarily.')
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
}).processSync(rule.selector)
|
|
77
|
+
|
|
78
|
+
if (classMapKeys.length) {
|
|
79
|
+
classMapKeys.forEach((key) => {
|
|
80
|
+
if (Object.keys(classMapValue).length) {
|
|
81
|
+
classMap[key] = Object.assign(classMap[key] || {}, classMapValue)
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
return classMap
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
getClassMap
|
|
91
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
interface EventConfig {
|
|
2
|
+
[key: string]: string[];
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const eventConfigMap: EventConfig = {
|
|
6
|
+
bindtap: ['onTouchStart', 'onTouchMove', 'onTouchEnd'],
|
|
7
|
+
bindlongpress: ['onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'],
|
|
8
|
+
bindtouchstart: ['onTouchStart'],
|
|
9
|
+
bindtouchmove: ['onTouchMove'],
|
|
10
|
+
bindtouchend: ['onTouchEnd'],
|
|
11
|
+
bindtouchcancel: ['onTouchCancel'],
|
|
12
|
+
catchtap: ['onTouchStart', 'onTouchMove', 'onTouchEnd'],
|
|
13
|
+
catchlongpress: ['onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'],
|
|
14
|
+
catchtouchstart: ['onTouchStart'],
|
|
15
|
+
catchtouchmove: ['onTouchMove'],
|
|
16
|
+
catchtouchend: ['onTouchEnd'],
|
|
17
|
+
catchtouchcancel: ['onTouchCancel'],
|
|
18
|
+
'capture-bindtap': ['onTouchStartCapture', 'onTouchMoveCapture', 'onTouchEndCapture'],
|
|
19
|
+
'capture-bindlongpress': ['onTouchStartCapture', 'onTouchMoveCapture', 'onTouchEndCapture', 'onTouchCancelCapture'],
|
|
20
|
+
'capture-bindtouchstart': ['onTouchStartCapture'],
|
|
21
|
+
'capture-bindtouchmove': ['onTouchMoveCapture'],
|
|
22
|
+
'capture-bindtouchend': ['onTouchEndCapture'],
|
|
23
|
+
'capture-bindtouchcancel': ['onTouchCancelCapture'],
|
|
24
|
+
'capture-catchtap': ['onTouchStartCapture', 'onTouchMoveCapture', 'onTouchEndCapture'],
|
|
25
|
+
'capture-catchlongpress': ['onTouchStartCapture', 'onTouchMoveCapture', 'onTouchEndCapture', 'onTouchCancelCapture'],
|
|
26
|
+
'capture-catchtouchstart': ['onTouchStartCapture'],
|
|
27
|
+
'capture-catchtouchmove': ['onTouchMoveCapture'],
|
|
28
|
+
'capture-catchtouchend': ['onTouchEndCapture'],
|
|
29
|
+
'capture-catchtouchcancel': ['onTouchCancelCapture']
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default eventConfigMap
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { useRef } from 'react'
|
|
2
|
+
import { omit } from './utils'
|
|
3
|
+
import eventConfigMap from './event.config'
|
|
4
|
+
import {
|
|
5
|
+
Props,
|
|
6
|
+
AdditionalProps,
|
|
7
|
+
RemoveProps,
|
|
8
|
+
UseInnerPropsConfig,
|
|
9
|
+
InnerRef,
|
|
10
|
+
SetTimeoutReturnType,
|
|
11
|
+
DataSetType,
|
|
12
|
+
LayoutRef,
|
|
13
|
+
NativeTouchEvent
|
|
14
|
+
} from './getInnerListeners.type'
|
|
15
|
+
|
|
16
|
+
const getTouchEvent = (
|
|
17
|
+
type: string,
|
|
18
|
+
event: NativeTouchEvent,
|
|
19
|
+
props: Props,
|
|
20
|
+
config: UseInnerPropsConfig
|
|
21
|
+
) => {
|
|
22
|
+
const nativeEvent = event.nativeEvent
|
|
23
|
+
const {
|
|
24
|
+
timestamp,
|
|
25
|
+
pageX,
|
|
26
|
+
pageY,
|
|
27
|
+
touches,
|
|
28
|
+
changedTouches
|
|
29
|
+
} = nativeEvent
|
|
30
|
+
const { id } = props
|
|
31
|
+
const { layoutRef } = config
|
|
32
|
+
return {
|
|
33
|
+
...event,
|
|
34
|
+
type,
|
|
35
|
+
timeStamp: timestamp,
|
|
36
|
+
target: {
|
|
37
|
+
...(event.target || {}),
|
|
38
|
+
id: id || '',
|
|
39
|
+
dataset: getDataSet(props),
|
|
40
|
+
offsetLeft: layoutRef?.current?.offsetLeft || 0,
|
|
41
|
+
offsetTop: layoutRef?.current?.offsetTop || 0
|
|
42
|
+
},
|
|
43
|
+
detail: {
|
|
44
|
+
x: pageX,
|
|
45
|
+
y: pageY
|
|
46
|
+
},
|
|
47
|
+
touches: touches.map(item => {
|
|
48
|
+
return {
|
|
49
|
+
identifier: item.identifier,
|
|
50
|
+
pageX: item.pageX,
|
|
51
|
+
pageY: item.pageY,
|
|
52
|
+
clientX: item.locationX,
|
|
53
|
+
clientY: item.locationY
|
|
54
|
+
}
|
|
55
|
+
}),
|
|
56
|
+
changedTouches: changedTouches.map(item => {
|
|
57
|
+
return {
|
|
58
|
+
identifier: item.identifier,
|
|
59
|
+
pageX: item.pageX,
|
|
60
|
+
pageY: item.pageY,
|
|
61
|
+
clientX: item.locationX,
|
|
62
|
+
clientY: item.locationY
|
|
63
|
+
}
|
|
64
|
+
}),
|
|
65
|
+
persist: event.persist,
|
|
66
|
+
stopPropagation: event.stopPropagation,
|
|
67
|
+
preventDefault: event.preventDefault
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const getDataSet = (props: Record<string, any>) => {
|
|
72
|
+
const result: DataSetType = {}
|
|
73
|
+
|
|
74
|
+
for (const key in props) {
|
|
75
|
+
if (key.indexOf('data-') === 0) {
|
|
76
|
+
const newKey = key.substr(5)
|
|
77
|
+
result[newKey] = props[key]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return result
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const getCustomEvent = (
|
|
85
|
+
type: string = '',
|
|
86
|
+
oe: any = {},
|
|
87
|
+
{ detail = {}, layoutRef }: { detail?: Record<string, unknown>; layoutRef: LayoutRef },
|
|
88
|
+
props: Props = {}
|
|
89
|
+
) => {
|
|
90
|
+
return {
|
|
91
|
+
...oe,
|
|
92
|
+
type,
|
|
93
|
+
detail,
|
|
94
|
+
target: {
|
|
95
|
+
...(oe.target || {}),
|
|
96
|
+
id: props.id || '',
|
|
97
|
+
dataset: getDataSet(props),
|
|
98
|
+
offsetLeft: layoutRef?.current?.offsetLeft || 0,
|
|
99
|
+
offsetTop: layoutRef?.current?.offsetTop || 0
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const useInnerProps = (
|
|
106
|
+
props: Props = {},
|
|
107
|
+
additionalProps: AdditionalProps = {},
|
|
108
|
+
removeProps: RemoveProps = [],
|
|
109
|
+
rawConfig: UseInnerPropsConfig
|
|
110
|
+
) => {
|
|
111
|
+
const ref = useRef<InnerRef>({
|
|
112
|
+
startTimer: {
|
|
113
|
+
bubble: null,
|
|
114
|
+
capture: null
|
|
115
|
+
},
|
|
116
|
+
needPress: {
|
|
117
|
+
bubble: false,
|
|
118
|
+
capture: false
|
|
119
|
+
},
|
|
120
|
+
mpxPressInfo: {
|
|
121
|
+
detail: {
|
|
122
|
+
x: 0,
|
|
123
|
+
y: 0
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const propsRef = useRef<Record<string, any>>({})
|
|
129
|
+
const eventConfig: { [key: string]: string[] } = {}
|
|
130
|
+
const config = rawConfig || {}
|
|
131
|
+
|
|
132
|
+
propsRef.current = { ...props, ...additionalProps }
|
|
133
|
+
|
|
134
|
+
for (const key in eventConfigMap) {
|
|
135
|
+
if (propsRef.current[key]) {
|
|
136
|
+
eventConfig[key] = eventConfigMap[key]
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!(Object.keys(eventConfig).length) || config.disableTouch) {
|
|
141
|
+
return omit(propsRef.current, removeProps)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function handleEmitEvent(
|
|
145
|
+
events: string[],
|
|
146
|
+
type: string,
|
|
147
|
+
oe: NativeTouchEvent
|
|
148
|
+
) {
|
|
149
|
+
events.forEach(event => {
|
|
150
|
+
if (propsRef.current[event]) {
|
|
151
|
+
const match = /^(catch|capture-catch):?(.*?)(?:\.(.*))?$/.exec(event)
|
|
152
|
+
if (match) {
|
|
153
|
+
oe.stopPropagation()
|
|
154
|
+
}
|
|
155
|
+
propsRef.current[event](getTouchEvent(type, oe, propsRef.current, config))
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
function handleTouchstart(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
160
|
+
e.persist()
|
|
161
|
+
const bubbleTouchEvent = ['catchtouchstart', 'bindtouchstart']
|
|
162
|
+
const bubblePressEvent = ['catchlongpress', 'bindlongpress']
|
|
163
|
+
const captureTouchEvent = ['capture-catchtouchstart', 'capture-bindtouchstart']
|
|
164
|
+
const capturePressEvent = ['capture-catchlongpress', 'capture-bindlongpress']
|
|
165
|
+
ref.current.startTimer[type] = null
|
|
166
|
+
ref.current.needPress[type] = true
|
|
167
|
+
const nativeEvent = e.nativeEvent
|
|
168
|
+
ref.current.mpxPressInfo.detail = {
|
|
169
|
+
x: nativeEvent.changedTouches[0].pageX,
|
|
170
|
+
y: nativeEvent.changedTouches[0].pageY
|
|
171
|
+
}
|
|
172
|
+
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
173
|
+
const currentPressEvent = type === 'bubble' ? bubblePressEvent : capturePressEvent
|
|
174
|
+
handleEmitEvent(currentTouchEvent, 'touchstart', e)
|
|
175
|
+
const { catchlongpress, bindlongpress, 'capture-catchlongpress': captureCatchlongpress, 'capture-bindlongpress': captureBindlongpress } = propsRef.current
|
|
176
|
+
if (catchlongpress || bindlongpress || captureCatchlongpress || captureBindlongpress) {
|
|
177
|
+
ref.current.startTimer[type] = setTimeout(() => {
|
|
178
|
+
ref.current.needPress[type] = false
|
|
179
|
+
handleEmitEvent(currentPressEvent, 'longpress', e)
|
|
180
|
+
}, 350)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function handleTouchmove(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
185
|
+
const bubbleTouchEvent = ['catchtouchmove', 'bindtouchmove']
|
|
186
|
+
const captureTouchEvent = ['capture-catchtouchmove', 'capture-bindtouchmove']
|
|
187
|
+
const tapDetailInfo = ref.current.mpxPressInfo.detail || { x: 0, y: 0 }
|
|
188
|
+
const nativeEvent = e.nativeEvent
|
|
189
|
+
const currentPageX = nativeEvent.changedTouches[0].pageX
|
|
190
|
+
const currentPageY = nativeEvent.changedTouches[0].pageY
|
|
191
|
+
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
192
|
+
if (Math.abs(currentPageX - tapDetailInfo.x) > 1 || Math.abs(currentPageY - tapDetailInfo.y) > 1) {
|
|
193
|
+
ref.current.needPress[type] = false
|
|
194
|
+
ref.current.startTimer[type] && clearTimeout(ref.current.startTimer[type] as SetTimeoutReturnType)
|
|
195
|
+
ref.current.startTimer[type] = null
|
|
196
|
+
}
|
|
197
|
+
handleEmitEvent(currentTouchEvent, 'touchmove', e)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function handleTouchend(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
201
|
+
const bubbleTouchEvent = ['catchtouchend', 'bindtouchend']
|
|
202
|
+
const bubbleTapEvent = ['catchtap', 'bindtap']
|
|
203
|
+
const captureTouchEvent = ['capture-catchtouchend', 'capture-bindtouchend']
|
|
204
|
+
const captureTapEvent = ['capture-catchtap', 'capture-bindtap']
|
|
205
|
+
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
206
|
+
const currentTapEvent = type === 'bubble' ? bubbleTapEvent : captureTapEvent
|
|
207
|
+
ref.current.startTimer[type] && clearTimeout(ref.current.startTimer[type] as SetTimeoutReturnType)
|
|
208
|
+
ref.current.startTimer[type] = null
|
|
209
|
+
handleEmitEvent(currentTouchEvent, 'touchend', e)
|
|
210
|
+
if (ref.current.needPress[type]) {
|
|
211
|
+
handleEmitEvent(currentTapEvent, 'tap', e)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function handleTouchcancel(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
216
|
+
const bubbleTouchEvent = ['catchtouchcancel', 'bindtouchcancel']
|
|
217
|
+
const captureTouchEvent = ['capture-catchtouchcancel', 'capture-bindtouchcancel']
|
|
218
|
+
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
219
|
+
ref.current.startTimer[type] && clearTimeout(ref.current.startTimer[type] as SetTimeoutReturnType)
|
|
220
|
+
ref.current.startTimer[type] = null
|
|
221
|
+
handleEmitEvent(currentTouchEvent, 'touchcancel', e)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const touchEventList = [{
|
|
225
|
+
eventName: 'onTouchStart',
|
|
226
|
+
handler: (e: NativeTouchEvent) => {
|
|
227
|
+
handleTouchstart(e, 'bubble')
|
|
228
|
+
}
|
|
229
|
+
}, {
|
|
230
|
+
eventName: 'onTouchMove',
|
|
231
|
+
handler: (e: NativeTouchEvent) => {
|
|
232
|
+
handleTouchmove(e, 'bubble')
|
|
233
|
+
}
|
|
234
|
+
}, {
|
|
235
|
+
eventName: 'onTouchEnd',
|
|
236
|
+
handler: (e: NativeTouchEvent) => {
|
|
237
|
+
handleTouchend(e, 'bubble')
|
|
238
|
+
}
|
|
239
|
+
}, {
|
|
240
|
+
eventName: 'onTouchCancel',
|
|
241
|
+
handler: (e: NativeTouchEvent) => {
|
|
242
|
+
handleTouchcancel(e, 'bubble')
|
|
243
|
+
}
|
|
244
|
+
}, {
|
|
245
|
+
eventName: 'onTouchStartCapture',
|
|
246
|
+
handler: (e: NativeTouchEvent) => {
|
|
247
|
+
handleTouchstart(e, 'capture')
|
|
248
|
+
}
|
|
249
|
+
}, {
|
|
250
|
+
eventName: 'onTouchMoveCapture',
|
|
251
|
+
handler: (e: NativeTouchEvent) => {
|
|
252
|
+
handleTouchmove(e, 'capture')
|
|
253
|
+
}
|
|
254
|
+
}, {
|
|
255
|
+
eventName: 'onTouchEndCapture',
|
|
256
|
+
handler: (e: NativeTouchEvent) => {
|
|
257
|
+
handleTouchend(e, 'capture')
|
|
258
|
+
}
|
|
259
|
+
}, {
|
|
260
|
+
eventName: 'onTouchCancelCapture',
|
|
261
|
+
handler: (e: NativeTouchEvent) => {
|
|
262
|
+
handleTouchcancel(e, 'capture')
|
|
263
|
+
}
|
|
264
|
+
}]
|
|
265
|
+
|
|
266
|
+
const events: Record<string, (e: NativeTouchEvent) => void> = {}
|
|
267
|
+
|
|
268
|
+
const transformedEventKeys: string[] = []
|
|
269
|
+
for (const key in eventConfig) {
|
|
270
|
+
transformedEventKeys.push(...eventConfig[key])
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const finalEventKeys = [...new Set(transformedEventKeys)]
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
touchEventList.forEach(item => {
|
|
277
|
+
if (finalEventKeys.includes(item.eventName)) {
|
|
278
|
+
events[item.eventName] = item.handler
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
const rawEventKeys = Object.keys(eventConfig)
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
...events,
|
|
286
|
+
...omit(propsRef.current, [...rawEventKeys, ...removeProps])
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
export default useInnerProps
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { NativeSyntheticEvent } from 'react-native'
|
|
3
|
+
|
|
4
|
+
type LayoutRef = React.MutableRefObject<any>
|
|
5
|
+
|
|
6
|
+
type SetTimeoutReturnType = ReturnType<typeof setTimeout>
|
|
7
|
+
|
|
8
|
+
type Props = Record<string, any>
|
|
9
|
+
|
|
10
|
+
type AdditionalProps = Record<string, any>;
|
|
11
|
+
|
|
12
|
+
type RemoveProps = string[];
|
|
13
|
+
|
|
14
|
+
type NativeTouchEvent = NativeSyntheticEvent<NativeEvent>
|
|
15
|
+
|
|
16
|
+
interface NativeEvent {
|
|
17
|
+
timestamp: number;
|
|
18
|
+
pageX: number;
|
|
19
|
+
pageY: number;
|
|
20
|
+
touches: TouchPoint[]
|
|
21
|
+
changedTouches: TouchPoint[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface TouchPoint {
|
|
25
|
+
identifier: number;
|
|
26
|
+
pageX: number;
|
|
27
|
+
pageY: number;
|
|
28
|
+
clientX: number;
|
|
29
|
+
clientY: number;
|
|
30
|
+
locationX?: number;
|
|
31
|
+
locationY?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface InnerRef {
|
|
35
|
+
startTimer: {
|
|
36
|
+
bubble: null | ReturnType<typeof setTimeout>;
|
|
37
|
+
capture: null | ReturnType<typeof setTimeout>;
|
|
38
|
+
};
|
|
39
|
+
needPress: {
|
|
40
|
+
bubble: boolean;
|
|
41
|
+
capture: boolean;
|
|
42
|
+
};
|
|
43
|
+
mpxPressInfo: {
|
|
44
|
+
detail: {
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
interface UseInnerPropsConfig {
|
|
51
|
+
layoutRef: LayoutRef;
|
|
52
|
+
disableTouch?: boolean
|
|
53
|
+
}
|
|
54
|
+
interface DataSetType {
|
|
55
|
+
[key: string]: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
NativeTouchEvent,
|
|
60
|
+
Props,
|
|
61
|
+
AdditionalProps,
|
|
62
|
+
RemoveProps,
|
|
63
|
+
UseInnerPropsConfig,
|
|
64
|
+
InnerRef,
|
|
65
|
+
LayoutRef,
|
|
66
|
+
SetTimeoutReturnType,
|
|
67
|
+
DataSetType
|
|
68
|
+
}
|