@mpxjs/webpack-plugin 2.9.40 → 2.9.41-react.0

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 (63) hide show
  1. package/lib/config.js +63 -97
  2. package/lib/dependencies/{RecordVueContentDependency.js → RecordLoaderContentDependency.js} +5 -5
  3. package/lib/dependencies/ResolveDependency.js +2 -2
  4. package/lib/helpers.js +5 -1
  5. package/lib/index.js +26 -21
  6. package/lib/loader.js +43 -97
  7. package/lib/native-loader.js +0 -1
  8. package/lib/platform/index.js +3 -0
  9. package/lib/platform/style/wx/index.js +414 -0
  10. package/lib/platform/template/wx/component-config/button.js +36 -0
  11. package/lib/platform/template/wx/component-config/image.js +15 -0
  12. package/lib/platform/template/wx/component-config/input.js +41 -0
  13. package/lib/platform/template/wx/component-config/scroll-view.js +27 -1
  14. package/lib/platform/template/wx/component-config/swiper-item.js +13 -1
  15. package/lib/platform/template/wx/component-config/swiper.js +25 -1
  16. package/lib/platform/template/wx/component-config/text.js +15 -0
  17. package/lib/platform/template/wx/component-config/textarea.js +39 -0
  18. package/lib/platform/template/wx/component-config/unsupported.js +18 -0
  19. package/lib/platform/template/wx/component-config/view.js +14 -0
  20. package/lib/platform/template/wx/index.js +88 -4
  21. package/lib/react/index.js +104 -0
  22. package/lib/react/processJSON.js +361 -0
  23. package/lib/react/processMainScript.js +21 -0
  24. package/lib/react/processScript.js +70 -0
  25. package/lib/react/processStyles.js +69 -0
  26. package/lib/react/processTemplate.js +153 -0
  27. package/lib/react/script-helper.js +133 -0
  28. package/lib/react/style-helper.js +91 -0
  29. package/lib/resolver/PackageEntryPlugin.js +1 -0
  30. package/lib/runtime/components/react/event.config.ts +32 -0
  31. package/lib/runtime/components/react/getInnerListeners.ts +289 -0
  32. package/lib/runtime/components/react/getInnerListeners.type.ts +68 -0
  33. package/lib/runtime/components/react/mpx-button.tsx +402 -0
  34. package/lib/runtime/components/react/mpx-image/index.tsx +351 -0
  35. package/lib/runtime/components/react/mpx-image/svg.tsx +21 -0
  36. package/lib/runtime/components/react/mpx-input.tsx +389 -0
  37. package/lib/runtime/components/react/mpx-scroll-view.tsx +412 -0
  38. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +398 -0
  39. package/lib/runtime/components/react/mpx-swiper/index.tsx +68 -0
  40. package/lib/runtime/components/react/mpx-swiper/type.ts +69 -0
  41. package/lib/runtime/components/react/mpx-swiper-item.tsx +42 -0
  42. package/lib/runtime/components/react/mpx-text.tsx +106 -0
  43. package/lib/runtime/components/react/mpx-textarea.tsx +46 -0
  44. package/lib/runtime/components/react/mpx-view.tsx +397 -0
  45. package/lib/runtime/components/react/useNodesRef.ts +39 -0
  46. package/lib/runtime/components/react/utils.ts +92 -0
  47. package/lib/runtime/optionProcessorReact.d.ts +9 -0
  48. package/lib/runtime/optionProcessorReact.js +21 -0
  49. package/lib/runtime/stringify.wxs +3 -8
  50. package/lib/style-compiler/index.js +2 -1
  51. package/lib/template-compiler/compiler.js +287 -36
  52. package/lib/template-compiler/gen-node-react.js +95 -0
  53. package/lib/template-compiler/index.js +15 -24
  54. package/lib/utils/env.js +17 -0
  55. package/lib/utils/make-map.js +1 -1
  56. package/lib/utils/shallow-stringify.js +12 -12
  57. package/lib/web/index.js +123 -0
  58. package/lib/web/processJSON.js +3 -3
  59. package/lib/web/processMainScript.js +25 -23
  60. package/lib/web/processScript.js +12 -16
  61. package/lib/web/processTemplate.js +13 -12
  62. package/lib/web/script-helper.js +14 -22
  63. package/package.json +4 -3
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Compared with Input:
3
+ * Subtraction:
4
+ * type, password, confirm-hold
5
+ * Addition:
6
+ * - confirm-type: Not support `return`
7
+ * ✔ auto-height
8
+ * ✘ fixed
9
+ * ✘ show-confirm-bar
10
+ * ✔ bindlinechange: No `heightRpx` info.
11
+ */
12
+ import React, { forwardRef } from 'react'
13
+ import { Keyboard, TextInput } from 'react-native'
14
+ import Input, { InputProps, PrivateInputProps } from './mpx-input'
15
+ import { omit } from './utils'
16
+ import { HandlerRef } from './useNodesRef'
17
+
18
+ export type TextareProps = Omit<
19
+ InputProps & PrivateInputProps,
20
+ 'type' | 'password' | 'multiline' | 'confirm-hold'
21
+ >
22
+
23
+ const Textarea = forwardRef<HandlerRef<TextInput, TextareProps>, TextareProps>(
24
+ (props, ref): React.JSX.Element => {
25
+ const restProps = omit(props, [
26
+ 'ref',
27
+ 'type',
28
+ 'password',
29
+ 'multiline',
30
+ 'confirm-hold',
31
+ ])
32
+ return (
33
+ <Input
34
+ ref={ref}
35
+ multiline
36
+ confirm-type='next'
37
+ bindblur={() => Keyboard.dismiss()}
38
+ {...restProps}
39
+ />
40
+ )
41
+ }
42
+ )
43
+
44
+ Textarea.displayName = 'mpx-textarea'
45
+
46
+ export default Textarea
@@ -0,0 +1,397 @@
1
+ /**
2
+ * ✔ hover-class
3
+ * ✘ hover-stop-propagation
4
+ * ✔ hover-start-time
5
+ * ✔ hover-stay-time
6
+ */
7
+ import { View, Text, StyleProp, TextStyle, ViewStyle, NativeSyntheticEvent, ViewProps, ImageStyle, ImageResizeMode, StyleSheet, Image, LayoutChangeEvent } from 'react-native'
8
+ import { useRef, useState, useEffect, forwardRef, ForwardedRef, ReactNode, JSX } from 'react'
9
+ // @ts-ignore
10
+ import useInnerProps from './getInnerListeners'
11
+ // @ts-ignore
12
+ import useNodesRef, { HandlerRef } from './useNodesRef' // 引入辅助函数
13
+
14
+ import { parseUrl, TEXT_STYLE_REGEX, PERCENT_REGX, isText} from './utils'
15
+
16
+
17
+ type ExtendedViewStyle = ViewStyle & {
18
+ backgroundImage?: string
19
+ backgroundSize?: ImageResizeMode
20
+ }
21
+
22
+ export interface _ViewProps extends ViewProps {
23
+ style?: Array<ExtendedViewStyle>
24
+ children?: ReactNode | ReactNode []
25
+ hoverStyle: Array<ExtendedViewStyle>
26
+ ['hover-start-time']: number
27
+ ['hover-stay-time']: number
28
+ 'enable-offset'?: boolean
29
+ bindtouchstart?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void
30
+ bindtouchmove?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void
31
+ bindtouchend?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void
32
+ }
33
+
34
+ type Obj = Record<string, any>
35
+
36
+ type GroupData = Record<string, Record<string, any>>;
37
+
38
+ type Handler = (...args: any []) => void
39
+
40
+ type Size = {
41
+ width: number,
42
+ height: number
43
+ }
44
+
45
+ type DimensionValue = number | 'auto' | `${number}%`
46
+
47
+ type PreImageInfo = {
48
+ src?: string,
49
+ sizeList: DimensionValue []
50
+ }
51
+
52
+ type ImageProps = {
53
+ style: ImageStyle,
54
+ src?: string
55
+ }
56
+
57
+ const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/
58
+
59
+ function groupBy(style: Obj, callback: (key: string, val: string) => string, group:GroupData = {}):GroupData {
60
+ let groupKey = ''
61
+ for (let key in style) {
62
+ if (style.hasOwnProperty(key)) { // 确保处理对象自身的属性
63
+ let val: string = style[key] as string
64
+ groupKey = callback(key, val)
65
+ if (!group[groupKey]) {
66
+ group[groupKey] = {}
67
+ }
68
+ group[groupKey][key] = val
69
+ }
70
+ }
71
+ return group
72
+ }
73
+
74
+ const applyHandlers = (handlers: Handler[] , args: any [] ) => {
75
+ for (let handler of handlers) {
76
+ handler(...args)
77
+ }
78
+ }
79
+
80
+ const checkNeedLayout = (style: PreImageInfo) => {
81
+ const [width, height] = style.sizeList
82
+ return (PERCENT_REGX.test(`${height}`) && width === 'auto') || (PERCENT_REGX.test(`${width}`) && height === 'auto')
83
+ }
84
+
85
+ /**
86
+ * h - 用户设置的高度
87
+ * lh - 容器的高度
88
+ * ratio - 原始图片的宽高比
89
+ * **/
90
+ function calculateSize(h: number, lh: number, ratio: number) {
91
+ let height, width
92
+ if (PERCENT_REGX.test(`${h}`)) { // auto px/rpx
93
+ if (!lh) return null
94
+ height = (parseFloat(`${h}`) / 100) * lh
95
+ width = height * ratio
96
+ } else { // 2. auto px/rpx - 根据比例计算
97
+ height = h
98
+ width = height * ratio
99
+ }
100
+
101
+ return {
102
+ width,
103
+ height
104
+ }
105
+ }
106
+
107
+ // background-size 转换
108
+ function backgroundSize (imageProps: ImageProps, preImageInfo: PreImageInfo, imageSize: Size, layoutInfo: Size) {
109
+ let sizeList = preImageInfo.sizeList
110
+ if (!sizeList) return
111
+ // 枚举值
112
+ if (['cover', 'contain'].includes(`${sizeList[0]}`)) {
113
+ imageProps.style.resizeMode = sizeList[0] as ImageResizeMode
114
+ } else {
115
+ const [width, height] = sizeList
116
+ let newWidth: ImageStyle['width'] = 0, newHeight: ImageStyle['height'] = 0
117
+
118
+ const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {}
119
+
120
+ if (width === 'auto' && height === 'auto') { // 均为auto
121
+ if (!imageSize) return
122
+ newHeight = imageSizeHeight
123
+ newWidth = imageSizeWidth
124
+ } else if (width === 'auto') { // auto px/rpx/%
125
+ if (!imageSize) return
126
+ const dimensions = calculateSize(height as number, layoutInfo?.height, imageSizeWidth / imageSizeHeight)
127
+ if (!dimensions) return
128
+ newWidth = dimensions.width
129
+ newHeight = dimensions.height
130
+ }else if (height === 'auto') { // auto px/rpx/%
131
+ if (!imageSize) return
132
+ const dimensions = calculateSize(width as number, layoutInfo?.width, imageSizeHeight / imageSizeWidth)
133
+ if (!dimensions) return
134
+ newHeight = dimensions.width
135
+ newWidth = dimensions.height
136
+ } else { // 数值类型 ImageStyle
137
+ // 数值类型设置为 stretch
138
+ (imageProps.style as ImageStyle).resizeMode = 'stretch'
139
+ newWidth = PERCENT_REGX.test(`${width}`) ? width : +width! as DimensionValue
140
+ newHeight = PERCENT_REGX.test(`${width}`) ? height : +height! as DimensionValue
141
+ }
142
+ // 样式合并
143
+ imageProps.style = {
144
+ ...imageProps.style as ImageStyle,
145
+ width: newWidth,
146
+ height: newHeight
147
+ }
148
+ }
149
+ }
150
+
151
+ // background-image转换为source
152
+ function backgroundImage(imageProps: ImageProps, preImageInfo: PreImageInfo) {
153
+ imageProps.src = preImageInfo.src
154
+ }
155
+
156
+ const imageStyleToProps = (preImageInfo: PreImageInfo, imageSize: Size, layoutInfo: Size) => {
157
+ // 初始化
158
+ const imageProps: ImageProps = {
159
+ style: {
160
+ resizeMode: 'cover' as ImageResizeMode,
161
+ ...StyleSheet.absoluteFillObject
162
+ }
163
+ }
164
+
165
+ applyHandlers([ backgroundSize, backgroundImage ],[imageProps, preImageInfo, imageSize, layoutInfo])
166
+ if (!imageProps?.src) return null
167
+ return imageProps
168
+ }
169
+
170
+
171
+ function preParseImage(imageStyle?: ExtendedViewStyle) {
172
+
173
+ const { backgroundImage, backgroundSize = [ "auto" ] } = imageStyle || {}
174
+ const src = parseUrl(backgroundImage)
175
+
176
+ let sizeList = backgroundSize.slice() as DimensionValue []
177
+
178
+ sizeList.length === 1 && sizeList.push(sizeList[0])
179
+
180
+ return {
181
+ src,
182
+ sizeList
183
+ }
184
+ }
185
+
186
+ function wrapImage(imageStyle?: ExtendedViewStyle) {
187
+ const [show, setShow] = useState<boolean>(false)
188
+ const [, setImageSizeWidth] = useState<number | null>(null)
189
+ const [, setImageSizeHeight] = useState<number | null>(null)
190
+ const [, setLayoutInfoWidth] = useState<number | null>(null)
191
+ const [, setLayoutInfoHeight] = useState<number | null>(null)
192
+ const sizeInfo = useRef<Size | null>(null)
193
+ const layoutInfo = useRef<Size | null>(null)
194
+
195
+ // 预解析
196
+ const preImageInfo: PreImageInfo = preParseImage(imageStyle)
197
+
198
+
199
+ // 判断是否可挂载onLayout
200
+ const needLayout = checkNeedLayout(preImageInfo)
201
+ const { src, sizeList } = preImageInfo
202
+
203
+ useEffect(() => {
204
+ if(!src) {
205
+ setShow(false)
206
+ sizeInfo.current = null
207
+ layoutInfo.current = null
208
+ return
209
+ }
210
+
211
+ if (!sizeList.includes('auto')) {
212
+ setShow(true)
213
+ return
214
+ }
215
+ Image.getSize(src, (width, height) => {
216
+ sizeInfo.current = {
217
+ width,
218
+ height
219
+ }
220
+ //1. 当需要绑定onLayout 2. 获取到布局信息
221
+ if (!needLayout || layoutInfo.current) {
222
+ setImageSizeWidth(width)
223
+ setImageSizeHeight(height)
224
+ if(layoutInfo.current) {
225
+ setLayoutInfoWidth(layoutInfo.current.width)
226
+ setLayoutInfoHeight(layoutInfo.current.height)
227
+ }
228
+ setShow(true)
229
+ }
230
+ })
231
+ }, [preImageInfo?.src])
232
+
233
+ if (!preImageInfo?.src) return null
234
+
235
+ const onLayout = (res: LayoutChangeEvent) => {
236
+ const { width, height } = res?.nativeEvent?.layout || {}
237
+ layoutInfo.current = {
238
+ width,
239
+ height
240
+ }
241
+ if (sizeInfo.current) {
242
+ setImageSizeWidth(sizeInfo.current.width)
243
+ setImageSizeHeight(sizeInfo.current.height)
244
+ setLayoutInfoWidth(width)
245
+ setLayoutInfoHeight(height)
246
+ setShow(true)
247
+ }
248
+ }
249
+
250
+ return <View key='viewBgImg' {...needLayout ? {onLayout} : null } style={{ ...StyleSheet.absoluteFillObject, width: '100%', height: '100%', overflow: 'hidden'}}>
251
+ {show && <Image {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} />}
252
+ </View>
253
+ }
254
+
255
+ function splitStyle(styles: ExtendedViewStyle) {
256
+ return groupBy(styles, (key) => {
257
+ if (TEXT_STYLE_REGEX.test(key))
258
+ return 'textStyle'
259
+ else if (IMAGE_STYLE_REGEX.test(key)) return 'imageStyle'
260
+ return 'innerStyle'
261
+ }, {})
262
+ }
263
+
264
+ function every(children: ReactNode [], callback: (children: ReactNode) => boolean) {
265
+ return children.every((child) => callback(child))
266
+ }
267
+
268
+ function wrapChildren(children: ReactNode | ReactNode [] , textStyle?: StyleProp<TextStyle>, imageStyle?: ExtendedViewStyle) {
269
+ children = Array.isArray(children) ? children : [children]
270
+ if (every(children as ReactNode[], (child)=>isText(child))) {
271
+ children = [<Text key='viewTextWrap' style={textStyle}>{children}</Text>]
272
+ } else {
273
+ if(textStyle) console.warn('Text style will be ignored unless every child of the view is Text node!')
274
+ }
275
+
276
+ return [
277
+ wrapImage(imageStyle),
278
+ ...children
279
+ ]
280
+ }
281
+
282
+ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((props, ref): JSX.Element => {
283
+ const {
284
+ style = [],
285
+ children,
286
+ hoverStyle,
287
+ 'hover-start-time': hoverStartTime = 50,
288
+ 'hover-stay-time': hoverStayTime = 400,
289
+ 'enable-offset': enableOffset
290
+ } = props
291
+
292
+ const [isHover, setIsHover] = useState(false)
293
+
294
+ const layoutRef = useRef({})
295
+
296
+ // 打平 style 数组
297
+ const styleObj:ExtendedViewStyle = StyleSheet.flatten(style)
298
+ // 默认样式
299
+ const defaultStyle:ExtendedViewStyle = {
300
+ // flex 布局相关的默认样式
301
+ ...styleObj.display === 'flex' && {
302
+ flexDirection: 'row',
303
+ flexBasis: 'auto',
304
+ flexShrink: 1,
305
+ flexWrap: 'nowrap'
306
+ }
307
+ }
308
+
309
+ const { nodeRef } = useNodesRef<View, _ViewProps>(props, ref, {
310
+ defaultStyle
311
+ })
312
+
313
+ const dataRef = useRef<{
314
+ startTimer?: ReturnType<typeof setTimeout>
315
+ stayTimer?: ReturnType<typeof setTimeout>
316
+ }>({})
317
+
318
+ useEffect(() => {
319
+ return () => {
320
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
321
+ dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer)
322
+ }
323
+ }, [])
324
+
325
+ const setStartTimer = () => {
326
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
327
+ dataRef.current.startTimer = setTimeout(() => {
328
+ setIsHover(() => true)
329
+ }, +hoverStartTime)
330
+ }
331
+
332
+ const setStayTimer = () => {
333
+ dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer)
334
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer)
335
+ dataRef.current.stayTimer = setTimeout(() => {
336
+ setIsHover(() => false)
337
+ }, +hoverStayTime)
338
+ }
339
+
340
+ function onTouchStart(e: NativeSyntheticEvent<TouchEvent>){
341
+ const { bindtouchstart } = props;
342
+ bindtouchstart && bindtouchstart(e)
343
+ setStartTimer()
344
+ }
345
+
346
+ function onTouchEnd(e: NativeSyntheticEvent<TouchEvent>){
347
+ const { bindtouchend } = props;
348
+ bindtouchend && bindtouchend(e)
349
+ setStayTimer()
350
+ }
351
+
352
+ const onLayout = () => {
353
+
354
+ nodeRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
355
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
356
+ })
357
+ }
358
+
359
+ const {textStyle, imageStyle, innerStyle} = splitStyle(StyleSheet.flatten<ExtendedViewStyle>([
360
+ defaultStyle,
361
+ styleObj,
362
+ ...(isHover ? hoverStyle : [])]
363
+ ))
364
+
365
+ const innerProps = useInnerProps(props, {
366
+ ref: nodeRef,
367
+ ...enableOffset ? { onLayout } : {},
368
+ ...(hoverStyle && {
369
+ bindtouchstart: onTouchStart,
370
+ bindtouchend: onTouchEnd
371
+ })
372
+ }, [
373
+ 'style',
374
+ 'children',
375
+ 'hover-start-time',
376
+ 'hover-stay-time',
377
+ 'hoverStyle',
378
+ 'hover-class',
379
+ 'enable-offset'
380
+ ], {
381
+ layoutRef
382
+ })
383
+
384
+ return (
385
+ <View
386
+ {...innerProps}
387
+ style={innerStyle}
388
+ >
389
+ {wrapChildren(children, textStyle, imageStyle)}
390
+ </View>
391
+ )
392
+ })
393
+
394
+ _View.displayName = 'mpx-view'
395
+
396
+ export default _View
397
+
@@ -0,0 +1,39 @@
1
+ import { useRef, useEffect, useImperativeHandle, RefObject, ForwardedRef } from 'react'
2
+
3
+
4
+ type Obj = Record<string, any>
5
+
6
+ export type HandlerRef<T, P> = {
7
+ getNodeInstance(): {
8
+ props: RefObject<P>,
9
+ nodeRef: RefObject<T>,
10
+ instance: Obj
11
+ }
12
+ }
13
+
14
+ export default function useNodesRef<T, P>(props: P, ref: ForwardedRef<HandlerRef<T, P>>, instance:Obj = {} ) {
15
+ const nodeRef = useRef<T>(null)
16
+ const _props = useRef<P | null>(props)
17
+
18
+ useEffect(() => {
19
+ _props.current = props
20
+ return () => {
21
+ _props.current = null // 组件销毁,清空 _props 依赖数据
22
+ }
23
+ }, [props])
24
+ useImperativeHandle(ref, () => {
25
+ return {
26
+ getNodeInstance () {
27
+ return {
28
+ props: _props,
29
+ nodeRef,
30
+ instance
31
+ }
32
+ }
33
+ }
34
+ })
35
+
36
+ return {
37
+ nodeRef
38
+ }
39
+ }
@@ -0,0 +1,92 @@
1
+ import { useEffect, useRef, Children, ReactNode, FunctionComponent, isValidElement } from 'react'
2
+ import { StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native'
3
+
4
+ export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/
5
+
6
+ export const PERCENT_REGX = /\d+(\.\d+)?%$/
7
+
8
+ const URL_REGEX = /url\(["']?(.*?)["']?\)/
9
+
10
+ export function omit<T, K extends string>(obj: T, fields: K[]): Omit<T, K> {
11
+ const shallowCopy: any = Object.assign({}, obj)
12
+ for (let i = 0; i < fields.length; i += 1) {
13
+ const key = fields[i]
14
+ delete shallowCopy[key]
15
+ }
16
+ return shallowCopy
17
+ }
18
+
19
+ /**
20
+ * 从 style 中提取 TextStyle
21
+ * @param style
22
+ * @returns
23
+ */
24
+ export const extractTextStyle = (style: StyleProp<ViewStyle & TextStyle>): TextStyle => {
25
+ return Object.entries(StyleSheet.flatten(style)).reduce((textStyle, [key, value]) => {
26
+ TEXT_STYLE_REGEX.test(key) && Object.assign(textStyle, { [key]: value })
27
+ return textStyle
28
+ }, {})
29
+ }
30
+
31
+ /**
32
+ * 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行
33
+ */
34
+ export const useUpdateEffect = (effect: any, deps: any) => {
35
+ const isMounted = useRef(false)
36
+
37
+ // for react-refresh
38
+ useEffect(() => {
39
+ return () => {
40
+ isMounted.current = false
41
+ }
42
+ }, [])
43
+
44
+ useEffect(() => {
45
+ if (!isMounted.current) {
46
+ isMounted.current = true
47
+ } else {
48
+ return effect()
49
+ }
50
+ }, deps)
51
+ }
52
+
53
+ /**
54
+ * 解析行内样式
55
+ * @param inlineStyle
56
+ * @returns
57
+ */
58
+ export const parseInlineStyle = (inlineStyle = ''): Record<string, string> => {
59
+ return inlineStyle.split(';').reduce((styleObj, style) => {
60
+ const [k, v, ...rest] = style.split(':')
61
+ if (rest.length || !v || !k) return styleObj
62
+ const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase())
63
+ return Object.assign(styleObj, { [key]: v.trim() })
64
+ }, {})
65
+ }
66
+
67
+ export const parseUrl = (cssUrl: string = '') => {
68
+ if (!cssUrl) return
69
+
70
+ const match = cssUrl.match(URL_REGEX)
71
+
72
+ return match?.[1]
73
+ }
74
+
75
+ export const getRestProps = (transferProps: any = {}, originProps: any = {}, deletePropsKey: any = []) => {
76
+ return {
77
+ ...transferProps,
78
+ ...omit(originProps, deletePropsKey)
79
+ }
80
+ }
81
+
82
+ export const isText = (ele: ReactNode) => {
83
+ if (isValidElement(ele)) {
84
+ const displayName = (ele.type as FunctionComponent)?.displayName
85
+ return displayName === 'mpx-text' || displayName === 'Text'
86
+ }
87
+ return false
88
+ }
89
+
90
+ export function every(children: ReactNode, callback: (children: ReactNode) => boolean ) {
91
+ return Children.toArray(children).every((child) => callback(child as ReactNode))
92
+ }
@@ -0,0 +1,9 @@
1
+ declare global {
2
+ namespace NodeJS {
3
+ interface Global {
4
+ [key: string]: any
5
+ }
6
+ }
7
+ }
8
+
9
+ export function getComponent (...args: any): object
@@ -0,0 +1,21 @@
1
+ export function getComponent (component, extendOptions) {
2
+ component = component.__esModule ? component.default : component
3
+ // eslint-disable-next-line
4
+ if (extendOptions) Object.assign(component, extendOptions)
5
+ return component
6
+ }
7
+
8
+ export function createApp ({
9
+ App,
10
+ pagesMap,
11
+ firstPage,
12
+ createElement,
13
+ NavigationContainer,
14
+ createNativeStackNavigator
15
+ }) {
16
+ const Stack = createNativeStackNavigator()
17
+ const pages = []
18
+ return () => {
19
+ return createElement(NavigationContainer, null, createElement(Stack.Navigator, null, ...pages))
20
+ }
21
+ }
@@ -90,10 +90,6 @@ function isArray (arr) {
90
90
  }
91
91
  }
92
92
 
93
- function isDef (v) {
94
- return v !== undefined && v !== null
95
- }
96
-
97
93
  var escapeMap = {
98
94
  '(': '_pl_',
99
95
  ')': '_pr_',
@@ -128,7 +124,6 @@ function mpEscape (str) {
128
124
  })
129
125
  }
130
126
 
131
-
132
127
  function stringifyDynamicClass (value) {
133
128
  if (isArray(value)) {
134
129
  value = stringifyArray(value)
@@ -145,11 +140,11 @@ function stringifyDynamicClass (value) {
145
140
 
146
141
  function stringifyArray (value) {
147
142
  var res = ''
148
- var stringified
143
+ var classString
149
144
  for (var i = 0; i < value.length; i++) {
150
- if (isDef(stringified = stringifyDynamicClass(value[i])) && stringified !== '') {
145
+ if ((classString = stringifyDynamicClass(value[i]))) {
151
146
  if (res) res += ' '
152
- res += stringified
147
+ res += classString
153
148
  }
154
149
  }
155
150
  return res
@@ -10,6 +10,7 @@ const transSpecial = require('./plugins/trans-special')
10
10
  const cssArrayList = require('./plugins/css-array-list')
11
11
  const { matchCondition } = require('../utils/match-condition')
12
12
  const parseRequest = require('../utils/parse-request')
13
+ const isReact = require('../utils/env').isReact
13
14
  const RecordRuntimeInfoDependency = require('../dependencies/RecordRuntimeInfoDependency')
14
15
 
15
16
  module.exports = function (css, map) {
@@ -52,7 +53,7 @@ module.exports = function (css, map) {
52
53
  plugins.push(transSpecial({ id }))
53
54
  }
54
55
 
55
- if (mode === 'web') {
56
+ if (mode === 'web' || isReact(mode)) {
56
57
  plugins.push(transSpecial({ id }))
57
58
  }
58
59