@mpxjs/webpack-plugin 2.9.55 → 2.9.57

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 (31) hide show
  1. package/lib/index.js +2 -0
  2. package/lib/json-compiler/index.js +2 -1
  3. package/lib/platform/json/wx/index.js +0 -1
  4. package/lib/runtime/base.styl +27 -0
  5. package/lib/runtime/components/react/dist/event.config.js +27 -0
  6. package/lib/runtime/components/react/dist/getInnerListeners.js +230 -0
  7. package/lib/runtime/components/react/dist/mpx-button.jsx +270 -0
  8. package/lib/runtime/components/react/dist/mpx-image/index.jsx +229 -0
  9. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +6 -0
  10. package/lib/runtime/components/react/dist/mpx-input.jsx +203 -0
  11. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +294 -0
  12. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +353 -0
  13. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +57 -0
  14. package/lib/runtime/components/react/dist/mpx-swiper/type.js +1 -0
  15. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +25 -0
  16. package/lib/runtime/components/react/dist/mpx-text.jsx +67 -0
  17. package/lib/runtime/components/react/dist/mpx-textarea.jsx +27 -0
  18. package/lib/runtime/components/react/dist/mpx-view.jsx +307 -0
  19. package/lib/runtime/components/react/dist/types/getInnerListeners.js +1 -0
  20. package/lib/runtime/components/react/dist/useNodesRef.js +25 -0
  21. package/lib/runtime/components/react/dist/utils.js +80 -0
  22. package/lib/runtime/components/react/getInnerListeners.ts +1 -1
  23. package/lib/runtime/components/react/mpx-button.tsx +1 -2
  24. package/lib/runtime/components/react/mpx-image/svg.tsx +0 -1
  25. package/lib/runtime/components/react/{getInnerListeners.type.ts → types/getInnerListeners.ts} +2 -2
  26. package/lib/runtime/components/react/types/global.d.ts +15 -0
  27. package/lib/runtime/optionProcessor.js +27 -1
  28. package/lib/template-compiler/compiler.js +72 -25
  29. package/lib/template-compiler/index.js +2 -1
  30. package/lib/web/processTemplate.js +1 -1
  31. package/package.json +7 -4
@@ -0,0 +1,57 @@
1
+ import React, { forwardRef, useRef } from 'react';
2
+ import { default as Carouse } from './carouse';
3
+ import useInnerProps from '../getInnerListeners';
4
+ import useNodesRef from '../useNodesRef'; // 引入辅助函数
5
+ /**
6
+ * ✔ indicator-dots
7
+ * ✔ indicator-color
8
+ * ✔ indicator-active-color
9
+ * ✔ autoplay
10
+ * ✔ current
11
+ * ✔ interval
12
+ * ✔ duration
13
+ * ✔ circular
14
+ * ✔ vertical
15
+ * ✘ display-multiple-items
16
+ * ✔ previous-margin
17
+ * ✔ next-margin
18
+ * ✘ snap-to-edge
19
+ */
20
+ const _SwiperWrapper = forwardRef((props, ref) => {
21
+ const { children } = props;
22
+ let innerLayout = useRef({});
23
+ const swiperProp = {
24
+ circular: props.circular || false,
25
+ current: props.current || 0,
26
+ autoplay: props.autoplay || false,
27
+ duration: props.duration || 500,
28
+ interval: props.interval || 5000,
29
+ showsPagination: props['indicator-dots'],
30
+ dotColor: props['indicator-color'] || "rgba(0, 0, 0, .3)",
31
+ activeDotColor: props['indicator-active-color'] || '#000000',
32
+ horizontal: props.vertical !== undefined ? !props.vertical : true,
33
+ style: props.style,
34
+ previousMargin: props['previous-margin'] ? parseInt(props['previous-margin']) : 0,
35
+ nextMargin: props['next-margin'] ? parseInt(props['next-margin']) : 0,
36
+ enableOffset: props['enable-offset'] || false,
37
+ bindchange: props.bindchange
38
+ };
39
+ const { nodeRef } = useNodesRef(props, ref, {});
40
+ const innerProps = useInnerProps(props, {
41
+ ref: nodeRef
42
+ }, [
43
+ 'indicator-dots',
44
+ 'indicator-color',
45
+ 'indicator-active-color',
46
+ 'previous-margin',
47
+ 'next-margin'
48
+ ], { layoutRef: innerLayout });
49
+ const getInnerLayout = (layout) => {
50
+ innerLayout.current = layout.current;
51
+ };
52
+ return <Carouse getInnerLayout={getInnerLayout} innerProps={innerProps} {...swiperProp} {...innerProps}>
53
+ {children}
54
+ </Carouse>;
55
+ });
56
+ _SwiperWrapper.displayName = 'mpx-swiper';
57
+ export default _SwiperWrapper;
@@ -0,0 +1,25 @@
1
+ import { View } from 'react-native';
2
+ import React, { forwardRef, useRef } from 'react';
3
+ import useInnerProps from './getInnerListeners';
4
+ import useNodesRef from './useNodesRef'; // 引入辅助函数
5
+ const _SwiperItem = forwardRef((props, ref) => {
6
+ const { children, 'enable-offset': enableOffset } = props;
7
+ const layoutRef = useRef({});
8
+ const { nodeRef } = useNodesRef(props, ref, {});
9
+ const onLayout = () => {
10
+ nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
11
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
12
+ });
13
+ };
14
+ const innerProps = useInnerProps(props, {
15
+ ...(enableOffset ? { onLayout } : {}),
16
+ }, [
17
+ 'children',
18
+ 'enable-offset'
19
+ ], { layoutRef });
20
+ return (<View ref={nodeRef} data-itemId={props['item-id']} {...innerProps}>
21
+ {children}
22
+ </View>);
23
+ });
24
+ _SwiperItem.displayName = 'mpx-swiper-item';
25
+ export default _SwiperItem;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * ✔ selectable
3
+ * ✘ space
4
+ * ✘ decode
5
+ */
6
+ import { Text, StyleSheet } from 'react-native';
7
+ import { useRef, useEffect, forwardRef } from 'react';
8
+ import useInnerProps from './getInnerListeners';
9
+ // @ts-ignore
10
+ import useNodesRef from './useNodesRef'; // 引入辅助函数
11
+ import { PERCENT_REGX } from './utils';
12
+ const DEFAULT_STYLE = {
13
+ fontSize: 16
14
+ };
15
+ const transformStyle = (styleObj) => {
16
+ let { lineHeight } = styleObj;
17
+ if (typeof lineHeight === 'string' && PERCENT_REGX.test(lineHeight)) {
18
+ lineHeight = (parseFloat(lineHeight) / 100) * (styleObj.fontSize || DEFAULT_STYLE.fontSize);
19
+ styleObj.lineHeight = lineHeight;
20
+ }
21
+ };
22
+ const _Text = forwardRef((props, ref) => {
23
+ const { style = [], children, selectable, 'enable-offset': enableOffset, 'user-select': userSelect, 'disable-default-style': disableDefaultStyle = false, } = props;
24
+ const layoutRef = useRef({});
25
+ const styleObj = StyleSheet.flatten(style);
26
+ let defaultStyle = {};
27
+ if (!disableDefaultStyle) {
28
+ defaultStyle = DEFAULT_STYLE;
29
+ transformStyle(styleObj);
30
+ }
31
+ const { nodeRef } = useNodesRef(props, ref, {
32
+ defaultStyle
33
+ });
34
+ const innerProps = useInnerProps(props, {
35
+ ref: nodeRef
36
+ }, [
37
+ 'style',
38
+ 'children',
39
+ 'selectable',
40
+ 'user-select',
41
+ 'useInherit',
42
+ 'enable-offset'
43
+ ], {
44
+ layoutRef
45
+ });
46
+ useEffect(() => {
47
+ let measureTimeout = null;
48
+ if (enableOffset) {
49
+ measureTimeout = setTimeout(() => {
50
+ nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
51
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
52
+ });
53
+ });
54
+ return () => {
55
+ if (measureTimeout) {
56
+ clearTimeout(measureTimeout);
57
+ measureTimeout = null;
58
+ }
59
+ };
60
+ }
61
+ }, []);
62
+ return (<Text style={{ ...defaultStyle, ...styleObj }} selectable={!!selectable || !!userSelect} {...innerProps}>
63
+ {children}
64
+ </Text>);
65
+ });
66
+ _Text.displayName = 'mpx-text';
67
+ export default _Text;
@@ -0,0 +1,27 @@
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 } from 'react-native';
14
+ import Input from './mpx-input';
15
+ import { omit } from './utils';
16
+ const Textarea = forwardRef((props, ref) => {
17
+ const restProps = omit(props, [
18
+ 'ref',
19
+ 'type',
20
+ 'password',
21
+ 'multiline',
22
+ 'confirm-hold',
23
+ ]);
24
+ return (<Input ref={ref} multiline confirm-type='next' bindblur={() => Keyboard.dismiss()} {...restProps}/>);
25
+ });
26
+ Textarea.displayName = 'mpx-textarea';
27
+ export default Textarea;
@@ -0,0 +1,307 @@
1
+ /**
2
+ * ✔ hover-class
3
+ * ✘ hover-stop-propagation
4
+ * ✔ hover-start-time
5
+ * ✔ hover-stay-time
6
+ */
7
+ import { View, Text, StyleSheet, Image } from 'react-native';
8
+ import { useRef, useState, useEffect, forwardRef } from 'react';
9
+ // @ts-ignore
10
+ import useInnerProps from './getInnerListeners';
11
+ // @ts-ignore
12
+ import useNodesRef from './useNodesRef'; // 引入辅助函数
13
+ import { parseUrl, TEXT_STYLE_REGEX, PERCENT_REGX, isText } from './utils';
14
+ const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/;
15
+ function groupBy(style, callback, group = {}) {
16
+ let groupKey = '';
17
+ for (let key in style) {
18
+ if (style.hasOwnProperty(key)) { // 确保处理对象自身的属性
19
+ let val = style[key];
20
+ groupKey = callback(key, val);
21
+ if (!group[groupKey]) {
22
+ group[groupKey] = {};
23
+ }
24
+ group[groupKey][key] = val;
25
+ }
26
+ }
27
+ return group;
28
+ }
29
+ const applyHandlers = (handlers, args) => {
30
+ for (let handler of handlers) {
31
+ handler(...args);
32
+ }
33
+ };
34
+ const checkNeedLayout = (style) => {
35
+ const [width, height] = style.sizeList;
36
+ return (PERCENT_REGX.test(`${height}`) && width === 'auto') || (PERCENT_REGX.test(`${width}`) && height === 'auto');
37
+ };
38
+ /**
39
+ * h - 用户设置的高度
40
+ * lh - 容器的高度
41
+ * ratio - 原始图片的宽高比
42
+ * **/
43
+ function calculateSize(h, lh, ratio) {
44
+ let height, width;
45
+ if (PERCENT_REGX.test(`${h}`)) { // auto px/rpx
46
+ if (!lh)
47
+ return null;
48
+ height = (parseFloat(`${h}`) / 100) * lh;
49
+ width = height * ratio;
50
+ }
51
+ else { // 2. auto px/rpx - 根据比例计算
52
+ height = h;
53
+ width = height * ratio;
54
+ }
55
+ return {
56
+ width,
57
+ height
58
+ };
59
+ }
60
+ // background-size 转换
61
+ function backgroundSize(imageProps, preImageInfo, imageSize, layoutInfo) {
62
+ let sizeList = preImageInfo.sizeList;
63
+ if (!sizeList)
64
+ return;
65
+ // 枚举值
66
+ if (['cover', 'contain'].includes(`${sizeList[0]}`)) {
67
+ imageProps.style.resizeMode = sizeList[0];
68
+ }
69
+ else {
70
+ const [width, height] = sizeList;
71
+ let newWidth = 0, newHeight = 0;
72
+ const { width: imageSizeWidth, height: imageSizeHeight } = imageSize || {};
73
+ if (width === 'auto' && height === 'auto') { // 均为auto
74
+ if (!imageSize)
75
+ return;
76
+ newHeight = imageSizeHeight;
77
+ newWidth = imageSizeWidth;
78
+ }
79
+ else if (width === 'auto') { // auto px/rpx/%
80
+ if (!imageSize)
81
+ return;
82
+ const dimensions = calculateSize(height, layoutInfo?.height, imageSizeWidth / imageSizeHeight);
83
+ if (!dimensions)
84
+ return;
85
+ newWidth = dimensions.width;
86
+ newHeight = dimensions.height;
87
+ }
88
+ else if (height === 'auto') { // auto px/rpx/%
89
+ if (!imageSize)
90
+ return;
91
+ const dimensions = calculateSize(width, layoutInfo?.width, imageSizeHeight / imageSizeWidth);
92
+ if (!dimensions)
93
+ return;
94
+ newHeight = dimensions.width;
95
+ newWidth = dimensions.height;
96
+ }
97
+ else { // 数值类型 ImageStyle
98
+ // 数值类型设置为 stretch
99
+ imageProps.style.resizeMode = 'stretch';
100
+ newWidth = PERCENT_REGX.test(`${width}`) ? width : +width;
101
+ newHeight = PERCENT_REGX.test(`${width}`) ? height : +height;
102
+ }
103
+ // 样式合并
104
+ imageProps.style = {
105
+ ...imageProps.style,
106
+ width: newWidth,
107
+ height: newHeight
108
+ };
109
+ }
110
+ }
111
+ // background-image转换为source
112
+ function backgroundImage(imageProps, preImageInfo) {
113
+ imageProps.src = preImageInfo.src;
114
+ }
115
+ const imageStyleToProps = (preImageInfo, imageSize, layoutInfo) => {
116
+ // 初始化
117
+ const imageProps = {
118
+ style: {
119
+ resizeMode: 'cover',
120
+ ...StyleSheet.absoluteFillObject
121
+ }
122
+ };
123
+ applyHandlers([backgroundSize, backgroundImage], [imageProps, preImageInfo, imageSize, layoutInfo]);
124
+ if (!imageProps?.src)
125
+ return null;
126
+ return imageProps;
127
+ };
128
+ function preParseImage(imageStyle) {
129
+ const { backgroundImage, backgroundSize = ["auto"] } = imageStyle || {};
130
+ const src = parseUrl(backgroundImage);
131
+ let sizeList = backgroundSize.slice();
132
+ sizeList.length === 1 && sizeList.push(sizeList[0]);
133
+ return {
134
+ src,
135
+ sizeList
136
+ };
137
+ }
138
+ function wrapImage(imageStyle) {
139
+ const [show, setShow] = useState(false);
140
+ const [, setImageSizeWidth] = useState(null);
141
+ const [, setImageSizeHeight] = useState(null);
142
+ const [, setLayoutInfoWidth] = useState(null);
143
+ const [, setLayoutInfoHeight] = useState(null);
144
+ const sizeInfo = useRef(null);
145
+ const layoutInfo = useRef(null);
146
+ // 预解析
147
+ const preImageInfo = preParseImage(imageStyle);
148
+ // 判断是否可挂载onLayout
149
+ const needLayout = checkNeedLayout(preImageInfo);
150
+ const { src, sizeList } = preImageInfo;
151
+ useEffect(() => {
152
+ if (!src) {
153
+ setShow(false);
154
+ sizeInfo.current = null;
155
+ layoutInfo.current = null;
156
+ return;
157
+ }
158
+ if (!sizeList.includes('auto')) {
159
+ setShow(true);
160
+ return;
161
+ }
162
+ Image.getSize(src, (width, height) => {
163
+ sizeInfo.current = {
164
+ width,
165
+ height
166
+ };
167
+ //1. 当需要绑定onLayout 2. 获取到布局信息
168
+ if (!needLayout || layoutInfo.current) {
169
+ setImageSizeWidth(width);
170
+ setImageSizeHeight(height);
171
+ if (layoutInfo.current) {
172
+ setLayoutInfoWidth(layoutInfo.current.width);
173
+ setLayoutInfoHeight(layoutInfo.current.height);
174
+ }
175
+ setShow(true);
176
+ }
177
+ });
178
+ }, [preImageInfo?.src]);
179
+ if (!preImageInfo?.src)
180
+ return null;
181
+ const onLayout = (res) => {
182
+ const { width, height } = res?.nativeEvent?.layout || {};
183
+ layoutInfo.current = {
184
+ width,
185
+ height
186
+ };
187
+ if (sizeInfo.current) {
188
+ setImageSizeWidth(sizeInfo.current.width);
189
+ setImageSizeHeight(sizeInfo.current.height);
190
+ setLayoutInfoWidth(width);
191
+ setLayoutInfoHeight(height);
192
+ setShow(true);
193
+ }
194
+ };
195
+ return <View key='viewBgImg' {...needLayout ? { onLayout } : null} style={{ ...StyleSheet.absoluteFillObject, width: '100%', height: '100%', overflow: 'hidden' }}>
196
+ {show && <Image {...imageStyleToProps(preImageInfo, sizeInfo.current, layoutInfo.current)}/>}
197
+ </View>;
198
+ }
199
+ function splitStyle(styles) {
200
+ return groupBy(styles, (key) => {
201
+ if (TEXT_STYLE_REGEX.test(key))
202
+ return 'textStyle';
203
+ else if (IMAGE_STYLE_REGEX.test(key))
204
+ return 'imageStyle';
205
+ return 'innerStyle';
206
+ }, {});
207
+ }
208
+ function every(children, callback) {
209
+ return children.every((child) => callback(child));
210
+ }
211
+ function wrapChildren(children, textStyle, imageStyle) {
212
+ children = Array.isArray(children) ? children : [children];
213
+ if (every(children, (child) => isText(child))) {
214
+ children = [<Text key='viewTextWrap' style={textStyle}>{children}</Text>];
215
+ }
216
+ else {
217
+ if (textStyle)
218
+ console.warn('Text style will be ignored unless every child of the view is Text node!');
219
+ }
220
+ return [
221
+ wrapImage(imageStyle),
222
+ ...children
223
+ ];
224
+ }
225
+ const _View = forwardRef((props, ref) => {
226
+ const { style = [], children, hoverStyle, 'hover-start-time': hoverStartTime = 50, 'hover-stay-time': hoverStayTime = 400, 'enable-offset': enableOffset } = props;
227
+ const [isHover, setIsHover] = useState(false);
228
+ const layoutRef = useRef({});
229
+ // 打平 style 数组
230
+ const styleObj = StyleSheet.flatten(style);
231
+ // 默认样式
232
+ const defaultStyle = {
233
+ // flex 布局相关的默认样式
234
+ ...styleObj.display === 'flex' && {
235
+ flexDirection: 'row',
236
+ flexBasis: 'auto',
237
+ flexShrink: 1,
238
+ flexWrap: 'nowrap'
239
+ }
240
+ };
241
+ const { nodeRef } = useNodesRef(props, ref, {
242
+ defaultStyle
243
+ });
244
+ const dataRef = useRef({});
245
+ useEffect(() => {
246
+ return () => {
247
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
248
+ dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
249
+ };
250
+ }, []);
251
+ const setStartTimer = () => {
252
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
253
+ dataRef.current.startTimer = setTimeout(() => {
254
+ setIsHover(() => true);
255
+ }, +hoverStartTime);
256
+ };
257
+ const setStayTimer = () => {
258
+ dataRef.current.stayTimer && clearTimeout(dataRef.current.stayTimer);
259
+ dataRef.current.startTimer && clearTimeout(dataRef.current.startTimer);
260
+ dataRef.current.stayTimer = setTimeout(() => {
261
+ setIsHover(() => false);
262
+ }, +hoverStayTime);
263
+ };
264
+ function onTouchStart(e) {
265
+ const { bindtouchstart } = props;
266
+ bindtouchstart && bindtouchstart(e);
267
+ setStartTimer();
268
+ }
269
+ function onTouchEnd(e) {
270
+ const { bindtouchend } = props;
271
+ bindtouchend && bindtouchend(e);
272
+ setStayTimer();
273
+ }
274
+ const onLayout = () => {
275
+ nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
276
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
277
+ });
278
+ };
279
+ const { textStyle, imageStyle, innerStyle } = splitStyle(StyleSheet.flatten([
280
+ defaultStyle,
281
+ styleObj,
282
+ ...(isHover ? hoverStyle : [])
283
+ ]));
284
+ const innerProps = useInnerProps(props, {
285
+ ref: nodeRef,
286
+ ...enableOffset ? { onLayout } : {},
287
+ ...(hoverStyle && {
288
+ bindtouchstart: onTouchStart,
289
+ bindtouchend: onTouchEnd
290
+ })
291
+ }, [
292
+ 'style',
293
+ 'children',
294
+ 'hover-start-time',
295
+ 'hover-stay-time',
296
+ 'hoverStyle',
297
+ 'hover-class',
298
+ 'enable-offset'
299
+ ], {
300
+ layoutRef
301
+ });
302
+ return (<View {...innerProps} style={innerStyle}>
303
+ {wrapChildren(children, textStyle, imageStyle)}
304
+ </View>);
305
+ });
306
+ _View.displayName = 'mpx-view';
307
+ export default _View;
@@ -0,0 +1,25 @@
1
+ import { useRef, useEffect, useImperativeHandle } from 'react';
2
+ export default function useNodesRef(props, ref, instance = {}) {
3
+ const nodeRef = useRef(null);
4
+ const _props = useRef(props);
5
+ useEffect(() => {
6
+ _props.current = props;
7
+ return () => {
8
+ _props.current = null; // 组件销毁,清空 _props 依赖数据
9
+ };
10
+ }, [props]);
11
+ useImperativeHandle(ref, () => {
12
+ return {
13
+ getNodeInstance() {
14
+ return {
15
+ props: _props,
16
+ nodeRef,
17
+ instance
18
+ };
19
+ }
20
+ };
21
+ });
22
+ return {
23
+ nodeRef
24
+ };
25
+ }
@@ -0,0 +1,80 @@
1
+ import { useEffect, useRef, Children, isValidElement } from 'react';
2
+ import { StyleSheet } from 'react-native';
3
+ export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/;
4
+ export const PERCENT_REGX = /\d+(\.\d+)?%$/;
5
+ const URL_REGEX = /url\(["']?(.*?)["']?\)/;
6
+ export function omit(obj, fields) {
7
+ const shallowCopy = Object.assign({}, obj);
8
+ for (let i = 0; i < fields.length; i += 1) {
9
+ const key = fields[i];
10
+ delete shallowCopy[key];
11
+ }
12
+ return shallowCopy;
13
+ }
14
+ /**
15
+ * 从 style 中提取 TextStyle
16
+ * @param style
17
+ * @returns
18
+ */
19
+ export const extractTextStyle = (style) => {
20
+ return Object.entries(StyleSheet.flatten(style)).reduce((textStyle, [key, value]) => {
21
+ TEXT_STYLE_REGEX.test(key) && Object.assign(textStyle, { [key]: value });
22
+ return textStyle;
23
+ }, {});
24
+ };
25
+ /**
26
+ * 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行
27
+ */
28
+ export const useUpdateEffect = (effect, deps) => {
29
+ const isMounted = useRef(false);
30
+ // for react-refresh
31
+ useEffect(() => {
32
+ return () => {
33
+ isMounted.current = false;
34
+ };
35
+ }, []);
36
+ useEffect(() => {
37
+ if (!isMounted.current) {
38
+ isMounted.current = true;
39
+ }
40
+ else {
41
+ return effect();
42
+ }
43
+ }, deps);
44
+ };
45
+ /**
46
+ * 解析行内样式
47
+ * @param inlineStyle
48
+ * @returns
49
+ */
50
+ export const parseInlineStyle = (inlineStyle = '') => {
51
+ return inlineStyle.split(';').reduce((styleObj, style) => {
52
+ const [k, v, ...rest] = style.split(':');
53
+ if (rest.length || !v || !k)
54
+ return styleObj;
55
+ const key = k.trim().replace(/-./g, c => c.substring(1).toUpperCase());
56
+ return Object.assign(styleObj, { [key]: v.trim() });
57
+ }, {});
58
+ };
59
+ export const parseUrl = (cssUrl = '') => {
60
+ if (!cssUrl)
61
+ return;
62
+ const match = cssUrl.match(URL_REGEX);
63
+ return match?.[1];
64
+ };
65
+ export const getRestProps = (transferProps = {}, originProps = {}, deletePropsKey = []) => {
66
+ return {
67
+ ...transferProps,
68
+ ...omit(originProps, deletePropsKey)
69
+ };
70
+ };
71
+ export const isText = (ele) => {
72
+ if (isValidElement(ele)) {
73
+ const displayName = ele.type?.displayName;
74
+ return displayName === 'mpx-text' || displayName === 'Text';
75
+ }
76
+ return false;
77
+ };
78
+ export function every(children, callback) {
79
+ return Children.toArray(children).every((child) => callback(child));
80
+ }
@@ -11,7 +11,7 @@ import {
11
11
  DataSetType,
12
12
  LayoutRef,
13
13
  NativeTouchEvent
14
- } from './getInnerListeners.type'
14
+ } from './types/getInnerListeners'
15
15
 
16
16
  const getTouchEvent = (
17
17
  type: string,
@@ -331,14 +331,13 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
331
331
  const catchTap = (evt: NativeSyntheticEvent<TouchEvent>) => {
332
332
  if (disabled) return
333
333
  catchtap && catchtap(getCustomEvent('tap', evt, { layoutRef }, props))
334
- handleOpenTypeEvent(evt)
335
334
  }
336
335
 
337
336
  function wrapChildren(children: ReactNode, textStyle?: StyleProp<TextStyle>) {
338
337
  if (every(children, (child)=>isText(child))) {
339
338
  children = [<Text key='buttonTextWrap' style={textStyle}>{children}</Text>]
340
339
  } else {
341
- if(textStyle) console.warn('Text style will be ignored unless every child of the button is Text node!')
340
+ if(textStyle) console.warn('Text style will be ignored unless every child of the Button is Text node!')
342
341
  }
343
342
 
344
343
  return children
@@ -1,7 +1,6 @@
1
1
  import React from 'react'
2
2
  import type { ImageSourcePropType, ImageStyle, StyleProp } from 'react-native'
3
3
  import { SvgCssUri, WithLocalSvg } from 'react-native-svg/css'
4
-
5
4
  interface SvgProps {
6
5
  local?: boolean
7
6
  src: string | ImageSourcePropType
@@ -1,7 +1,7 @@
1
- import React from 'react'
1
+ import { MutableRefObject } from 'react'
2
2
  import { NativeSyntheticEvent } from 'react-native'
3
3
 
4
- type LayoutRef = React.MutableRefObject<any>
4
+ type LayoutRef = MutableRefObject<any>
5
5
 
6
6
  type SetTimeoutReturnType = ReturnType<typeof setTimeout>
7
7
 
@@ -0,0 +1,15 @@
1
+ declare module 'react-native-svg/css' {
2
+ import type { ImageSourcePropType, StyleProp, ImageStyle } from 'react-native'
3
+ import type { SvgProps as SvgCssUriProps } from 'react-native-svg'
4
+
5
+ export const SvgCssUri: React.ComponentType<SvgCssUriProps & { uri?: string }>
6
+
7
+ export interface WithLocalSvgProps {
8
+ asset: ImageSourcePropType
9
+ style?: StyleProp<ImageStyle>
10
+ width?: string | number
11
+ height?: string | number
12
+ }
13
+
14
+ export const WithLocalSvg: React.ComponentType<WithLocalSvgProps>
15
+ }