@mpxjs/webpack-plugin 2.9.59 → 2.9.64

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.
Files changed (115) hide show
  1. package/lib/index.js +1 -3
  2. package/lib/platform/style/wx/index.js +344 -270
  3. package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
  4. package/lib/platform/template/wx/component-config/checkbox.js +8 -0
  5. package/lib/platform/template/wx/component-config/cover-image.js +15 -0
  6. package/lib/platform/template/wx/component-config/cover-view.js +9 -0
  7. package/lib/platform/template/wx/component-config/form.js +13 -1
  8. package/lib/platform/template/wx/component-config/icon.js +8 -0
  9. package/lib/platform/template/wx/component-config/index.js +5 -1
  10. package/lib/platform/template/wx/component-config/label.js +15 -0
  11. package/lib/platform/template/wx/component-config/movable-area.js +18 -1
  12. package/lib/platform/template/wx/component-config/movable-view.js +18 -1
  13. package/lib/platform/template/wx/component-config/navigator.js +8 -0
  14. package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
  15. package/lib/platform/template/wx/component-config/picker-view.js +18 -2
  16. package/lib/platform/template/wx/component-config/picker.js +14 -1
  17. package/lib/platform/template/wx/component-config/radio-group.js +8 -0
  18. package/lib/platform/template/wx/component-config/radio.js +8 -0
  19. package/lib/platform/template/wx/component-config/root-portal.js +15 -0
  20. package/lib/platform/template/wx/component-config/switch.js +8 -0
  21. package/lib/platform/template/wx/component-config/unsupported.js +1 -3
  22. package/lib/react/processScript.js +2 -0
  23. package/lib/react/processStyles.js +1 -0
  24. package/lib/react/processTemplate.js +2 -3
  25. package/lib/react/style-helper.js +12 -7
  26. package/lib/runtime/components/react/context.ts +40 -0
  27. package/lib/runtime/components/react/dist/context.js +8 -0
  28. package/lib/runtime/components/react/dist/getInnerListeners.js +34 -12
  29. package/lib/runtime/components/react/dist/mpx-button.jsx +88 -88
  30. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +82 -0
  31. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +139 -0
  32. package/lib/runtime/components/react/dist/mpx-form.jsx +61 -0
  33. package/lib/runtime/components/react/dist/mpx-icon.jsx +48 -0
  34. package/lib/runtime/components/react/dist/mpx-image/index.jsx +39 -43
  35. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -2
  36. package/lib/runtime/components/react/dist/mpx-input.jsx +63 -37
  37. package/lib/runtime/components/react/dist/mpx-label.jsx +55 -0
  38. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +41 -0
  39. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
  40. package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
  41. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
  42. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
  43. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +142 -0
  44. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +94 -0
  45. package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
  46. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
  47. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
  48. package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
  49. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +107 -0
  50. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +162 -0
  51. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +80 -0
  52. package/lib/runtime/components/react/dist/mpx-radio.jsx +154 -0
  53. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +15 -0
  54. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +93 -70
  55. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +281 -157
  56. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +21 -11
  57. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +19 -11
  58. package/lib/runtime/components/react/dist/mpx-switch.jsx +79 -0
  59. package/lib/runtime/components/react/dist/mpx-text.jsx +21 -49
  60. package/lib/runtime/components/react/dist/mpx-textarea.jsx +2 -2
  61. package/lib/runtime/components/react/dist/mpx-view.jsx +451 -146
  62. package/lib/runtime/components/react/dist/mpx-web-view.jsx +17 -20
  63. package/lib/runtime/components/react/dist/parser.js +218 -0
  64. package/lib/runtime/components/react/dist/types/common.js +1 -0
  65. package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
  66. package/lib/runtime/components/react/dist/utils.jsx +433 -0
  67. package/lib/runtime/components/react/getInnerListeners.ts +43 -21
  68. package/lib/runtime/components/react/mpx-button.tsx +129 -119
  69. package/lib/runtime/components/react/mpx-checkbox-group.tsx +152 -0
  70. package/lib/runtime/components/react/mpx-checkbox.tsx +234 -0
  71. package/lib/runtime/components/react/mpx-form.tsx +117 -0
  72. package/lib/runtime/components/react/mpx-icon.tsx +106 -0
  73. package/lib/runtime/components/react/mpx-image/index.tsx +62 -68
  74. package/lib/runtime/components/react/mpx-image/svg.tsx +7 -5
  75. package/lib/runtime/components/react/mpx-input.tsx +90 -42
  76. package/lib/runtime/components/react/mpx-label.tsx +110 -0
  77. package/lib/runtime/components/react/mpx-movable-area.tsx +81 -0
  78. package/lib/runtime/components/react/mpx-movable-view.tsx +424 -0
  79. package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
  80. package/lib/runtime/components/react/mpx-picker/date.tsx +82 -0
  81. package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
  82. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +156 -0
  83. package/lib/runtime/components/react/mpx-picker/region.tsx +107 -0
  84. package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
  85. package/lib/runtime/components/react/mpx-picker/selector.tsx +91 -0
  86. package/lib/runtime/components/react/mpx-picker/time.tsx +270 -0
  87. package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
  88. package/lib/runtime/components/react/mpx-picker-view-column.tsx +156 -0
  89. package/lib/runtime/components/react/mpx-picker-view.tsx +220 -0
  90. package/lib/runtime/components/react/mpx-radio-group.tsx +150 -0
  91. package/lib/runtime/components/react/mpx-radio.tsx +230 -0
  92. package/lib/runtime/components/react/mpx-root-portal.tsx +27 -0
  93. package/lib/runtime/components/react/mpx-scroll-view.tsx +184 -130
  94. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +308 -183
  95. package/lib/runtime/components/react/mpx-swiper/index.tsx +27 -19
  96. package/lib/runtime/components/react/mpx-swiper/type.ts +23 -5
  97. package/lib/runtime/components/react/mpx-swiper-item.tsx +49 -14
  98. package/lib/runtime/components/react/mpx-switch.tsx +148 -0
  99. package/lib/runtime/components/react/mpx-text.tsx +53 -77
  100. package/lib/runtime/components/react/mpx-textarea.tsx +3 -3
  101. package/lib/runtime/components/react/mpx-view.tsx +576 -195
  102. package/lib/runtime/components/react/mpx-web-view.tsx +34 -39
  103. package/lib/runtime/components/react/parser.ts +245 -0
  104. package/lib/runtime/components/react/types/common.ts +12 -0
  105. package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
  106. package/lib/runtime/components/react/types/global.d.ts +17 -1
  107. package/lib/runtime/components/react/useNodesRef.ts +4 -10
  108. package/lib/runtime/components/react/utils.tsx +505 -0
  109. package/lib/runtime/optionProcessor.js +19 -17
  110. package/lib/template-compiler/compiler.js +84 -61
  111. package/lib/template-compiler/gen-node-react.js +7 -9
  112. package/lib/web/processStyles.js +2 -5
  113. package/package.json +8 -3
  114. package/lib/runtime/components/react/dist/utils.js +0 -80
  115. package/lib/runtime/components/react/utils.ts +0 -92
@@ -0,0 +1,505 @@
1
+ import { useEffect, useRef, ReactNode, ReactElement, FunctionComponent, isValidElement, useContext, useState, Dispatch, SetStateAction, Children, cloneElement } from 'react'
2
+ import { Dimensions, StyleSheet, LayoutChangeEvent, TextStyle } from 'react-native'
3
+ import { isObject, hasOwn, diffAndCloneA, error, warn } from '@mpxjs/utils'
4
+ import { VarContext } from './context'
5
+ import { ExpressionParser, parseFunc, ReplaceSource } from './parser'
6
+
7
+ export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/
8
+ export const PERCENT_REGEX = /^\s*-?\d+(\.\d+)?%\s*$/
9
+ export const URL_REGEX = /^\s*url\(["']?(.*?)["']?\)\s*$/
10
+ export const BACKGROUND_REGEX = /^background(Image|Size|Repeat|Position)$/
11
+ export const TEXT_PROPS_REGEX = /ellipsizeMode|numberOfLines/
12
+ export const DEFAULT_FONT_SIZE = 16
13
+ export const DEFAULT_UNLAY_STYLE = {
14
+ opacity: 0
15
+ }
16
+
17
+ export function rpx (value: number) {
18
+ const { width } = Dimensions.get('screen')
19
+ // rn 单位 dp = 1(css)px = 1 物理像素 * pixelRatio(像素比)
20
+ // px = rpx * (750 / 屏幕宽度)
21
+ return value * width / 750
22
+ }
23
+
24
+ const rpxRegExp = /^\s*(-?\d+(\.\d+)?)rpx\s*$/
25
+ const pxRegExp = /^\s*(-?\d+(\.\d+)?)(px)?\s*$/
26
+ const hairlineRegExp = /^\s*hairlineWidth\s*$/
27
+ const varDecRegExp = /^--.*/
28
+ const varUseRegExp = /var\(/
29
+ const calcUseRegExp = /calc\(/
30
+
31
+ export function omit<T, K extends string> (obj: T, fields: K[]): Omit<T, K> {
32
+ const shallowCopy: any = Object.assign({}, obj)
33
+ for (let i = 0; i < fields.length; i += 1) {
34
+ const key = fields[i]
35
+ delete shallowCopy[key]
36
+ }
37
+ return shallowCopy
38
+ }
39
+
40
+ /**
41
+ * 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行
42
+ */
43
+ export const useUpdateEffect = (effect: any, deps: any) => {
44
+ const isMounted = useRef(false)
45
+
46
+ // for react-refresh
47
+ useEffect(() => {
48
+ return () => {
49
+ isMounted.current = false
50
+ }
51
+ }, [])
52
+
53
+ useEffect(() => {
54
+ if (!isMounted.current) {
55
+ isMounted.current = true
56
+ } else {
57
+ return effect()
58
+ }
59
+ }, deps)
60
+ }
61
+
62
+ /**
63
+ * 解析行内样式
64
+ * @param inlineStyle
65
+ * @returns
66
+ */
67
+ export const parseInlineStyle = (inlineStyle = ''): Record<string, string> => {
68
+ return inlineStyle.split(';').reduce((styleObj, style) => {
69
+ const [k, v, ...rest] = style.split(':')
70
+ if (rest.length || !v || !k) return styleObj
71
+ const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase())
72
+ return Object.assign(styleObj, { [key]: v.trim() })
73
+ }, {})
74
+ }
75
+
76
+ export const parseUrl = (cssUrl = '') => {
77
+ if (!cssUrl) return
78
+ const match = cssUrl.match(URL_REGEX)
79
+ return match?.[1]
80
+ }
81
+
82
+ export const getRestProps = (transferProps: any = {}, originProps: any = {}, deletePropsKey: any = []) => {
83
+ return {
84
+ ...transferProps,
85
+ ...omit(originProps, deletePropsKey)
86
+ }
87
+ }
88
+
89
+ export function isText (ele: ReactNode): ele is ReactElement {
90
+ if (isValidElement(ele)) {
91
+ const displayName = (ele.type as FunctionComponent)?.displayName
92
+ return displayName === 'mpx-text' || displayName === 'Text'
93
+ }
94
+ return false
95
+ }
96
+
97
+ export function isEmbedded (ele: ReactNode): ele is ReactElement {
98
+ if (isValidElement(ele)) {
99
+ const displayName = (ele.type as FunctionComponent)?.displayName || ''
100
+ return ['mpx-checkbox', 'mpx-radio', 'mpx-switch'].includes(displayName)
101
+ }
102
+ return false
103
+ }
104
+
105
+ export function every (children: ReactNode, callback: (children: ReactNode) => boolean) {
106
+ const childrenArray = Array.isArray(children) ? children : [children]
107
+ return childrenArray.every((child) => callback(child))
108
+ }
109
+
110
+ type GroupData<T> = Record<string, Partial<T>>
111
+ export function groupBy<T extends Record<string, any>> (
112
+ obj: T,
113
+ callback: (key: string, val: T[keyof T]) => string,
114
+ group: GroupData<T> = {}
115
+ ): GroupData<T> {
116
+ Object.entries(obj).forEach(([key, val]) => {
117
+ const groupKey = callback(key, val)
118
+ group[groupKey] = group[groupKey] || {}
119
+ group[groupKey][key as keyof T] = val
120
+ })
121
+ return group
122
+ }
123
+
124
+ export function splitStyle<T extends Record<string, any>> (styleObj: T): {
125
+ textStyle?: Partial<T>;
126
+ backgroundStyle?: Partial<T>;
127
+ innerStyle?: Partial<T>;
128
+ } {
129
+ return groupBy(styleObj, (key) => {
130
+ if (TEXT_STYLE_REGEX.test(key)) {
131
+ return 'textStyle'
132
+ } else if (BACKGROUND_REGEX.test(key)) {
133
+ return 'backgroundStyle'
134
+ } else {
135
+ return 'innerStyle'
136
+ }
137
+ }) as {
138
+ textStyle: Partial<T>;
139
+ backgroundStyle: Partial<T>;
140
+ innerStyle: Partial<T>;
141
+ }
142
+ }
143
+
144
+ const selfPercentRule: Record<string, 'height' | 'width'> = {
145
+ translateX: 'width',
146
+ translateY: 'height',
147
+ borderTopLeftRadius: 'width',
148
+ borderBottomLeftRadius: 'width',
149
+ borderBottomRightRadius: 'width',
150
+ borderTopRightRadius: 'width',
151
+ borderRadius: 'width'
152
+ }
153
+
154
+ const parentHeightPercentRule: Record<string, boolean> = {
155
+ height: true,
156
+ top: true,
157
+ bottom: true
158
+ }
159
+
160
+ // todo calc时处理角度和时间等单位
161
+ function formatValue (value: string) {
162
+ let matched
163
+ if ((matched = pxRegExp.exec(value))) {
164
+ return +matched[1]
165
+ } else if ((matched = rpxRegExp.exec(value))) {
166
+ return rpx(+matched[1])
167
+ } else if (hairlineRegExp.test(value)) {
168
+ return StyleSheet.hairlineWidth
169
+ }
170
+ return value
171
+ }
172
+
173
+ interface PercentConfig {
174
+ fontSize?: number | string
175
+ width?: number
176
+ height?: number
177
+ parentFontSize?: number
178
+ parentWidth?: number
179
+ parentHeight?: number
180
+ }
181
+
182
+ function resolvePercent (value: string | number | undefined, key: string, percentConfig: PercentConfig): string | number | undefined {
183
+ if (!(typeof value === 'string' && PERCENT_REGEX.test(value))) return value
184
+ let base
185
+ let reason
186
+ if (key === 'fontSize') {
187
+ base = percentConfig.parentFontSize
188
+ reason = 'parent-font-size'
189
+ } else if (key === 'lineHeight') {
190
+ base = resolvePercent(percentConfig.fontSize, 'fontSize', percentConfig)
191
+ reason = 'font-size'
192
+ } else if (selfPercentRule[key]) {
193
+ base = percentConfig[selfPercentRule[key]]
194
+ reason = selfPercentRule[key]
195
+ } else if (parentHeightPercentRule[key]) {
196
+ base = percentConfig.parentHeight
197
+ reason = 'parent-height'
198
+ } else {
199
+ base = percentConfig.parentWidth
200
+ reason = 'parent-width'
201
+ }
202
+ if (typeof base !== 'number') {
203
+ error(`[${key}] can not contain % unit unless you set [${reason}] with a number for the percent calculation.`)
204
+ return value
205
+ } else {
206
+ return parseFloat(value) / 100 * base
207
+ }
208
+ }
209
+
210
+ function transformPercent (styleObj: Record<string, any>, percentKeyPaths: Array<Array<string>>, percentConfig: PercentConfig) {
211
+ percentKeyPaths.forEach((percentKeyPath) => {
212
+ setStyle(styleObj, percentKeyPath, ({ target, key, value }) => {
213
+ target[key] = resolvePercent(value, key, percentConfig)
214
+ })
215
+ })
216
+ }
217
+
218
+ function resolveVar (input: string, varContext: Record<string, any>) {
219
+ const parsed = parseFunc(input, 'var')
220
+ const replaced = new ReplaceSource(input)
221
+
222
+ parsed.forEach(({ start, end, args }) => {
223
+ const varName = args[0]
224
+ const fallback = args[1] || ''
225
+ let varValue = hasOwn(varContext, varName) ? varContext[varName] : fallback
226
+ if (varUseRegExp.test(varValue)) {
227
+ varValue = '' + resolveVar(varValue, varContext)
228
+ } else {
229
+ varValue = '' + formatValue(varValue)
230
+ }
231
+ replaced.replace(start, end - 1, varValue)
232
+ })
233
+ return formatValue(replaced.source())
234
+ }
235
+
236
+ function transformVar (styleObj: Record<string, any>, varKeyPaths: Array<Array<string>>, varContext: Record<string, any>) {
237
+ varKeyPaths.forEach((varKeyPath) => {
238
+ setStyle(styleObj, varKeyPath, ({ target, key, value }) => {
239
+ target[key] = resolveVar(value, varContext)
240
+ })
241
+ })
242
+ }
243
+
244
+ function transformCalc (styleObj: Record<string, any>, calcKeyPaths: Array<Array<string>>, formatter: (value: string, key: string) => number) {
245
+ calcKeyPaths.forEach((calcKeyPath) => {
246
+ setStyle(styleObj, calcKeyPath, ({ target, key, value }) => {
247
+ const parsed = parseFunc(value, 'calc')
248
+ const replaced = new ReplaceSource(value)
249
+ parsed.forEach(({ start, end, args }) => {
250
+ const exp = args[0]
251
+ try {
252
+ const result = new ExpressionParser(exp, (value) => {
253
+ return formatter(value, key)
254
+ }).parse()
255
+ replaced.replace(start, end - 1, '' + result.value)
256
+ } catch (e) {
257
+ error(`calc(${exp}) parse error.`, undefined, e)
258
+ }
259
+ })
260
+ target[key] = formatValue(replaced.source())
261
+ })
262
+ })
263
+ }
264
+
265
+ interface TransformStyleConfig {
266
+ enableVar?: boolean
267
+ externalVarContext?: Record<string, any>
268
+ parentFontSize?: number
269
+ parentWidth?: number
270
+ parentHeight?: number
271
+ }
272
+
273
+ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }: TransformStyleConfig) {
274
+ const varStyle: Record<string, any> = {}
275
+ const normalStyle: Record<string, any> = {}
276
+ let hasVarDec = false
277
+ let hasVarUse = false
278
+ let hasSelfPercent = false
279
+ const varKeyPaths: Array<Array<string>> = []
280
+ const percentKeyPaths: Array<Array<string>> = []
281
+ const calcKeyPaths: Array<Array<string>> = []
282
+ const [width, setWidth] = useState(0)
283
+ const [height, setHeight] = useState(0)
284
+
285
+ function varVisitor ({ key, value, keyPath }: VisitorArg) {
286
+ if (keyPath.length === 1) {
287
+ if (varDecRegExp.test(key)) {
288
+ hasVarDec = true
289
+ varStyle[key] = value
290
+ } else {
291
+ // clone对象避免set值时改写到props
292
+ normalStyle[key] = isObject(value) ? diffAndCloneA(value).clone : value
293
+ }
294
+ }
295
+ // 对于var定义中使用的var无需替换值,可以通过resolveVar递归解析出值
296
+ if (!varDecRegExp.test(key) && varUseRegExp.test(value)) {
297
+ hasVarUse = true
298
+ varKeyPaths.push(keyPath.slice())
299
+ }
300
+ }
301
+ // traverse var
302
+ traverseStyle(styleObj, [varVisitor])
303
+ hasVarDec = hasVarDec || !!externalVarContext
304
+ enableVar = enableVar || hasVarDec || hasVarUse
305
+ const enableVarRef = useRef(enableVar)
306
+ if (enableVarRef.current !== enableVar) {
307
+ error('css variable use/declare should be stable in the component lifecycle, or you can set [enable-var] with true.')
308
+ }
309
+ // apply var
310
+ const varContextRef = useRef({})
311
+ if (enableVarRef.current) {
312
+ const varContext = useContext(VarContext)
313
+ const newVarContext = Object.assign({}, varContext, externalVarContext, varStyle)
314
+ // 缓存比较newVarContext是否发生变化
315
+ if (diffAndCloneA(varContextRef.current, newVarContext).diff) {
316
+ varContextRef.current = newVarContext
317
+ }
318
+ transformVar(normalStyle, varKeyPaths, varContextRef.current)
319
+ }
320
+
321
+ function calcVisitor ({ value, keyPath }: VisitorArg) {
322
+ if (calcUseRegExp.test(value)) {
323
+ calcKeyPaths.push(keyPath.slice())
324
+ }
325
+ }
326
+
327
+ function percentVisitor ({ key, value, keyPath }: VisitorArg) {
328
+ if (hasOwn(selfPercentRule, key) && PERCENT_REGEX.test(value)) {
329
+ hasSelfPercent = true
330
+ percentKeyPaths.push(keyPath.slice())
331
+ } else if (key === 'fontSize' || key === 'lineHeight') {
332
+ percentKeyPaths.push(keyPath.slice())
333
+ }
334
+ }
335
+
336
+ // traverse calc & percent
337
+ traverseStyle(normalStyle, [percentVisitor, calcVisitor])
338
+
339
+ const percentConfig = {
340
+ width,
341
+ height,
342
+ fontSize: normalStyle.fontSize,
343
+ parentWidth,
344
+ parentHeight,
345
+ parentFontSize
346
+ }
347
+
348
+ // apply percent
349
+ transformPercent(normalStyle, percentKeyPaths, percentConfig)
350
+ // apply calc
351
+ transformCalc(normalStyle, calcKeyPaths, (value: string, key: string) => {
352
+ if (PERCENT_REGEX.test(value)) {
353
+ const resolved = resolvePercent(value, key, percentConfig)
354
+ return typeof resolved === 'number' ? resolved : 0
355
+ } else {
356
+ const formatted = formatValue(value)
357
+ if (typeof formatted === 'number') {
358
+ return formatted
359
+ } else {
360
+ warn('calc() only support number, px, rpx, % temporarily.')
361
+ return 0
362
+ }
363
+ }
364
+ })
365
+
366
+ return {
367
+ normalStyle,
368
+ hasSelfPercent,
369
+ hasVarDec,
370
+ enableVarRef,
371
+ varContextRef,
372
+ setWidth,
373
+ setHeight
374
+ }
375
+ }
376
+
377
+ export interface VisitorArg {
378
+ target: Record<string, any>
379
+ key: string
380
+ value: any
381
+ keyPath: Array<string>
382
+ }
383
+
384
+ export function traverseStyle (styleObj: Record<string, any>, visitors: Array<(arg: VisitorArg) => void>) {
385
+ const keyPath: Array<string> = []
386
+ function traverse<T extends Record<string, any>> (target: T) {
387
+ if (Array.isArray(target)) {
388
+ target.forEach((value, index) => {
389
+ const key = String(index)
390
+ keyPath.push(key)
391
+ visitors.forEach(visitor => visitor({
392
+ target,
393
+ key,
394
+ value,
395
+ keyPath
396
+ }))
397
+ traverse(value)
398
+ keyPath.pop()
399
+ })
400
+ } else if (isObject(target)) {
401
+ Object.entries(target).forEach(([key, value]) => {
402
+ keyPath.push(key)
403
+ visitors.forEach(visitor => visitor({ target, key, value, keyPath }))
404
+ traverse(value)
405
+ keyPath.pop()
406
+ })
407
+ }
408
+ }
409
+ traverse(styleObj)
410
+ }
411
+
412
+ export function setStyle (styleObj: Record<string, any>, keyPath: Array<string>, setter: (arg: VisitorArg) => void, needClone = false) {
413
+ let target = styleObj
414
+ const firstKey = keyPath[0]
415
+ const lastKey = keyPath[keyPath.length - 1]
416
+ if (needClone) target[firstKey] = diffAndCloneA(target[firstKey]).clone
417
+ for (let i = 0; i < keyPath.length - 1; i++) {
418
+ target = target[keyPath[i]]
419
+ if (!target) return
420
+ }
421
+ setter({
422
+ target,
423
+ key: lastKey,
424
+ value: target[lastKey],
425
+ keyPath
426
+ })
427
+ }
428
+
429
+ export function splitProps<T extends Record<string, any>> (props: T): {
430
+ textProps?: Partial<T>;
431
+ innerProps?: Partial<T>;
432
+ } {
433
+ return groupBy(props, (key) => {
434
+ if (TEXT_PROPS_REGEX.test(key)) {
435
+ return 'textProps'
436
+ } else {
437
+ return 'innerProps'
438
+ }
439
+ }) as {
440
+ textProps: Partial<T>;
441
+ innerProps: Partial<T>;
442
+ }
443
+ }
444
+
445
+ interface LayoutConfig {
446
+ props: Record<string, any>
447
+ hasSelfPercent: boolean
448
+ setWidth: Dispatch<SetStateAction<number>>
449
+ setHeight: Dispatch<SetStateAction<number>>
450
+ onLayout?: (event?: LayoutChangeEvent) => void
451
+ nodeRef: React.RefObject<any>
452
+ }
453
+ export const useLayout = ({ props, hasSelfPercent, setWidth, setHeight, onLayout, nodeRef }:LayoutConfig) => {
454
+ const layoutRef = useRef({})
455
+ const hasLayoutRef = useRef(false)
456
+ const layoutStyle: Record<string, any> = !hasLayoutRef.current && hasSelfPercent ? DEFAULT_UNLAY_STYLE : {}
457
+ const layoutProps: Record<string, any> = {}
458
+ const enableOffset = props['enable-offset']
459
+ if (hasSelfPercent || onLayout || enableOffset) {
460
+ layoutProps.onLayout = (e: LayoutChangeEvent) => {
461
+ hasLayoutRef.current = true
462
+ if (hasSelfPercent) {
463
+ const { width, height } = e?.nativeEvent?.layout || {}
464
+ setWidth(width || 0)
465
+ setHeight(height || 0)
466
+ }
467
+ if (enableOffset) {
468
+ nodeRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
469
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
470
+ })
471
+ }
472
+ onLayout && onLayout(e)
473
+ props.onLayout && props.onLayout(e)
474
+ }
475
+ }
476
+ return {
477
+ layoutRef,
478
+ layoutStyle,
479
+ layoutProps
480
+ }
481
+ }
482
+
483
+ export interface WrapChildrenConfig {
484
+ hasVarDec: boolean
485
+ varContext?: Record<string, any>
486
+ textStyle?: TextStyle
487
+ textProps?: Record<string, any>
488
+ }
489
+
490
+ export function wrapChildren (props: Record<string, any> = {}, { hasVarDec, varContext, textStyle, textProps }: WrapChildrenConfig) {
491
+ let { children } = props
492
+ if (textStyle || textProps) {
493
+ children = Children.map(children, (child) => {
494
+ if (isText(child)) {
495
+ const style = { ...textStyle, ...child.props.style }
496
+ return cloneElement(child, { ...textProps, style })
497
+ }
498
+ return child
499
+ })
500
+ }
501
+ if (hasVarDec && varContext) {
502
+ children = <VarContext.Provider value={varContext} key='varContextWrap'>{children}</VarContext.Provider>
503
+ }
504
+ return children
505
+ }
@@ -81,23 +81,25 @@ registered in parent context!`)
81
81
  transitionName: ''
82
82
  }
83
83
  }
84
- option.watch = {
85
- $route: {
86
- handler () {
87
- const actionType = global.__mpxRouter.currentActionType
84
+ if (!global.__mpx.config.webConfig.disablePageTransition) {
85
+ option.watch = {
86
+ $route: {
87
+ handler () {
88
+ const actionType = global.__mpxRouter.currentActionType
88
89
 
89
- switch (actionType) {
90
- case 'to':
91
- this.transitionName = 'mpx-slide-left'
92
- break
93
- case 'back':
94
- this.transitionName = 'mpx-slide-right'
95
- break
96
- default:
97
- this.transitionName = ''
98
- }
99
- },
100
- immediate: true
90
+ switch (actionType) {
91
+ case 'to':
92
+ this.transitionName = 'mpx-slide-left'
93
+ break
94
+ case 'back':
95
+ this.transitionName = 'mpx-slide-right'
96
+ break
97
+ default:
98
+ this.transitionName = ''
99
+ }
100
+ },
101
+ immediate: true
102
+ }
101
103
  }
102
104
  }
103
105
  }
@@ -161,7 +163,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
161
163
  redirect: '/' + firstPage
162
164
  })
163
165
  }
164
- const webRouteConfig = global.__mpx.config.webRouteConfig
166
+ const webRouteConfig = global.__mpx.config.webConfig.routeConfig || global.__mpx.config.webRouteConfig
165
167
  global.__mpxRouter = option.router = new VueRouter({
166
168
  ...webRouteConfig,
167
169
  routes: routes