@mpxjs/webpack-plugin 2.9.59 → 2.9.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/platform/style/wx/index.js +314 -254
- package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
- package/lib/platform/template/wx/component-config/checkbox.js +8 -0
- package/lib/platform/template/wx/component-config/cover-image.js +15 -0
- package/lib/platform/template/wx/component-config/cover-view.js +9 -0
- package/lib/platform/template/wx/component-config/form.js +13 -1
- package/lib/platform/template/wx/component-config/icon.js +8 -0
- package/lib/platform/template/wx/component-config/index.js +5 -1
- package/lib/platform/template/wx/component-config/label.js +15 -0
- package/lib/platform/template/wx/component-config/movable-area.js +18 -1
- package/lib/platform/template/wx/component-config/movable-view.js +18 -1
- package/lib/platform/template/wx/component-config/navigator.js +8 -0
- package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
- package/lib/platform/template/wx/component-config/picker-view.js +18 -2
- package/lib/platform/template/wx/component-config/picker.js +14 -1
- package/lib/platform/template/wx/component-config/radio-group.js +8 -0
- package/lib/platform/template/wx/component-config/radio.js +8 -0
- package/lib/platform/template/wx/component-config/root-portal.js +15 -0
- package/lib/platform/template/wx/component-config/switch.js +8 -0
- package/lib/platform/template/wx/component-config/unsupported.js +1 -3
- package/lib/react/processScript.js +2 -0
- package/lib/runtime/components/react/context.ts +38 -0
- package/lib/runtime/components/react/dist/context.js +7 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +22 -11
- package/lib/runtime/components/react/dist/mpx-button.jsx +67 -45
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +81 -0
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +152 -0
- package/lib/runtime/components/react/dist/mpx-form.jsx +59 -0
- package/lib/runtime/components/react/dist/mpx-icon.jsx +51 -0
- package/lib/runtime/components/react/dist/mpx-image/index.jsx +17 -22
- package/lib/runtime/components/react/dist/mpx-image/svg.jsx +0 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +38 -16
- package/lib/runtime/components/react/dist/mpx-label.jsx +63 -0
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +46 -0
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
- package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +139 -0
- package/lib/runtime/components/react/dist/mpx-picker/region.jsx +90 -0
- package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
- package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
- package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +15 -0
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +68 -0
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +79 -0
- package/lib/runtime/components/react/dist/mpx-radio.jsx +169 -0
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +11 -0
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +66 -50
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +206 -147
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +9 -7
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-switch.jsx +76 -0
- package/lib/runtime/components/react/dist/mpx-text.jsx +7 -19
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-view.jsx +326 -96
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +9 -15
- package/lib/runtime/components/react/dist/types/common.js +1 -0
- package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
- package/lib/runtime/components/react/dist/utils.js +82 -14
- package/lib/runtime/components/react/getInnerListeners.ts +25 -13
- package/lib/runtime/components/react/mpx-button.tsx +87 -67
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +147 -0
- package/lib/runtime/components/react/mpx-checkbox.tsx +245 -0
- package/lib/runtime/components/react/mpx-form.tsx +89 -0
- package/lib/runtime/components/react/mpx-icon.tsx +103 -0
- package/lib/runtime/components/react/mpx-image/index.tsx +20 -32
- package/lib/runtime/components/react/mpx-image/svg.tsx +2 -2
- package/lib/runtime/components/react/mpx-input.tsx +54 -26
- package/lib/runtime/components/react/mpx-label.tsx +115 -0
- package/lib/runtime/components/react/mpx-movable-area.tsx +67 -0
- package/lib/runtime/components/react/mpx-movable-view.tsx +425 -0
- package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
- package/lib/runtime/components/react/mpx-picker/date.tsx +83 -0
- package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +153 -0
- package/lib/runtime/components/react/mpx-picker/region.tsx +104 -0
- package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
- package/lib/runtime/components/react/mpx-picker/selector.tsx +92 -0
- package/lib/runtime/components/react/mpx-picker/time.tsx +274 -0
- package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +28 -0
- package/lib/runtime/components/react/mpx-picker-view.tsx +104 -0
- package/lib/runtime/components/react/mpx-radio-group.tsx +147 -0
- package/lib/runtime/components/react/mpx-radio.tsx +246 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +25 -0
- package/lib/runtime/components/react/mpx-scroll-view.tsx +82 -58
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +203 -156
- package/lib/runtime/components/react/mpx-swiper/index.tsx +12 -13
- package/lib/runtime/components/react/mpx-swiper/type.ts +11 -4
- package/lib/runtime/components/react/mpx-swiper-item.tsx +5 -3
- package/lib/runtime/components/react/mpx-switch.tsx +127 -0
- package/lib/runtime/components/react/mpx-text.tsx +52 -68
- package/lib/runtime/components/react/mpx-textarea.tsx +2 -2
- package/lib/runtime/components/react/mpx-view.tsx +373 -140
- package/lib/runtime/components/react/mpx-web-view.tsx +24 -28
- package/lib/runtime/components/react/types/common.ts +12 -0
- package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
- package/lib/runtime/components/react/types/global.d.ts +4 -0
- package/lib/runtime/components/react/useNodesRef.ts +3 -8
- package/lib/runtime/components/react/utils.ts +93 -15
- package/lib/runtime/optionProcessor.js +19 -17
- package/lib/template-compiler/compiler.js +56 -41
- package/lib/template-compiler/gen-node-react.js +7 -7
- package/package.json +6 -3
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { useRef,
|
|
1
|
+
import { useRef, useImperativeHandle } from 'react';
|
|
2
2
|
export default function useNodesRef(props, ref, instance = {}) {
|
|
3
3
|
const nodeRef = useRef(null);
|
|
4
|
-
const _props = useRef(
|
|
5
|
-
|
|
6
|
-
_props.current = props;
|
|
7
|
-
return () => {
|
|
8
|
-
_props.current = null; // 组件销毁,清空 _props 依赖数据
|
|
9
|
-
};
|
|
10
|
-
}, [props]);
|
|
4
|
+
const _props = useRef(null);
|
|
5
|
+
_props.current = props;
|
|
11
6
|
useImperativeHandle(ref, () => {
|
|
12
7
|
return {
|
|
13
8
|
getNodeInstance() {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { useEffect, useRef,
|
|
2
|
-
import { StyleSheet } from 'react-native';
|
|
1
|
+
import { useEffect, useRef, isValidElement } from 'react';
|
|
3
2
|
export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/;
|
|
4
3
|
export const PERCENT_REGEX = /^\s*-?\d+(\.\d+)?%\s*$/;
|
|
4
|
+
export const IMAGE_STYLE_REGEX = /^background(Image|Size|Repeat|Position)$/;
|
|
5
|
+
export const TEXT_PROPS_REGEX = /ellipsizeMode|numberOfLines/;
|
|
6
|
+
export const DEFAULT_STYLE = {
|
|
7
|
+
fontSize: 16
|
|
8
|
+
};
|
|
5
9
|
const URL_REGEX = /url\(["']?(.*?)["']?\)/;
|
|
6
10
|
export function omit(obj, fields) {
|
|
7
11
|
const shallowCopy = Object.assign({}, obj);
|
|
@@ -11,17 +15,6 @@ export function omit(obj, fields) {
|
|
|
11
15
|
}
|
|
12
16
|
return shallowCopy;
|
|
13
17
|
}
|
|
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
18
|
/**
|
|
26
19
|
* 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行
|
|
27
20
|
*/
|
|
@@ -75,6 +68,81 @@ export const isText = (ele) => {
|
|
|
75
68
|
}
|
|
76
69
|
return false;
|
|
77
70
|
};
|
|
71
|
+
export const isEmbedded = (ele) => {
|
|
72
|
+
if (isValidElement(ele)) {
|
|
73
|
+
const displayName = ele.type?.displayName;
|
|
74
|
+
return displayName && ['mpx-checkbox', 'mpx-radio', 'mpx-switch'].includes(displayName);
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
};
|
|
78
78
|
export function every(children, callback) {
|
|
79
|
-
|
|
79
|
+
const childrenArray = Array.isArray(children) ? children : [children];
|
|
80
|
+
return childrenArray.every((child) => callback(child));
|
|
81
|
+
}
|
|
82
|
+
export function groupBy(obj, callback, group = {}) {
|
|
83
|
+
let groupKey = '';
|
|
84
|
+
for (let key in obj) {
|
|
85
|
+
if (obj.hasOwnProperty(key)) { // 确保处理对象自身的属性
|
|
86
|
+
let val = obj[key];
|
|
87
|
+
groupKey = callback(key, val);
|
|
88
|
+
if (!group[groupKey]) {
|
|
89
|
+
group[groupKey] = {};
|
|
90
|
+
}
|
|
91
|
+
group[groupKey][key] = val;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return group;
|
|
80
95
|
}
|
|
96
|
+
export const normalizeStyle = (style = {}) => {
|
|
97
|
+
const { borderRadius } = style;
|
|
98
|
+
if (borderRadius && PERCENT_REGEX.test(borderRadius)) {
|
|
99
|
+
style.borderTopLeftRadius = borderRadius;
|
|
100
|
+
style.borderBottomLeftRadius = borderRadius;
|
|
101
|
+
style.borderBottomRightRadius = borderRadius;
|
|
102
|
+
style.borderTopRightRadius = borderRadius;
|
|
103
|
+
delete style.borderRadius;
|
|
104
|
+
}
|
|
105
|
+
['backgroundSize', 'backgroundPosition'].forEach(name => {
|
|
106
|
+
if (style[name] && typeof style[name] === 'string') {
|
|
107
|
+
if (style[name].trim()) {
|
|
108
|
+
style[name] = style[name].split(' ');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return style;
|
|
113
|
+
};
|
|
114
|
+
export function splitStyle(styles) {
|
|
115
|
+
return groupBy(styles, (key) => {
|
|
116
|
+
if (TEXT_STYLE_REGEX.test(key)) {
|
|
117
|
+
return 'textStyle';
|
|
118
|
+
}
|
|
119
|
+
else if (IMAGE_STYLE_REGEX.test(key)) {
|
|
120
|
+
return 'imageStyle';
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return 'innerStyle';
|
|
124
|
+
}
|
|
125
|
+
}, {});
|
|
126
|
+
}
|
|
127
|
+
export function splitProps(props) {
|
|
128
|
+
return groupBy(props, (key) => {
|
|
129
|
+
if (TEXT_PROPS_REGEX.test(key)) {
|
|
130
|
+
return 'textProps';
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
return 'innerProps';
|
|
134
|
+
}
|
|
135
|
+
}, {});
|
|
136
|
+
}
|
|
137
|
+
export const throwReactWarning = (message) => {
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
console.warn(message);
|
|
140
|
+
}, 0);
|
|
141
|
+
};
|
|
142
|
+
export const transformTextStyle = (styleObj) => {
|
|
143
|
+
let { lineHeight } = styleObj;
|
|
144
|
+
if (typeof lineHeight === 'string' && PERCENT_REGEX.test(lineHeight)) {
|
|
145
|
+
lineHeight = (parseFloat(lineHeight) / 100) * (styleObj.fontSize || DEFAULT_STYLE.fontSize);
|
|
146
|
+
styleObj.lineHeight = lineHeight;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
@@ -97,8 +97,10 @@ export const getCustomEvent = (
|
|
|
97
97
|
dataset: getDataSet(props),
|
|
98
98
|
offsetLeft: layoutRef?.current?.offsetLeft || 0,
|
|
99
99
|
offsetTop: layoutRef?.current?.offsetTop || 0
|
|
100
|
-
}
|
|
101
|
-
|
|
100
|
+
},
|
|
101
|
+
persist: oe.persist,
|
|
102
|
+
stopPropagation: oe.stopPropagation,
|
|
103
|
+
preventDefault: oe.preventDefault
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
|
|
@@ -106,7 +108,7 @@ const useInnerProps = (
|
|
|
106
108
|
props: Props = {},
|
|
107
109
|
additionalProps: AdditionalProps = {},
|
|
108
110
|
removeProps: RemoveProps = [],
|
|
109
|
-
rawConfig
|
|
111
|
+
rawConfig?: UseInnerPropsConfig
|
|
110
112
|
) => {
|
|
111
113
|
const ref = useRef<InnerRef>({
|
|
112
114
|
startTimer: {
|
|
@@ -127,7 +129,7 @@ const useInnerProps = (
|
|
|
127
129
|
|
|
128
130
|
const propsRef = useRef<Record<string, any>>({})
|
|
129
131
|
const eventConfig: { [key: string]: string[] } = {}
|
|
130
|
-
const config = rawConfig || {}
|
|
132
|
+
const config = rawConfig || { layoutRef: { current: {} }, disableTouch: false, disableTap: false }
|
|
131
133
|
|
|
132
134
|
propsRef.current = { ...props, ...additionalProps }
|
|
133
135
|
|
|
@@ -156,6 +158,19 @@ const useInnerProps = (
|
|
|
156
158
|
}
|
|
157
159
|
})
|
|
158
160
|
}
|
|
161
|
+
|
|
162
|
+
function checkIsNeedPress (e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
163
|
+
const tapDetailInfo = ref.current.mpxPressInfo.detail || { x: 0, y: 0 }
|
|
164
|
+
const nativeEvent = e.nativeEvent
|
|
165
|
+
const currentPageX = nativeEvent.changedTouches[0].pageX
|
|
166
|
+
const currentPageY = nativeEvent.changedTouches[0].pageY
|
|
167
|
+
if (Math.abs(currentPageX - tapDetailInfo.x) > 1 || Math.abs(currentPageY - tapDetailInfo.y) > 1) {
|
|
168
|
+
ref.current.needPress[type] = false
|
|
169
|
+
ref.current.startTimer[type] && clearTimeout(ref.current.startTimer[type] as SetTimeoutReturnType)
|
|
170
|
+
ref.current.startTimer[type] = null
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
159
174
|
function handleTouchstart(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
160
175
|
e.persist()
|
|
161
176
|
const bubbleTouchEvent = ['catchtouchstart', 'bindtouchstart']
|
|
@@ -184,20 +199,14 @@ const useInnerProps = (
|
|
|
184
199
|
function handleTouchmove(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
185
200
|
const bubbleTouchEvent = ['catchtouchmove', 'bindtouchmove']
|
|
186
201
|
const captureTouchEvent = ['capture-catchtouchmove', 'capture-bindtouchmove']
|
|
187
|
-
const tapDetailInfo = ref.current.mpxPressInfo.detail || { x: 0, y: 0 }
|
|
188
|
-
const nativeEvent = e.nativeEvent
|
|
189
|
-
const currentPageX = nativeEvent.changedTouches[0].pageX
|
|
190
|
-
const currentPageY = nativeEvent.changedTouches[0].pageY
|
|
191
202
|
const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent
|
|
192
|
-
if (Math.abs(currentPageX - tapDetailInfo.x) > 1 || Math.abs(currentPageY - tapDetailInfo.y) > 1) {
|
|
193
|
-
ref.current.needPress[type] = false
|
|
194
|
-
ref.current.startTimer[type] && clearTimeout(ref.current.startTimer[type] as SetTimeoutReturnType)
|
|
195
|
-
ref.current.startTimer[type] = null
|
|
196
|
-
}
|
|
197
203
|
handleEmitEvent(currentTouchEvent, 'touchmove', e)
|
|
204
|
+
checkIsNeedPress(e, type)
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
function handleTouchend(e: NativeTouchEvent, type: 'bubble' | 'capture') {
|
|
208
|
+
// move event may not be triggered
|
|
209
|
+
checkIsNeedPress(e, type)
|
|
201
210
|
const bubbleTouchEvent = ['catchtouchend', 'bindtouchend']
|
|
202
211
|
const bubbleTapEvent = ['catchtap', 'bindtap']
|
|
203
212
|
const captureTouchEvent = ['capture-catchtouchend', 'capture-bindtouchend']
|
|
@@ -208,6 +217,9 @@ const useInnerProps = (
|
|
|
208
217
|
ref.current.startTimer[type] = null
|
|
209
218
|
handleEmitEvent(currentTouchEvent, 'touchend', e)
|
|
210
219
|
if (ref.current.needPress[type]) {
|
|
220
|
+
if (type === 'bubble' && config.disableTap) {
|
|
221
|
+
return
|
|
222
|
+
}
|
|
211
223
|
handleEmitEvent(currentTapEvent, 'tap', e)
|
|
212
224
|
}
|
|
213
225
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ✔ plain
|
|
5
5
|
* ✔ disabled
|
|
6
6
|
* ✔ loading
|
|
7
|
-
*
|
|
7
|
+
* ✔ form-type
|
|
8
8
|
* - open-type: Partially. Only support `share`、`getUserInfo`
|
|
9
9
|
* ✔ hover-class: Convert hoverClass to hoverStyle.
|
|
10
10
|
* ✔ hover-style
|
|
@@ -34,27 +34,23 @@
|
|
|
34
34
|
* ✘ bindagreeprivacyauthorization
|
|
35
35
|
* ✔ bindtap
|
|
36
36
|
*/
|
|
37
|
-
import
|
|
38
|
-
|
|
39
|
-
useRef,
|
|
40
|
-
useState,
|
|
41
|
-
ReactNode,
|
|
42
|
-
forwardRef,
|
|
43
|
-
} from 'react'
|
|
37
|
+
import { useEffect, useRef, useState, ReactNode, forwardRef, useContext, JSX } from 'react'
|
|
38
|
+
|
|
44
39
|
import {
|
|
45
40
|
View,
|
|
46
41
|
Text,
|
|
47
42
|
StyleSheet,
|
|
48
|
-
StyleProp,
|
|
49
43
|
ViewStyle,
|
|
50
44
|
TextStyle,
|
|
51
45
|
Animated,
|
|
52
46
|
Easing,
|
|
53
47
|
NativeSyntheticEvent,
|
|
54
48
|
} from 'react-native'
|
|
55
|
-
import {
|
|
49
|
+
import { splitStyle, isText, every, splitProps, throwReactWarning, transformTextStyle } from './utils'
|
|
56
50
|
import useInnerProps, { getCustomEvent } from './getInnerListeners'
|
|
57
51
|
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
52
|
+
import { FormContext } from './context'
|
|
53
|
+
import { isEmptyObject } from '@mpxjs/utils'
|
|
58
54
|
|
|
59
55
|
export type Type = 'default' | 'primary' | 'warn'
|
|
60
56
|
|
|
@@ -74,16 +70,16 @@ export interface ButtonProps {
|
|
|
74
70
|
disabled?: boolean
|
|
75
71
|
loading?: boolean
|
|
76
72
|
'hover-class'?: string
|
|
77
|
-
'hover-style'?:
|
|
73
|
+
'hover-style'?: ViewStyle & TextStyle & Record<string, any>
|
|
78
74
|
'hover-start-time'?: number
|
|
79
75
|
'hover-stay-time'?: number
|
|
80
76
|
'open-type'?: OpenType
|
|
77
|
+
'form-type'?: 'submit' | 'reset'
|
|
81
78
|
'enable-offset'?: boolean,
|
|
82
|
-
style?:
|
|
79
|
+
style?: ViewStyle & TextStyle & Record<string, any>
|
|
83
80
|
children: ReactNode
|
|
84
81
|
bindgetuserinfo?: (userInfo: any) => void
|
|
85
82
|
bindtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
86
|
-
catchtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
87
83
|
bindtouchstart?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
88
84
|
bindtouchend?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
89
85
|
}
|
|
@@ -132,27 +128,27 @@ const styles = StyleSheet.create({
|
|
|
132
128
|
const getOpenTypeEvent = (openType: OpenType) => {
|
|
133
129
|
// @ts-ignore
|
|
134
130
|
if (!global?.__mpx?.config?.rnConfig) {
|
|
135
|
-
|
|
131
|
+
throwReactWarning('[Mpx runtime warn]: Environment not supported')
|
|
136
132
|
return
|
|
137
133
|
}
|
|
138
134
|
|
|
139
135
|
const eventName = OpenTypeEventsMap.get(openType)
|
|
140
136
|
if (!eventName) {
|
|
141
|
-
|
|
137
|
+
throwReactWarning(`[Mpx runtime warn]: open-type not support ${openType}`)
|
|
142
138
|
return
|
|
143
139
|
}
|
|
144
140
|
|
|
145
141
|
// @ts-ignore
|
|
146
142
|
const event = global.__mpx.config.rnConfig?.openTypeHandler?.[eventName]
|
|
147
143
|
if (!event) {
|
|
148
|
-
|
|
144
|
+
throwReactWarning(`[Mpx runtime warn]: Unregistered ${eventName} event`)
|
|
149
145
|
return
|
|
150
146
|
}
|
|
151
147
|
|
|
152
148
|
return event
|
|
153
149
|
}
|
|
154
150
|
|
|
155
|
-
const Loading = ({ alone = false }: { alone: boolean }):
|
|
151
|
+
const Loading = ({ alone = false }: { alone: boolean }): JSX.Element => {
|
|
156
152
|
const image = useRef(new Animated.Value(0)).current
|
|
157
153
|
|
|
158
154
|
const rotate = image.interpolate({
|
|
@@ -188,7 +184,7 @@ const Loading = ({ alone = false }: { alone: boolean }): React.JSX.Element => {
|
|
|
188
184
|
return <Animated.Image testID="loading" style={loadingStyle} source={{ uri: LOADING_IMAGE_URI }} />
|
|
189
185
|
}
|
|
190
186
|
|
|
191
|
-
const Button = forwardRef<HandlerRef<
|
|
187
|
+
const Button = forwardRef<HandlerRef<View, ButtonProps>, ButtonProps>((props, ref): JSX.Element => {
|
|
192
188
|
const {
|
|
193
189
|
size = 'default',
|
|
194
190
|
type = 'default',
|
|
@@ -196,20 +192,31 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
196
192
|
disabled = false,
|
|
197
193
|
loading = false,
|
|
198
194
|
'hover-class': hoverClass,
|
|
199
|
-
'hover-style': hoverStyle =
|
|
195
|
+
'hover-style': hoverStyle = {},
|
|
200
196
|
'hover-start-time': hoverStartTime = 20,
|
|
201
197
|
'hover-stay-time': hoverStayTime = 70,
|
|
202
198
|
'open-type': openType,
|
|
203
199
|
'enable-offset': enableOffset,
|
|
204
|
-
|
|
200
|
+
'form-type': formType,
|
|
201
|
+
style = {},
|
|
205
202
|
children,
|
|
206
203
|
bindgetuserinfo,
|
|
207
204
|
bindtap,
|
|
208
|
-
catchtap,
|
|
209
205
|
bindtouchstart,
|
|
210
206
|
bindtouchend,
|
|
211
207
|
} = props
|
|
212
208
|
|
|
209
|
+
|
|
210
|
+
const formContext = useContext(FormContext)
|
|
211
|
+
|
|
212
|
+
let submitFn: () => void | undefined;
|
|
213
|
+
let resetFn: () => void | undefined;
|
|
214
|
+
|
|
215
|
+
if (formContext) {
|
|
216
|
+
submitFn = formContext.submit
|
|
217
|
+
resetFn = formContext.reset
|
|
218
|
+
}
|
|
219
|
+
|
|
213
220
|
const refs = useRef<{
|
|
214
221
|
hoverStartTimer: ReturnType<typeof setTimeout> | undefined
|
|
215
222
|
hoverStayTimer: ReturnType<typeof setTimeout> | undefined
|
|
@@ -226,9 +233,13 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
226
233
|
|
|
227
234
|
const applyHoverEffect = isHover && hoverClass !== 'none'
|
|
228
235
|
|
|
229
|
-
const
|
|
236
|
+
const { textStyle, imageStyle, innerStyle } = splitStyle(style)
|
|
237
|
+
|
|
238
|
+
const { textStyle: hoverTextStyle, imageStyle: hoverImageStyle, innerStyle: hoverInnerStyle } = splitStyle(hoverStyle)
|
|
230
239
|
|
|
231
|
-
|
|
240
|
+
if (imageStyle || hoverImageStyle) {
|
|
241
|
+
throwReactWarning('[Mpx runtime warn]: Button does not support background image-related styles!')
|
|
242
|
+
}
|
|
232
243
|
|
|
233
244
|
const [color, hoverColor, plainColor, disabledColor] = TypeColorMap[type]
|
|
234
245
|
|
|
@@ -237,16 +248,16 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
237
248
|
const plainBorderColor = disabled
|
|
238
249
|
? 'rgba(0, 0, 0, .2)'
|
|
239
250
|
: applyHoverEffect
|
|
240
|
-
|
|
241
|
-
|
|
251
|
+
? `rgba(${plainColor},.6)`
|
|
252
|
+
: `rgb(${plainColor})`
|
|
242
253
|
|
|
243
254
|
const normalBorderColor = type === 'default' ? 'rgba(0, 0, 0, .2)' : normalBackgroundColor
|
|
244
255
|
|
|
245
256
|
const plainTextColor = disabled
|
|
246
257
|
? 'rgba(0, 0, 0, .2)'
|
|
247
258
|
: applyHoverEffect
|
|
248
|
-
|
|
249
|
-
|
|
259
|
+
? `rgba(${plainColor}, .6)`
|
|
260
|
+
: `rgb(${plainColor})`
|
|
250
261
|
|
|
251
262
|
const normalTextColor =
|
|
252
263
|
type === 'default'
|
|
@@ -260,20 +271,17 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
260
271
|
backgroundColor: plain ? 'transparent' : normalBackgroundColor,
|
|
261
272
|
}
|
|
262
273
|
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
...
|
|
274
|
+
const defaultViewStyle = {
|
|
275
|
+
...styles.button,
|
|
276
|
+
...(isMiniSize && styles.buttonMini),
|
|
277
|
+
...viewStyle,
|
|
266
278
|
}
|
|
267
279
|
|
|
268
|
-
const
|
|
269
|
-
styles.
|
|
270
|
-
isMiniSize && styles.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const defaultTextStyle = [
|
|
275
|
-
styles.text, isMiniSize && styles.textMini, textStyle
|
|
276
|
-
]
|
|
280
|
+
const defaultTextStyle = {
|
|
281
|
+
...styles.text,
|
|
282
|
+
...(isMiniSize && styles.textMini),
|
|
283
|
+
color: plain ? plainTextColor : normalTextColor,
|
|
284
|
+
}
|
|
277
285
|
|
|
278
286
|
const handleOpenTypeEvent = (evt: NativeSyntheticEvent<TouchEvent>) => {
|
|
279
287
|
if (!openType) return
|
|
@@ -286,11 +294,13 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
286
294
|
})
|
|
287
295
|
}
|
|
288
296
|
|
|
289
|
-
if (openType === 'getUserInfo') {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
297
|
+
if (openType === 'getUserInfo' && handleEvent && bindgetuserinfo) {
|
|
298
|
+
Promise.resolve(handleEvent)
|
|
299
|
+
.then((userInfo) => {
|
|
300
|
+
if (typeof userInfo === 'object') {
|
|
301
|
+
bindgetuserinfo(userInfo)
|
|
302
|
+
}
|
|
303
|
+
})
|
|
294
304
|
}
|
|
295
305
|
}
|
|
296
306
|
|
|
@@ -322,32 +332,41 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
322
332
|
setStayTimer()
|
|
323
333
|
}
|
|
324
334
|
|
|
335
|
+
const handleFormTypeFn = () => {
|
|
336
|
+
if (formType === 'submit') {
|
|
337
|
+
submitFn && submitFn()
|
|
338
|
+
} else if (formType === 'reset') {
|
|
339
|
+
resetFn && resetFn()
|
|
340
|
+
}
|
|
341
|
+
}
|
|
325
342
|
const onTap = (evt: NativeSyntheticEvent<TouchEvent>) => {
|
|
326
343
|
if (disabled) return
|
|
327
344
|
bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props))
|
|
328
345
|
handleOpenTypeEvent(evt)
|
|
346
|
+
handleFormTypeFn()
|
|
329
347
|
}
|
|
330
348
|
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
349
|
+
function wrapChildren(children: ReactNode, defaultTextStyle: Record<string, any>, textStyle: Record<string, any>) {
|
|
350
|
+
if (!children) return children
|
|
351
|
+
const hasTextStyle = !isEmptyObject(textStyle)
|
|
352
|
+
const { textProps } = splitProps(props)
|
|
335
353
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
children =
|
|
354
|
+
if (every(children, (child) => isText(child))) {
|
|
355
|
+
transformTextStyle(textStyle as TextStyle)
|
|
356
|
+
children = <Text key='buttonTextWrap' style={{ ...defaultTextStyle, ...textStyle }} {...(textProps || {})}>{children}</Text>
|
|
339
357
|
} else {
|
|
340
|
-
if(
|
|
358
|
+
if (hasTextStyle) throwReactWarning('[Mpx runtime warn]: Text style will be ignored unless every child of the Button is Text node!')
|
|
341
359
|
}
|
|
342
|
-
|
|
360
|
+
|
|
343
361
|
return children
|
|
344
362
|
}
|
|
345
363
|
|
|
346
364
|
const { nodeRef } = useNodesRef(props, ref, {
|
|
347
|
-
defaultStyle:
|
|
365
|
+
defaultStyle: {
|
|
348
366
|
...defaultViewStyle,
|
|
349
367
|
...defaultTextStyle,
|
|
350
|
-
|
|
368
|
+
...textStyle
|
|
369
|
+
}
|
|
351
370
|
})
|
|
352
371
|
|
|
353
372
|
const onLayout = () => {
|
|
@@ -363,33 +382,34 @@ const Button = forwardRef<HandlerRef< View, ButtonProps>,ButtonProps >((props, r
|
|
|
363
382
|
bindtouchstart: onTouchStart,
|
|
364
383
|
bindtouchend: onTouchEnd,
|
|
365
384
|
bindtap: onTap,
|
|
366
|
-
catchtap: catchTap,
|
|
367
385
|
...(enableOffset ? { onLayout } : {}),
|
|
368
386
|
},
|
|
369
387
|
[
|
|
370
388
|
'enable-offset'
|
|
371
389
|
],
|
|
372
|
-
{
|
|
373
|
-
layoutRef
|
|
390
|
+
{
|
|
391
|
+
layoutRef,
|
|
392
|
+
disableTap: disabled
|
|
374
393
|
}
|
|
375
394
|
);
|
|
376
395
|
|
|
377
396
|
return (
|
|
378
397
|
<View
|
|
379
398
|
{...innerProps}
|
|
380
|
-
style={
|
|
399
|
+
style={{
|
|
381
400
|
...defaultViewStyle,
|
|
382
|
-
|
|
383
|
-
applyHoverEffect &&
|
|
384
|
-
|
|
401
|
+
...innerStyle,
|
|
402
|
+
...(applyHoverEffect && hoverInnerStyle),
|
|
403
|
+
} as ViewStyle}>
|
|
385
404
|
{loading && <Loading alone={!children} />}
|
|
386
405
|
{
|
|
387
406
|
wrapChildren(
|
|
388
|
-
children,
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
407
|
+
children,
|
|
408
|
+
defaultTextStyle,
|
|
409
|
+
{
|
|
410
|
+
...textStyle,
|
|
411
|
+
...(applyHoverEffect && hoverTextStyle),
|
|
412
|
+
}
|
|
393
413
|
)
|
|
394
414
|
}
|
|
395
415
|
</View>
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ✔ bindchange
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
JSX,
|
|
6
|
+
useRef,
|
|
7
|
+
forwardRef,
|
|
8
|
+
ReactNode,
|
|
9
|
+
useContext
|
|
10
|
+
} from 'react'
|
|
11
|
+
import {
|
|
12
|
+
View,
|
|
13
|
+
NativeSyntheticEvent,
|
|
14
|
+
ViewStyle
|
|
15
|
+
} from 'react-native'
|
|
16
|
+
import { FormContext, FormFieldValue, CheckboxGroupContext, GroupValue } from './context'
|
|
17
|
+
import useInnerProps, { getCustomEvent } from './getInnerListeners'
|
|
18
|
+
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
19
|
+
import { throwReactWarning } from './utils'
|
|
20
|
+
|
|
21
|
+
export interface CheckboxGroupProps {
|
|
22
|
+
name: string
|
|
23
|
+
style?: ViewStyle & Record<string, any>
|
|
24
|
+
'enable-offset'?: boolean
|
|
25
|
+
children: ReactNode
|
|
26
|
+
bindchange?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const CheckboxGroup = forwardRef<
|
|
30
|
+
HandlerRef<View, CheckboxGroupProps>,
|
|
31
|
+
CheckboxGroupProps
|
|
32
|
+
>((props, ref): JSX.Element => {
|
|
33
|
+
const {
|
|
34
|
+
style = {},
|
|
35
|
+
'enable-offset': enableOffset,
|
|
36
|
+
children,
|
|
37
|
+
bindchange
|
|
38
|
+
} = props
|
|
39
|
+
|
|
40
|
+
const layoutRef = useRef({})
|
|
41
|
+
const formContext = useContext(FormContext)
|
|
42
|
+
|
|
43
|
+
let formValuesMap: Map<string, FormFieldValue> | undefined;
|
|
44
|
+
|
|
45
|
+
if (formContext) {
|
|
46
|
+
formValuesMap = formContext.formValuesMap
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const groupValue: GroupValue = useRef({}).current
|
|
50
|
+
|
|
51
|
+
const defaultStyle = {
|
|
52
|
+
flexDirection: 'row',
|
|
53
|
+
flexWrap: 'wrap',
|
|
54
|
+
...style
|
|
55
|
+
}
|
|
56
|
+
const { nodeRef } = useNodesRef(props, ref, {
|
|
57
|
+
defaultStyle
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const onLayout = () => {
|
|
61
|
+
nodeRef.current?.measure(
|
|
62
|
+
(
|
|
63
|
+
x: number,
|
|
64
|
+
y: number,
|
|
65
|
+
width: number,
|
|
66
|
+
height: number,
|
|
67
|
+
offsetLeft: number,
|
|
68
|
+
offsetTop: number
|
|
69
|
+
) => {
|
|
70
|
+
layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const getSelectionValue = (): string[] => {
|
|
76
|
+
const arr: string[] = []
|
|
77
|
+
for (let key in groupValue) {
|
|
78
|
+
if (groupValue[key].checked) {
|
|
79
|
+
arr.push(key)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return arr
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const getValue = () => {
|
|
86
|
+
return getSelectionValue()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const resetValue = () => {
|
|
90
|
+
Object.keys(groupValue).forEach((key) => {
|
|
91
|
+
groupValue[key].checked = false
|
|
92
|
+
groupValue[key].setValue(false)
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (formValuesMap) {
|
|
97
|
+
if (!props.name) {
|
|
98
|
+
throwReactWarning('[Mpx runtime warn]: If a form component is used, the name attribute is required.')
|
|
99
|
+
} else {
|
|
100
|
+
formValuesMap.set(props.name, { getValue, resetValue })
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const notifyChange = (
|
|
105
|
+
evt: NativeSyntheticEvent<TouchEvent>
|
|
106
|
+
) => {
|
|
107
|
+
bindchange &&
|
|
108
|
+
bindchange(
|
|
109
|
+
getCustomEvent(
|
|
110
|
+
'tap',
|
|
111
|
+
evt,
|
|
112
|
+
{
|
|
113
|
+
layoutRef,
|
|
114
|
+
detail: {
|
|
115
|
+
value: getSelectionValue()
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
props
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const innerProps = useInnerProps(
|
|
124
|
+
props,
|
|
125
|
+
{
|
|
126
|
+
ref: nodeRef,
|
|
127
|
+
style: defaultStyle,
|
|
128
|
+
...(enableOffset ? { onLayout } : {})
|
|
129
|
+
},
|
|
130
|
+
['enable-offset'],
|
|
131
|
+
{
|
|
132
|
+
layoutRef
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<View {...innerProps}>
|
|
138
|
+
<CheckboxGroupContext.Provider value={{ groupValue, notifyChange }}>
|
|
139
|
+
{children}
|
|
140
|
+
</CheckboxGroupContext.Provider>
|
|
141
|
+
</View>
|
|
142
|
+
)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
CheckboxGroup.displayName = 'mpx-checkbox-group'
|
|
146
|
+
|
|
147
|
+
export default CheckboxGroup
|