@mpxjs/webpack-plugin 2.9.70-alpha.0 → 2.9.70
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/LICENSE +433 -0
- package/README.md +1 -1
- package/lib/config.js +0 -14
- package/lib/dependencies/ResolveDependency.js +0 -5
- package/lib/index.js +7 -38
- package/lib/json-compiler/helper.js +3 -3
- package/lib/loader.js +0 -53
- package/lib/parser.js +1 -1
- package/lib/platform/json/wx/index.js +21 -8
- package/lib/platform/style/wx/index.js +51 -54
- package/lib/platform/template/wx/component-config/button.js +2 -14
- package/lib/platform/template/wx/component-config/fix-component-name.js +15 -12
- package/lib/platform/template/wx/component-config/image.js +0 -4
- package/lib/platform/template/wx/component-config/index.js +1 -1
- package/lib/platform/template/wx/component-config/input.js +0 -4
- package/lib/platform/template/wx/component-config/rich-text.js +6 -2
- package/lib/platform/template/wx/component-config/scroll-view.js +0 -4
- package/lib/platform/template/wx/component-config/switch.js +0 -4
- package/lib/platform/template/wx/component-config/text.js +0 -4
- package/lib/platform/template/wx/component-config/textarea.js +0 -5
- package/lib/platform/template/wx/component-config/unsupported.js +1 -1
- package/lib/platform/template/wx/component-config/view.js +0 -4
- package/lib/platform/template/wx/index.js +1 -127
- package/lib/resolve-loader.js +1 -4
- package/lib/runtime/components/react/dist/getInnerListeners.js +5 -6
- package/lib/runtime/components/react/dist/mpx-canvas/html.js +2 -4
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +5 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +96 -107
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +26 -27
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +480 -0
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +68 -0
- package/lib/runtime/components/react/dist/mpx-swiper/type.js +1 -0
- package/lib/runtime/components/react/dist/mpx-view.jsx +6 -3
- package/lib/runtime/components/react/dist/pickerFaces.js +6 -12
- package/lib/runtime/components/react/dist/{pickerViewOverlay.jsx → pickerOverlay.jsx} +3 -5
- package/lib/runtime/components/react/dist/useAnimationHooks.js +7 -8
- package/lib/runtime/components/react/dist/utils.jsx +89 -60
- package/lib/runtime/components/react/event.config.ts +25 -26
- package/lib/runtime/components/react/getInnerListeners.ts +212 -169
- package/lib/runtime/components/react/mpx-button.tsx +9 -14
- package/lib/runtime/components/react/mpx-canvas/html.ts +2 -4
- package/lib/runtime/components/react/mpx-canvas/index.tsx +44 -46
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +15 -13
- package/lib/runtime/components/react/mpx-checkbox.tsx +20 -21
- package/lib/runtime/components/react/mpx-form.tsx +15 -20
- package/lib/runtime/components/react/mpx-icon.tsx +2 -2
- package/lib/runtime/components/react/mpx-image.tsx +87 -47
- package/lib/runtime/components/react/mpx-input.tsx +24 -32
- package/lib/runtime/components/react/mpx-label.tsx +12 -14
- package/lib/runtime/components/react/mpx-movable-area.tsx +10 -16
- package/lib/runtime/components/react/mpx-movable-view.tsx +20 -24
- package/lib/runtime/components/react/mpx-navigator.tsx +2 -8
- package/lib/runtime/components/react/mpx-radio-group.tsx +13 -15
- package/lib/runtime/components/react/mpx-radio.tsx +19 -25
- package/lib/runtime/components/react/mpx-rich-text/html.ts +40 -0
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +121 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +3 -5
- package/lib/runtime/components/react/mpx-scroll-view.tsx +40 -41
- package/lib/runtime/components/react/mpx-switch.tsx +19 -15
- package/lib/runtime/components/react/mpx-text.tsx +8 -16
- package/lib/runtime/components/react/mpx-textarea.tsx +11 -10
- package/lib/runtime/components/react/mpx-view.tsx +18 -20
- package/lib/runtime/components/react/mpx-web-view.tsx +94 -59
- package/lib/runtime/components/react/types/global.d.ts +2 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +36 -12
- package/lib/runtime/components/react/utils.tsx +91 -60
- package/lib/runtime/components/web/mpx-web-view.vue +34 -20
- package/lib/runtime/optionProcessor.js +0 -22
- package/lib/style-compiler/index.js +1 -1
- package/lib/style-compiler/plugins/scope-id.js +30 -2
- package/lib/template-compiler/compiler.js +30 -26
- package/lib/utils/env.js +1 -6
- package/lib/utils/pre-process-json.js +9 -5
- package/package.json +4 -7
- package/lib/dependencies/AddEntryDependency.js +0 -24
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +0 -39
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +0 -606
- package/lib/runtime/components/react/dist/pickerVIewContext.js +0 -9
- package/lib/runtime/components/react/dist/pickerViewMask.jsx +0 -18
- package/lib/runtime/components/tenon/getInnerListeners.js +0 -334
- package/lib/runtime/components/tenon/tenon-button.vue +0 -309
- package/lib/runtime/components/tenon/tenon-image.vue +0 -66
- package/lib/runtime/components/tenon/tenon-input.vue +0 -171
- package/lib/runtime/components/tenon/tenon-rich-text.vue +0 -26
- package/lib/runtime/components/tenon/tenon-scroll-view.vue +0 -127
- package/lib/runtime/components/tenon/tenon-switch.vue +0 -96
- package/lib/runtime/components/tenon/tenon-text.vue +0 -70
- package/lib/runtime/components/tenon/tenon-textarea.vue +0 -86
- package/lib/runtime/components/tenon/tenon-view.vue +0 -93
- package/lib/runtime/components/web/event.js +0 -105
- package/lib/runtime/optionProcessor.tenon.js +0 -84
- package/lib/style-compiler/plugins/hm.js +0 -20
- package/lib/tenon/index.js +0 -117
- package/lib/tenon/processJSON.js +0 -352
- package/lib/tenon/processScript.js +0 -203
- package/lib/tenon/processStyles.js +0 -21
- package/lib/tenon/processTemplate.js +0 -126
- package/lib/tenon/script-helper.js +0 -223
- package/lib/utils/get-relative-path.js +0 -25
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { forwardRef, JSX,
|
|
2
|
-
import {
|
|
3
|
-
import { View } from 'react-native'
|
|
1
|
+
import { forwardRef, JSX, useRef, useContext, useMemo, createElement } from 'react'
|
|
2
|
+
import { warn, getFocusedNavigation, isFunction } from '@mpxjs/utils'
|
|
4
3
|
import { Portal } from '@ant-design/react-native'
|
|
5
4
|
import { getCustomEvent } from './getInnerListeners'
|
|
6
5
|
import { promisify, redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy'
|
|
@@ -31,26 +30,25 @@ interface WebViewProps {
|
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
interface PayloadData {
|
|
34
|
-
|
|
33
|
+
[x: string]: any
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
type MessageData = {
|
|
38
37
|
payload?: PayloadData,
|
|
38
|
+
args?: Array<any>,
|
|
39
39
|
type?: string,
|
|
40
40
|
callbackId?: number
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((props, ref): JSX.Element => {
|
|
44
|
-
const { src, bindmessage
|
|
45
|
-
|
|
46
|
-
return (<View></View>)
|
|
47
|
-
}
|
|
43
|
+
const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((props, ref): JSX.Element | null => {
|
|
44
|
+
const { src, bindmessage, bindload, binderror } = props
|
|
45
|
+
const mpx = global.__mpx
|
|
48
46
|
if (props.style) {
|
|
49
47
|
warn('The web-view component does not support the style prop.')
|
|
50
48
|
}
|
|
51
49
|
const pageId = useContext(RouteContext)
|
|
52
50
|
const currentPage = useMemo(() => getCurrentPage(pageId), [pageId])
|
|
53
|
-
|
|
51
|
+
const webViewRef = useRef<WebView>(null)
|
|
54
52
|
const defaultWebViewStyle = {
|
|
55
53
|
position: 'absolute' as 'absolute' | 'relative' | 'static',
|
|
56
54
|
left: 0 as number,
|
|
@@ -59,34 +57,14 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
59
57
|
bottom: 0 as number
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
const webViewRef = useRef<WebView>(null)
|
|
63
60
|
useNodesRef<WebView, WebViewProps>(props, ref, webViewRef, {
|
|
64
61
|
style: defaultWebViewStyle
|
|
65
62
|
})
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// 这里是 WebView 销毁前执行的逻辑
|
|
70
|
-
bindmessage(getCustomEvent('messsage', {}, {
|
|
71
|
-
detail: {
|
|
72
|
-
data: _messageList.current
|
|
73
|
-
},
|
|
74
|
-
layoutRef: webViewRef
|
|
75
|
-
}))
|
|
64
|
+
if (!src) {
|
|
65
|
+
return null
|
|
76
66
|
}
|
|
77
67
|
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
if (currentPage) {
|
|
80
|
-
currentPage.__webViewUrl = src
|
|
81
|
-
}
|
|
82
|
-
}, [src, currentPage])
|
|
83
|
-
|
|
84
|
-
useEffect(() => {
|
|
85
|
-
// 组件卸载时执行
|
|
86
|
-
return () => {
|
|
87
|
-
handleUnload()
|
|
88
|
-
}
|
|
89
|
-
}, [])
|
|
90
68
|
const _load = function (res: WebViewNavigationEvent) {
|
|
91
69
|
const result = {
|
|
92
70
|
type: 'load',
|
|
@@ -107,8 +85,33 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
107
85
|
}
|
|
108
86
|
binderror(result)
|
|
109
87
|
}
|
|
88
|
+
const injectedJavaScript = `
|
|
89
|
+
if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
|
|
90
|
+
var _documentTitle = document.title;
|
|
91
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
92
|
+
type: 'setTitle',
|
|
93
|
+
payload: {
|
|
94
|
+
_documentTitle: _documentTitle
|
|
95
|
+
}
|
|
96
|
+
}))
|
|
97
|
+
Object.defineProperty(document, 'title', {
|
|
98
|
+
set (val) {
|
|
99
|
+
_documentTitle = val
|
|
100
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
101
|
+
type: 'setTitle',
|
|
102
|
+
payload: {
|
|
103
|
+
_documentTitle: _documentTitle
|
|
104
|
+
}
|
|
105
|
+
}))
|
|
106
|
+
},
|
|
107
|
+
get () {
|
|
108
|
+
return _documentTitle
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
`
|
|
110
113
|
const _changeUrl = function (navState: WebViewNavigation) {
|
|
111
|
-
if (
|
|
114
|
+
if (navState.navigationType) { // navigationType这个事件在页面开始加载时和页面加载完成时都会被触发所以判断这个避免其他无效触发执行该逻辑
|
|
112
115
|
currentPage.__webViewUrl = navState.url
|
|
113
116
|
}
|
|
114
117
|
}
|
|
@@ -121,43 +124,79 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
121
124
|
if (typeof nativeEventData === 'string') {
|
|
122
125
|
data = JSON.parse(nativeEventData)
|
|
123
126
|
}
|
|
124
|
-
} catch (e) {
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
+
} catch (e) {}
|
|
128
|
+
const args = data.args
|
|
127
129
|
const postData: PayloadData = data.payload || {}
|
|
128
|
-
|
|
130
|
+
const params = Array.isArray(args) ? args : [postData]
|
|
131
|
+
const type = data.type
|
|
132
|
+
switch (type) {
|
|
133
|
+
case 'setTitle':
|
|
134
|
+
{ // case下不允许直接声明,包个块解决该问题
|
|
135
|
+
const title = postData._documentTitle
|
|
136
|
+
if (title) {
|
|
137
|
+
const navigation = getFocusedNavigation()
|
|
138
|
+
navigation && navigation.setOptions({ title })
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
break
|
|
129
142
|
case 'postMessage':
|
|
130
|
-
|
|
143
|
+
bindmessage && bindmessage(getCustomEvent('messsage', {}, { // RN组件销毁顺序与小程序不一致,所以改成和支付宝消息一致
|
|
144
|
+
detail: {
|
|
145
|
+
data: params[0]?.data
|
|
146
|
+
}
|
|
147
|
+
}))
|
|
131
148
|
asyncCallback = Promise.resolve({
|
|
132
149
|
errMsg: 'invokeWebappApi:ok'
|
|
133
150
|
})
|
|
134
151
|
break
|
|
135
152
|
case 'navigateTo':
|
|
136
|
-
asyncCallback = navObj.navigateTo(
|
|
153
|
+
asyncCallback = navObj.navigateTo(...params)
|
|
137
154
|
break
|
|
138
155
|
case 'navigateBack':
|
|
139
|
-
asyncCallback = navObj.navigateBack(
|
|
156
|
+
asyncCallback = navObj.navigateBack(...params)
|
|
140
157
|
break
|
|
141
158
|
case 'redirectTo':
|
|
142
|
-
asyncCallback = navObj.redirectTo(
|
|
159
|
+
asyncCallback = navObj.redirectTo(...params)
|
|
143
160
|
break
|
|
144
161
|
case 'switchTab':
|
|
145
|
-
asyncCallback = navObj.switchTab(
|
|
162
|
+
asyncCallback = navObj.switchTab(...params)
|
|
146
163
|
break
|
|
147
164
|
case 'reLaunch':
|
|
148
|
-
asyncCallback = navObj.reLaunch(
|
|
165
|
+
asyncCallback = navObj.reLaunch(...params)
|
|
166
|
+
break
|
|
167
|
+
default:
|
|
168
|
+
if (type) {
|
|
169
|
+
const implement = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations[type]
|
|
170
|
+
if (isFunction(implement)) {
|
|
171
|
+
asyncCallback = Promise.resolve(implement(...params))
|
|
172
|
+
} else {
|
|
173
|
+
/* eslint-disable prefer-promise-reject-errors */
|
|
174
|
+
asyncCallback = Promise.reject({
|
|
175
|
+
errMsg: `未在apiImplementations中配置${type}方法`
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
}
|
|
149
179
|
break
|
|
150
180
|
}
|
|
151
181
|
|
|
152
182
|
asyncCallback && asyncCallback.then((res: any) => {
|
|
153
183
|
if (webViewRef.current?.postMessage) {
|
|
154
184
|
const test = JSON.stringify({
|
|
155
|
-
type
|
|
185
|
+
type,
|
|
156
186
|
callbackId: data.callbackId,
|
|
157
187
|
result: res
|
|
158
188
|
})
|
|
159
189
|
webViewRef.current.postMessage(test)
|
|
160
190
|
}
|
|
191
|
+
}).catch((error: any) => {
|
|
192
|
+
if (webViewRef.current?.postMessage) {
|
|
193
|
+
const test = JSON.stringify({
|
|
194
|
+
type,
|
|
195
|
+
callbackId: data.callbackId,
|
|
196
|
+
error
|
|
197
|
+
})
|
|
198
|
+
webViewRef.current.postMessage(test)
|
|
199
|
+
}
|
|
161
200
|
})
|
|
162
201
|
}
|
|
163
202
|
const events = {}
|
|
@@ -172,21 +211,17 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
172
211
|
onError: _error
|
|
173
212
|
})
|
|
174
213
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
onNavigationStateChange={_changeUrl}
|
|
187
|
-
javaScriptEnabled={true}
|
|
188
|
-
></WebView>
|
|
189
|
-
</Portal>)
|
|
214
|
+
extendObject(events, {
|
|
215
|
+
onMessage: _message
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
return createElement(Portal, null, createElement(WebView, extendObject({
|
|
219
|
+
style: defaultWebViewStyle,
|
|
220
|
+
source: { uri: src },
|
|
221
|
+
ref: webViewRef,
|
|
222
|
+
javaScriptEnabled: true,
|
|
223
|
+
onNavigationStateChange: _changeUrl
|
|
224
|
+
}, events)))
|
|
190
225
|
})
|
|
191
226
|
|
|
192
227
|
_WebView.displayName = 'MpxWebview'
|
|
@@ -83,12 +83,34 @@ const InitialValue: ExtendedViewStyle = Object.assign({
|
|
|
83
83
|
const TransformOrigin = 'transformOrigin'
|
|
84
84
|
// transform
|
|
85
85
|
const isTransform = (key: string) => Object.keys(TransformInitial).includes(key)
|
|
86
|
+
// 多value解析
|
|
87
|
+
const parseValues = (str: string, char = ' ') => {
|
|
88
|
+
let stack = 0
|
|
89
|
+
let temp = ''
|
|
90
|
+
const result = []
|
|
91
|
+
for (let i = 0; i < str.length; i++) {
|
|
92
|
+
if (str[i] === '(') {
|
|
93
|
+
stack++
|
|
94
|
+
} else if (str[i] === ')') {
|
|
95
|
+
stack--
|
|
96
|
+
}
|
|
97
|
+
// 非括号内 或者 非分隔字符且非空
|
|
98
|
+
if (stack !== 0 || (str[i] !== char && str[i] !== ' ')) {
|
|
99
|
+
temp += str[i]
|
|
100
|
+
}
|
|
101
|
+
if ((stack === 0 && str[i] === char) || i === str.length - 1) {
|
|
102
|
+
result.push(temp)
|
|
103
|
+
temp = ''
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return result
|
|
107
|
+
}
|
|
86
108
|
// parse string transform, eg: transform: 'rotateX(45deg) rotateZ(0.785398rad)'
|
|
87
109
|
const parseTransform = (transformStr: string) => {
|
|
88
|
-
const values = transformStr
|
|
110
|
+
const values = parseValues(transformStr)
|
|
89
111
|
const transform: {[propName: string]: string|number|number[]}[] = []
|
|
90
112
|
values.forEach(item => {
|
|
91
|
-
const match = item.match(/([/\w]+)\((
|
|
113
|
+
const match = item.match(/([/\w]+)\((.+)\)/)
|
|
92
114
|
if (match && match.length >= 3) {
|
|
93
115
|
let key = match[1]
|
|
94
116
|
const val = match[2]
|
|
@@ -109,7 +131,7 @@ const parseTransform = (transformStr: string) => {
|
|
|
109
131
|
break
|
|
110
132
|
case 'matrix':
|
|
111
133
|
case 'matrix3d':
|
|
112
|
-
transform.push({ [key]: val
|
|
134
|
+
transform.push({ [key]: parseValues(val, ',').map(val => +val) })
|
|
113
135
|
break
|
|
114
136
|
case 'translate':
|
|
115
137
|
case 'scale':
|
|
@@ -120,8 +142,8 @@ const parseTransform = (transformStr: string) => {
|
|
|
120
142
|
{
|
|
121
143
|
// 2 个以上的值处理
|
|
122
144
|
key = key.replace('3d', '')
|
|
123
|
-
const vals = val
|
|
124
|
-
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
145
|
+
const vals = parseValues(val, ',').splice(0, key === 'rotate' ? 4 : 3)
|
|
146
|
+
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
125
147
|
if (vals.length === 1 && key === 'scale') {
|
|
126
148
|
vals.push(vals[0])
|
|
127
149
|
}
|
|
@@ -218,12 +240,14 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
|
|
|
218
240
|
}
|
|
219
241
|
// 添加每个key的多次step动画
|
|
220
242
|
animatedKeys.forEach(key => {
|
|
221
|
-
|
|
243
|
+
const ruleV = isTransform(key) ? transform.get(key) : rules.get(key)
|
|
222
244
|
// key不存在,第一轮取shareValMap[key]value,非第一轮取上一轮的
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
245
|
+
const toVal = ruleV !== undefined
|
|
246
|
+
? ruleV
|
|
247
|
+
: index > 0
|
|
248
|
+
? lastValueMap[key]
|
|
249
|
+
: shareValMap[key].value
|
|
250
|
+
const animation = getAnimation({ key, value: toVal! }, { delay, duration, easing }, needSetCallback ? setTransformOrigin : undefined)
|
|
227
251
|
needSetCallback = false
|
|
228
252
|
if (!sequence[key]) {
|
|
229
253
|
sequence[key] = [animation]
|
|
@@ -231,7 +255,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
|
|
|
231
255
|
sequence[key].push(animation)
|
|
232
256
|
}
|
|
233
257
|
// 更新一下 lastValueMap
|
|
234
|
-
lastValueMap[key] = toVal
|
|
258
|
+
lastValueMap[key] = toVal!
|
|
235
259
|
})
|
|
236
260
|
// 赋值驱动动画
|
|
237
261
|
animatedKeys.forEach((key) => {
|
|
@@ -327,6 +351,6 @@ export default function useAnimationHooks<T, P> (props: _ViewProps) {
|
|
|
327
351
|
styles[key] = shareValMap[key].value
|
|
328
352
|
}
|
|
329
353
|
return styles
|
|
330
|
-
},
|
|
354
|
+
}, {} as ExtendedViewStyle)
|
|
331
355
|
})
|
|
332
356
|
}
|
|
@@ -18,8 +18,10 @@ export const HIDDEN_STYLE = {
|
|
|
18
18
|
opacity: 0
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const varDecRegExp =
|
|
21
|
+
const varDecRegExp = /^--/
|
|
22
22
|
const varUseRegExp = /var\(/
|
|
23
|
+
const unoVarDecRegExp = /^--un-/
|
|
24
|
+
const unoVarUseRegExp = /var\(--un-/
|
|
23
25
|
const calcUseRegExp = /calc\(/
|
|
24
26
|
const envUseRegExp = /env\(/
|
|
25
27
|
|
|
@@ -37,7 +39,7 @@ function getSafeAreaInset (name: string) {
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export function omit<T, K extends string> (obj: T, fields: K[]): Omit<T, K> {
|
|
40
|
-
const shallowCopy: any =
|
|
42
|
+
const shallowCopy: any = extendObject({}, obj)
|
|
41
43
|
for (let i = 0; i < fields.length; i += 1) {
|
|
42
44
|
const key = fields[i]
|
|
43
45
|
delete shallowCopy[key]
|
|
@@ -77,7 +79,7 @@ export const parseInlineStyle = (inlineStyle = ''): Record<string, string> => {
|
|
|
77
79
|
const [k, v, ...rest] = style.split(':')
|
|
78
80
|
if (rest.length || !v || !k) return styleObj
|
|
79
81
|
const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase())
|
|
80
|
-
return
|
|
82
|
+
return extendObject(styleObj, { [key]: global.__formatValue(v.trim()) })
|
|
81
83
|
}, {})
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -286,11 +288,15 @@ interface TransformStyleConfig {
|
|
|
286
288
|
|
|
287
289
|
export function useTransformStyle (styleObj: Record<string, any> = {}, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }: TransformStyleConfig) {
|
|
288
290
|
const varStyle: Record<string, any> = {}
|
|
291
|
+
const unoVarStyle: Record<string, any> = {}
|
|
289
292
|
const normalStyle: Record<string, any> = {}
|
|
293
|
+
const normalStyleRef = useRef<Record<string, any>>({})
|
|
294
|
+
const normalStyleChangedRef = useRef(false)
|
|
290
295
|
let hasVarDec = false
|
|
291
296
|
let hasVarUse = false
|
|
292
297
|
let hasSelfPercent = false
|
|
293
298
|
const varKeyPaths: Array<Array<string>> = []
|
|
299
|
+
const unoVarKeyPaths: Array<Array<string>> = []
|
|
294
300
|
const percentKeyPaths: Array<Array<string>> = []
|
|
295
301
|
const calcKeyPaths: Array<Array<string>> = []
|
|
296
302
|
const envKeyPaths: Array<Array<string>> = []
|
|
@@ -299,7 +305,9 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
|
|
|
299
305
|
|
|
300
306
|
function varVisitor ({ key, value, keyPath }: VisitorArg) {
|
|
301
307
|
if (keyPath.length === 1) {
|
|
302
|
-
if (
|
|
308
|
+
if (unoVarDecRegExp.test(key)) {
|
|
309
|
+
unoVarStyle[key] = value
|
|
310
|
+
} else if (varDecRegExp.test(key)) {
|
|
303
311
|
hasVarDec = true
|
|
304
312
|
varStyle[key] = value
|
|
305
313
|
} else {
|
|
@@ -308,25 +316,32 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
|
|
|
308
316
|
}
|
|
309
317
|
}
|
|
310
318
|
// 对于var定义中使用的var无需替换值,可以通过resolveVar递归解析出值
|
|
311
|
-
if (!varDecRegExp.test(key)
|
|
312
|
-
|
|
313
|
-
|
|
319
|
+
if (!varDecRegExp.test(key)) {
|
|
320
|
+
// 一般情况下一个样式属性中不会混用unocss var和普通css var,可分开进行互斥处理
|
|
321
|
+
if (unoVarUseRegExp.test(value)) {
|
|
322
|
+
unoVarKeyPaths.push(keyPath.slice())
|
|
323
|
+
} else if (varUseRegExp.test(value)) {
|
|
324
|
+
hasVarUse = true
|
|
325
|
+
varKeyPaths.push(keyPath.slice())
|
|
326
|
+
}
|
|
314
327
|
}
|
|
315
328
|
}
|
|
316
329
|
|
|
317
|
-
// traverse var
|
|
330
|
+
// traverse var & generate normalStyle
|
|
318
331
|
traverseStyle(styleObj, [varVisitor])
|
|
332
|
+
|
|
319
333
|
hasVarDec = hasVarDec || !!externalVarContext
|
|
320
334
|
enableVar = enableVar || hasVarDec || hasVarUse
|
|
321
335
|
const enableVarRef = useRef(enableVar)
|
|
322
336
|
if (enableVarRef.current !== enableVar) {
|
|
323
337
|
error('css variable use/declare should be stable in the component lifecycle, or you can set [enable-var] with true.')
|
|
324
338
|
}
|
|
325
|
-
// apply var
|
|
339
|
+
// apply css var
|
|
326
340
|
const varContextRef = useRef({})
|
|
327
341
|
if (enableVarRef.current) {
|
|
342
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
328
343
|
const varContext = useContext(VarContext)
|
|
329
|
-
const newVarContext =
|
|
344
|
+
const newVarContext = extendObject({}, varContext, externalVarContext, varStyle)
|
|
330
345
|
// 缓存比较newVarContext是否发生变化
|
|
331
346
|
if (diffAndCloneA(varContextRef.current, newVarContext).diff) {
|
|
332
347
|
varContextRef.current = newVarContext
|
|
@@ -334,70 +349,86 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
|
|
|
334
349
|
transformVar(normalStyle, varKeyPaths, varContextRef.current)
|
|
335
350
|
}
|
|
336
351
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
352
|
+
// apply unocss var
|
|
353
|
+
if (unoVarKeyPaths.length) {
|
|
354
|
+
transformVar(normalStyle, unoVarKeyPaths, unoVarStyle)
|
|
341
355
|
}
|
|
342
356
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
357
|
+
const { clone, diff } = diffAndCloneA(normalStyle, normalStyleRef.current)
|
|
358
|
+
if (diff) {
|
|
359
|
+
normalStyleRef.current = clone
|
|
360
|
+
normalStyleChangedRef.current = !normalStyleChangedRef.current
|
|
347
361
|
}
|
|
348
362
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
363
|
+
const memoResult = useMemo(() => {
|
|
364
|
+
// transform can be memoized
|
|
365
|
+
function envVisitor ({ value, keyPath }: VisitorArg) {
|
|
366
|
+
if (envUseRegExp.test(value)) {
|
|
367
|
+
envKeyPaths.push(keyPath.slice())
|
|
368
|
+
}
|
|
355
369
|
}
|
|
356
|
-
}
|
|
357
370
|
|
|
358
|
-
|
|
359
|
-
|
|
371
|
+
function calcVisitor ({ value, keyPath }: VisitorArg) {
|
|
372
|
+
if (calcUseRegExp.test(value)) {
|
|
373
|
+
calcKeyPaths.push(keyPath.slice())
|
|
374
|
+
}
|
|
375
|
+
}
|
|
360
376
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
377
|
+
function percentVisitor ({ key, value, keyPath }: VisitorArg) {
|
|
378
|
+
if (hasOwn(selfPercentRule, key) && PERCENT_REGEX.test(value)) {
|
|
379
|
+
hasSelfPercent = true
|
|
380
|
+
percentKeyPaths.push(keyPath.slice())
|
|
381
|
+
} else if ((key === 'fontSize' || key === 'lineHeight') && PERCENT_REGEX.test(value)) {
|
|
382
|
+
percentKeyPaths.push(keyPath.slice())
|
|
383
|
+
}
|
|
384
|
+
}
|
|
369
385
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
386
|
+
// traverse env & calc & percent
|
|
387
|
+
traverseStyle(normalStyle, [envVisitor, percentVisitor, calcVisitor])
|
|
388
|
+
|
|
389
|
+
const percentConfig = {
|
|
390
|
+
width,
|
|
391
|
+
height,
|
|
392
|
+
fontSize: normalStyle.fontSize,
|
|
393
|
+
parentWidth,
|
|
394
|
+
parentHeight,
|
|
395
|
+
parentFontSize
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// apply env
|
|
399
|
+
transformEnv(normalStyle, envKeyPaths)
|
|
400
|
+
// apply percent
|
|
401
|
+
transformPercent(normalStyle, percentKeyPaths, percentConfig)
|
|
402
|
+
// apply calc
|
|
403
|
+
transformCalc(normalStyle, calcKeyPaths, (value: string, key: string) => {
|
|
404
|
+
if (PERCENT_REGEX.test(value)) {
|
|
405
|
+
const resolved = resolvePercent(value, key, percentConfig)
|
|
406
|
+
return typeof resolved === 'number' ? resolved : 0
|
|
383
407
|
} else {
|
|
384
|
-
|
|
385
|
-
|
|
408
|
+
const formatted = global.__formatValue(value)
|
|
409
|
+
if (typeof formatted === 'number') {
|
|
410
|
+
return formatted
|
|
411
|
+
} else {
|
|
412
|
+
warn('calc() only support number, px, rpx, % temporarily.')
|
|
413
|
+
return 0
|
|
414
|
+
}
|
|
386
415
|
}
|
|
416
|
+
})
|
|
417
|
+
// transform number enum stringify
|
|
418
|
+
transformStringify(normalStyle)
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
normalStyle,
|
|
422
|
+
hasSelfPercent
|
|
387
423
|
}
|
|
388
|
-
})
|
|
389
|
-
// transform number enum stringify
|
|
390
|
-
transformStringify(normalStyle)
|
|
424
|
+
}, [normalStyleChangedRef.current, width, height, parentWidth, parentHeight, parentFontSize])
|
|
391
425
|
|
|
392
|
-
return {
|
|
393
|
-
normalStyle,
|
|
394
|
-
hasSelfPercent,
|
|
426
|
+
return extendObject({
|
|
395
427
|
hasVarDec,
|
|
396
|
-
enableVarRef,
|
|
397
428
|
varContextRef,
|
|
398
429
|
setWidth,
|
|
399
430
|
setHeight
|
|
400
|
-
}
|
|
431
|
+
}, memoResult)
|
|
401
432
|
}
|
|
402
433
|
|
|
403
434
|
export interface VisitorArg {
|
|
@@ -477,7 +508,7 @@ interface LayoutConfig {
|
|
|
477
508
|
export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout, nodeRef }: LayoutConfig) => {
|
|
478
509
|
const layoutRef = useRef({})
|
|
479
510
|
const hasLayoutRef = useRef(false)
|
|
480
|
-
const layoutStyle
|
|
511
|
+
const layoutStyle = useMemo(() => { return !hasLayoutRef.current && hasSelfPercent ? HIDDEN_STYLE : {} }, [hasLayoutRef.current])
|
|
481
512
|
const layoutProps: Record<string, any> = {}
|
|
482
513
|
const enableOffset = props['enable-offset']
|
|
483
514
|
if (hasSelfPercent || onLayout || enableOffset) {
|
|
@@ -565,7 +596,7 @@ export const useStableCallback = <T extends AnyFunc | null | undefined> (
|
|
|
565
596
|
}
|
|
566
597
|
|
|
567
598
|
export const usePrevious = <T, > (value: T): T | undefined => {
|
|
568
|
-
const ref = useRef<T | undefined>(
|
|
599
|
+
const ref = useRef<T | undefined>()
|
|
569
600
|
const prev = ref.current
|
|
570
601
|
ref.current = value
|
|
571
602
|
return prev
|