@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,76 @@
1
+ /**
2
+ * 普通选择器,range可以是Array<Obj> 也可以是Array
3
+ */
4
+ import { View, TouchableWithoutFeedback } from 'react-native';
5
+ import React, { forwardRef, useState, useRef, useEffect } from 'react';
6
+ import { Picker } from '@ant-design/react-native';
7
+ import useNodesRef from '../useNodesRef'; // 引入辅助函数
8
+ const formatRangeFun = (range, rangeKey = '') => {
9
+ let newRange = [];
10
+ newRange = (range || []).map((item, index) => {
11
+ if (typeof item === 'object') {
12
+ return { value: index, label: item[rangeKey] };
13
+ }
14
+ else {
15
+ return { value: index, label: item };
16
+ }
17
+ });
18
+ return newRange;
19
+ };
20
+ const _SelectorPicker = forwardRef((props, ref) => {
21
+ const { range, children, value, disabled, bindchange, bindcancel } = props;
22
+ // 格式化数据为Array<*>
23
+ const formatRange = formatRangeFun(range, props['range-key']);
24
+ // 选中的索引值
25
+ const [selected, setSelected] = useState(value || 0);
26
+ // range数据源
27
+ const [data, setData] = useState(formatRange || []);
28
+ // 存储layout布局信息
29
+ const layoutRef = useRef({});
30
+ const { nodeRef: viewRef } = useNodesRef(props, ref, {});
31
+ useEffect(() => {
32
+ if (range) {
33
+ const newFormatRange = formatRangeFun(range, props['range-key']);
34
+ setData(newFormatRange);
35
+ }
36
+ setSelected(() => {
37
+ return value;
38
+ });
39
+ }, [range, value]);
40
+ const defaultValue = [value];
41
+ const onChange = (value) => {
42
+ bindchange && bindchange({
43
+ detail: {
44
+ value: value && value[0]
45
+ }
46
+ });
47
+ };
48
+ const onElementLayout = (layout) => {
49
+ viewRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
50
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
51
+ props.getInnerLayout && props.getInnerLayout(layoutRef);
52
+ });
53
+ };
54
+ const antPickerProps = {
55
+ data,
56
+ value: [selected],
57
+ cols: 1,
58
+ defaultValue,
59
+ itemHeight: 40,
60
+ onChange,
61
+ onDismiss: bindcancel && bindcancel
62
+ };
63
+ const touchProps = {
64
+ onLayout: onElementLayout,
65
+ ref: viewRef
66
+ };
67
+ return (<Picker {...antPickerProps}>
68
+ <TouchableWithoutFeedback>
69
+ <View {...touchProps}>
70
+ {children}
71
+ </View>
72
+ </TouchableWithoutFeedback>
73
+ </Picker>);
74
+ });
75
+ _SelectorPicker.displayName = 'mpx-picker-selector';
76
+ export default _SelectorPicker;
@@ -0,0 +1,244 @@
1
+ import { View, Text, Modal, TouchableWithoutFeedback } from 'react-native';
2
+ import { PickerView } from '@ant-design/react-native';
3
+ import React, { forwardRef, useState, useRef, useEffect } from 'react';
4
+ import useNodesRef from '../useNodesRef'; // 引入辅助函数
5
+ // 可见应用窗口的大小。
6
+ // const { height: dHeight, width: dWidth } = Dimensions.get('window');
7
+ // modal属性: {"height": 298.33331298828125, "offsetLeft": 0, "offsetTop": 513.6666870117188, "width": 375, "x": 0, "y": 513.6666870117188}
8
+ // const { height: sHeight, width: sWidth } = Dimensions.get('screen');
9
+ // 设备屏幕的大小。 screen
10
+ const styles = {
11
+ showModal: {
12
+ backgroundColor: 'black',
13
+ opacity: 0.5,
14
+ position: 'absolute',
15
+ width: '100%'
16
+ },
17
+ hideModal: {
18
+ opacity: 1,
19
+ height: 0
20
+ },
21
+ modal: {
22
+ backgroundColor: 'black',
23
+ opacity: 0.5
24
+ },
25
+ centeredView: {
26
+ position: 'absolute',
27
+ bottom: 0,
28
+ width: '100%',
29
+ overflow: 'scroll'
30
+ },
31
+ btnLine: {
32
+ width: '100%',
33
+ flex: 1,
34
+ flexDirection: 'row',
35
+ justifyContent: 'space-between',
36
+ borderColor: 20,
37
+ borderBottomWidth: 1,
38
+ backgroundColor: 'white',
39
+ paddingLeft: 40,
40
+ paddingRight: 40
41
+ },
42
+ cancel: {
43
+ height: 50,
44
+ display: 'flex',
45
+ justifyContent: 'center'
46
+ },
47
+ ok: {
48
+ height: 50,
49
+ display: 'flex',
50
+ justifyContent: 'center'
51
+ },
52
+ btntext: {
53
+ color: '#0ae',
54
+ fontSize: 18
55
+ }
56
+ };
57
+ function formatStrToInt(timestr) {
58
+ const [start, end] = timestr.split(':');
59
+ return [parseInt(start), parseInt(end)];
60
+ }
61
+ // [9, 59] to 09:59
62
+ function formatStr(arr) {
63
+ let [hour, minute] = arr;
64
+ if (hour < 10) {
65
+ hour = '0' + hour;
66
+ }
67
+ if (minute < 10) {
68
+ minute = '0' + minute;
69
+ }
70
+ return hour + ':' + minute;
71
+ }
72
+ function generateMinute() {
73
+ const arrMinute = [];
74
+ for (let i = 0; i <= 59; i++) {
75
+ const obj = {
76
+ label: toSingleStr(i),
77
+ value: i,
78
+ children: []
79
+ };
80
+ arrMinute.push(obj);
81
+ }
82
+ return arrMinute;
83
+ }
84
+ function generateColumns() {
85
+ const pickData = [];
86
+ for (let i = 0; i <= 23; i++) {
87
+ const obj = {
88
+ label: toSingleStr(i),
89
+ value: i,
90
+ children: generateMinute()
91
+ };
92
+ pickData.push(obj);
93
+ }
94
+ return pickData;
95
+ }
96
+ function toSingleStr(str) {
97
+ return str < 10 ? '0' + str : str;
98
+ }
99
+ function toStr(time) {
100
+ const [hour, minute] = formatStrToInt(time);
101
+ const newHour = toSingleStr(hour);
102
+ const newMinute = toSingleStr(minute);
103
+ return '' + newHour + newMinute;
104
+ }
105
+ function checkSelectedIsValid(strStart, strEnd, selected) {
106
+ const strSel = '' + toSingleStr(selected[0]) + toSingleStr(selected[1]);
107
+ if (strSel < strStart || strSel > strEnd)
108
+ return false;
109
+ return true;
110
+ }
111
+ /**
112
+ * [{label:'', value: '', key: '', children: []}]
113
+ label: string | ReactNode
114
+ value: string | number
115
+ key?: string | number
116
+ children?: PickerColumnItem[]
117
+ */
118
+ // start="02:10" end = 23:01
119
+ const _TimePicker = forwardRef((props, ref) => {
120
+ const { children, start, end, value, bindchange, bindcancel, disabled } = props;
121
+ const defaultProps = {
122
+ start: '00:10',
123
+ end: '23:59'
124
+ };
125
+ const defaultValue = formatStrToInt(value);
126
+ const [timevalue, setTimeValue] = useState(defaultValue);
127
+ // 存储layout布局信息
128
+ const layoutRef = useRef({});
129
+ const { nodeRef: viewRef } = useNodesRef(props, ref, {});
130
+ // 存储modal的布局信息
131
+ const modalLayoutRef = useRef({});
132
+ const { nodeRef: modalRef } = useNodesRef(props, ref, {});
133
+ const [visible, setVisible] = useState(false);
134
+ const columnData = generateColumns();
135
+ const [data, setData] = useState(columnData);
136
+ const [offsetTop, setOffsetTop] = useState(0);
137
+ const strStart = toStr(start);
138
+ const strEnd = toStr(end);
139
+ useEffect(() => {
140
+ const newColumnData = generateColumns();
141
+ setData(newColumnData);
142
+ }, [start, end]);
143
+ useEffect(() => {
144
+ if (value) {
145
+ const nValue = formatStrToInt(value);
146
+ nValue && setTimeValue(nValue);
147
+ }
148
+ }, [value]);
149
+ // console.log('---------------visible---', visible, JSON.stringify(columnData))
150
+ const handleModalStatus = (status) => {
151
+ setVisible(status);
152
+ };
153
+ const handleConfirm = () => {
154
+ handleModalStatus(false);
155
+ bindchange && bindchange({
156
+ detail: {
157
+ value: formatStr(timevalue)
158
+ }
159
+ });
160
+ };
161
+ const handleCancel = () => {
162
+ handleModalStatus(false);
163
+ bindcancel && bindcancel();
164
+ };
165
+ const handleChildClick = () => {
166
+ handleModalStatus(true);
167
+ };
168
+ const handlePickChange = (date) => {
169
+ // 不是有效的值
170
+ if (!checkSelectedIsValid(strStart, strEnd, date)) {
171
+ setTimeValue(timevalue);
172
+ }
173
+ else {
174
+ // [9, 13]
175
+ setTimeValue(date);
176
+ const strDate = formatStr(date);
177
+ bindchange && bindchange({
178
+ detail: {
179
+ value: strDate
180
+ }
181
+ });
182
+ }
183
+ };
184
+ const onElementLayout = () => {
185
+ viewRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
186
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
187
+ props.getInnerLayout && props.getInnerLayout(layoutRef);
188
+ });
189
+ };
190
+ const onModalLayout = () => {
191
+ modalRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
192
+ modalLayoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
193
+ setOffsetTop(offsetTop);
194
+ });
195
+ };
196
+ const renderModalChildren = () => {
197
+ const pickerProps = {
198
+ data,
199
+ value: timevalue,
200
+ defaultValue: timevalue,
201
+ cols: 2,
202
+ onChange: handlePickChange
203
+ };
204
+ return (<View style={styles.centeredView} ref={modalRef} onLayout={onModalLayout}>
205
+ <View style={styles.btnLine}>
206
+ <View style={styles.cancel}>
207
+ <TouchableWithoutFeedback onPress={handleCancel}>
208
+ <Text style={styles.btntext}>取消</Text>
209
+ </TouchableWithoutFeedback>
210
+ </View>
211
+ <View style={styles.ok}>
212
+ <TouchableWithoutFeedback onPress={handleConfirm}>
213
+ <Text style={styles.btntext}>确定</Text>
214
+ </TouchableWithoutFeedback>
215
+ </View>
216
+ </View>
217
+ <PickerView {...pickerProps}></PickerView>
218
+ </View>);
219
+ };
220
+ const renderChildren = () => {
221
+ const touchProps = {
222
+ onLayout: onElementLayout,
223
+ ref: viewRef
224
+ };
225
+ return <View>
226
+ <TouchableWithoutFeedback onPress={handleChildClick}>
227
+ <View {...touchProps}>{children}</View>
228
+ </TouchableWithoutFeedback>
229
+ </View>;
230
+ };
231
+ const strStyle = visible ? styles.showModal : styles.hideModal;
232
+ const mheight = Math.floor(offsetTop);
233
+ // Animated.View
234
+ return (<>
235
+ <View style={{ ...strStyle, height: visible ? mheight : 0, bottom: 0 }}>
236
+ <Modal animationType="slide" transparent={true} visible={visible}>
237
+ {renderModalChildren()}
238
+ </Modal>
239
+ </View>
240
+ {renderChildren()}
241
+ </>);
242
+ });
243
+ _TimePicker.displayName = 'mpx-picker-time';
244
+ export default _TimePicker;
@@ -0,0 +1,107 @@
1
+ import { View, Animated, SafeAreaView } from 'react-native';
2
+ import React, { forwardRef, useState, useEffect } from 'react';
3
+ import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils';
4
+ import useNodesRef from './useNodesRef'; // 引入辅助函数
5
+ const defaultItemHeight = 36;
6
+ // 每个Column 都有个外层的高度, 内部的元素高度
7
+ // 默认的高度
8
+ const _PickerViewColumn = forwardRef((props, ref) => {
9
+ const { children, selectedIndex, onColumnLayoutChange, onSelectChange, getInnerLayout, style, wrapperStyle, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
10
+ // PickerViewColumn
11
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
12
+ const { textStyle } = splitStyle(normalStyle);
13
+ const { textProps } = splitProps(props);
14
+ // const { innerStyle } = splitStyle(normalStyle)
15
+ // scrollView的ref
16
+ const { nodeRef: scrollViewRef } = useNodesRef(props, ref, {});
17
+ // 每个元素的高度
18
+ let [itemH, setItemH] = useState(0);
19
+ useEffect(() => {
20
+ if (selectedIndex && itemH) {
21
+ const offsetY = selectedIndex * itemH;
22
+ scrollViewRef.current?.scrollTo({ x: 0, y: offsetY, animated: true });
23
+ }
24
+ }, [selectedIndex, itemH]);
25
+ const onScrollViewLayout = () => {
26
+ getInnerLayout && getInnerLayout(layoutRef);
27
+ };
28
+ const {
29
+ // 存储layout布局信息
30
+ layoutRef, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout: onScrollViewLayout });
31
+ const onItemLayout = (e) => {
32
+ const layout = e.nativeEvent.layout;
33
+ if (layout.height && itemH !== layout.height) {
34
+ itemH = layout.height;
35
+ setItemH(layout.height);
36
+ onColumnLayoutChange && onColumnLayoutChange({ height: layout.height * 5 });
37
+ }
38
+ };
39
+ const onMomentumScrollEnd = (e) => {
40
+ if (scrollViewRef && itemH) {
41
+ const { y: scrollY } = e.nativeEvent.contentOffset;
42
+ const selIndex = Math.floor(scrollY / itemH);
43
+ onSelectChange(selIndex);
44
+ }
45
+ };
46
+ const renderInnerchild = () => {
47
+ // Fragment 节点
48
+ let realElement = [];
49
+ const getRealChilds = () => {
50
+ if (Array.isArray(children)) {
51
+ realElement = children;
52
+ }
53
+ else {
54
+ const tempChild = children;
55
+ if (tempChild.props.children && tempChild.props.children) {
56
+ realElement = tempChild.props.children;
57
+ }
58
+ else {
59
+ realElement = [children];
60
+ }
61
+ }
62
+ return realElement;
63
+ };
64
+ const realChilds = getRealChilds();
65
+ const arrChild = realChilds.map((item, index) => {
66
+ const InnerProps = index === 0 ? { onLayout: onItemLayout } : {};
67
+ const strKey = 'picker' + props.prefix + '-column' + index;
68
+ const arrHeight = (wrapperStyle.itemHeight + '').match(/\d+/g) || [];
69
+ const iHeight = (arrHeight[0] || defaultItemHeight);
70
+ return <View key={strKey} {...InnerProps} style={[{ height: iHeight, width: '100%' }]}>
71
+ {wrapChildren({
72
+ children: item
73
+ }, {
74
+ hasVarDec,
75
+ varContext: varContextRef.current,
76
+ textStyle,
77
+ textProps
78
+ })}
79
+ </View>;
80
+ });
81
+ const totalHeight = itemH * 5;
82
+ if (wrapperStyle.height && totalHeight !== wrapperStyle.height) {
83
+ const fix = Math.ceil((totalHeight - wrapperStyle.height) / 2);
84
+ arrChild.unshift(<View key="picker-column-0" style={[{ height: itemH - fix }]}></View>);
85
+ arrChild.unshift(<View key="picker-column-1" style={[{ height: itemH }]}></View>);
86
+ arrChild.push(<View key="picker-column-2" style={[{ height: itemH }]}></View>);
87
+ arrChild.push(<View key="picker-column-3" style={[{ height: itemH - fix }]}></View>);
88
+ }
89
+ else {
90
+ arrChild.unshift(<View key="picker-column-0" style={[{ height: itemH }]}></View>);
91
+ arrChild.unshift(<View key="picker-column-1" style={[{ height: itemH }]}></View>);
92
+ arrChild.push(<View key="picker-column-2" style={[{ height: itemH }]}></View>);
93
+ arrChild.push(<View key="picker-column-3" style={[{ height: itemH }]}></View>);
94
+ }
95
+ return arrChild;
96
+ };
97
+ const renderScollView = () => {
98
+ return (<Animated.ScrollView horizontal={false} ref={scrollViewRef} bounces={false} scrollsToTop={false} removeClippedSubviews={true} showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false} pagingEnabled={false} snapToInterval={itemH} automaticallyAdjustContentInsets={false} {...layoutProps} onMomentumScrollEnd={onMomentumScrollEnd}>
99
+ {renderInnerchild()}
100
+ </Animated.ScrollView>);
101
+ };
102
+ return (<SafeAreaView style={[{ display: 'flex', flex: 1 }]}>
103
+ {renderScollView()}
104
+ </SafeAreaView>);
105
+ });
106
+ _PickerViewColumn.displayName = 'mpx-picker-view-column';
107
+ export default _PickerViewColumn;
@@ -0,0 +1,162 @@
1
+ import { View } from 'react-native';
2
+ import { LinearGradient } from 'react-native-linear-gradient';
3
+ import React, { forwardRef, useState, useRef } from 'react';
4
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
5
+ import useNodesRef from './useNodesRef'; // 引入辅助函数
6
+ import { parseInlineStyle, useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from './utils';
7
+ const styles = {
8
+ wrapper: {
9
+ display: 'flex',
10
+ flex: 1,
11
+ flexDirection: 'row',
12
+ justifyContent: 'space-around',
13
+ overflow: 'hidden',
14
+ alignItems: 'center'
15
+ },
16
+ maskTop: {
17
+ position: 'absolute',
18
+ width: 1000,
19
+ zIndex: 100
20
+ },
21
+ maskBottom: {
22
+ position: 'absolute',
23
+ width: 1000,
24
+ zIndex: 100
25
+ }
26
+ };
27
+ const _PickerView = forwardRef((props, ref) => {
28
+ const { children, value = [], bindchange, style, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
29
+ // indicatorStyle 需要转换为rn的style
30
+ // 微信设置到pick-view上上设置的normalStyle如border等需要转换成RN的style然后进行透传
31
+ const indicatorStyle = parseInlineStyle(props['indicator-style']);
32
+ const { height: indicatorH, width: indicatorW } = indicatorStyle;
33
+ const { nodeRef } = useNodesRef(props, ref, {});
34
+ // picker-view 设置的color等textStyle,在小程序上的表现是可以继承到最内层的text样式, 但是RN内部column是slot无法设置, 需要业务自己在column内的元素上设置
35
+ const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
36
+ const { textStyle } = splitStyle(normalStyle);
37
+ const { textProps } = splitProps(props);
38
+ const {
39
+ // 存储layout布局信息
40
+ layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef });
41
+ const isSetW = indicatorW !== undefined ? 1 : 0;
42
+ const cloneRef = useRef(null);
43
+ const maskPos = {};
44
+ let [pickH, setPickH] = useState(0);
45
+ const itemH = pickH / 5;
46
+ if (normalStyle?.height && pickH && pickH !== normalStyle?.height) {
47
+ maskPos.height = itemH * 2 + Math.ceil((normalStyle.height - pickH) / 2);
48
+ }
49
+ else {
50
+ maskPos.height = itemH * 2;
51
+ }
52
+ const onColumnLayoutChange = (layoutConfig) => {
53
+ pickH = layoutConfig.height;
54
+ setPickH(layoutConfig.height);
55
+ };
56
+ const onSelectChange = (columnIndex, selIndex) => {
57
+ const changeValue = value.slice();
58
+ changeValue[columnIndex] = selIndex;
59
+ const eventData = getCustomEvent('change', {}, { detail: { value: changeValue, source: 'change' }, layoutRef });
60
+ bindchange && bindchange(eventData);
61
+ };
62
+ const innerProps = useInnerProps(props, {
63
+ ref: nodeRef,
64
+ style: {
65
+ ...normalStyle,
66
+ ...layoutStyle,
67
+ position: 'relative',
68
+ overflow: 'hidden'
69
+ },
70
+ ...layoutProps
71
+ }, [
72
+ 'enable-offset'
73
+ ], { layoutRef });
74
+ const cloneChild = (child, index) => {
75
+ // const extraProps = index === 0 ? { getInnerLayout: getInnerLayout, innerProps } : {}
76
+ const extraProps = {};
77
+ const childProps = {
78
+ ...child?.props,
79
+ ref: cloneRef,
80
+ prefix: index,
81
+ key: 'pick-view' + index,
82
+ wrapperStyle: {
83
+ height: normalStyle?.height || 0,
84
+ itemHeight: indicatorH || 0
85
+ },
86
+ onColumnLayoutChange,
87
+ onSelectChange: onSelectChange.bind(null, index),
88
+ selectedIndex: value?.[index] || 0,
89
+ ...extraProps
90
+ };
91
+ const realElement = React.cloneElement(child, childProps);
92
+ return wrapChildren({
93
+ children: realElement
94
+ }, {
95
+ hasVarDec,
96
+ varContext: varContextRef.current,
97
+ textStyle,
98
+ textProps
99
+ });
100
+ };
101
+ const renderTopMask = () => {
102
+ const linearProps = {
103
+ colors: ['rgba(255,255,255,0.8)', 'rgba(255,255,255,0.2)'],
104
+ style: [
105
+ styles.maskTop,
106
+ {
107
+ height: maskPos.height,
108
+ top: 0,
109
+ pointerEvents: 'none'
110
+ }
111
+ ]
112
+ };
113
+ return (<LinearGradient {...linearProps}/>);
114
+ };
115
+ const renderBottomMask = () => {
116
+ const linearProps = {
117
+ colors: ['rgba(255,255,255,0.2)', 'rgba(255,255,255,0.8)'],
118
+ style: [
119
+ styles.maskBottom,
120
+ {
121
+ height: maskPos.height,
122
+ bottom: 0,
123
+ pointerEvents: 'none'
124
+ }
125
+ ]
126
+ };
127
+ return <LinearGradient {...linearProps}></LinearGradient>;
128
+ };
129
+ const renderLine = () => {
130
+ return <View style={[{
131
+ position: 'absolute',
132
+ top: '50%',
133
+ transform: [{ translateY: -(itemH / 2) }],
134
+ height: itemH,
135
+ borderTopWidth: 1,
136
+ borderBottomWidth: 1,
137
+ borderColor: '#f0f0f0',
138
+ width: '100%',
139
+ zIndex: 101
140
+ }]}></View>;
141
+ };
142
+ const renderSubChild = () => {
143
+ if (Array.isArray(children)) {
144
+ return children.map((item, index) => {
145
+ return cloneChild(item, index);
146
+ });
147
+ }
148
+ else {
149
+ return cloneChild(children, 0);
150
+ }
151
+ };
152
+ return (<View {...innerProps}>
153
+ {renderTopMask()}
154
+ <View style={[styles.wrapper]}>
155
+ {renderSubChild()}
156
+ </View>
157
+ {renderBottomMask()}
158
+ {!isSetW && renderLine()}
159
+ </View>);
160
+ });
161
+ _PickerView.displayName = 'mpx-picker-view';
162
+ export default _PickerView;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * ✔ bindchange
3
+ */
4
+ import { useRef, forwardRef, useContext } from 'react';
5
+ import { View } from 'react-native';
6
+ import { warn } from '@mpxjs/utils';
7
+ import { FormContext, RadioGroupContext } from './context';
8
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
+ import useNodesRef from './useNodesRef';
10
+ import { useLayout, useTransformStyle, wrapChildren } from './utils';
11
+ const radioGroup = forwardRef((props, ref) => {
12
+ const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, bindchange } = props;
13
+ const formContext = useContext(FormContext);
14
+ let formValuesMap;
15
+ if (formContext) {
16
+ formValuesMap = formContext.formValuesMap;
17
+ }
18
+ const groupValue = useRef({}).current;
19
+ const defaultStyle = {
20
+ flexDirection: 'row',
21
+ flexWrap: 'wrap'
22
+ };
23
+ const styleObj = {
24
+ ...defaultStyle,
25
+ ...style
26
+ };
27
+ const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
28
+ const { nodeRef } = useNodesRef(props, ref, { defaultStyle });
29
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
30
+ const getSelectionValue = () => {
31
+ for (const key in groupValue) {
32
+ if (groupValue[key].checked) {
33
+ return key;
34
+ }
35
+ }
36
+ };
37
+ const getValue = () => {
38
+ return getSelectionValue();
39
+ };
40
+ const resetValue = () => {
41
+ Object.keys(groupValue).forEach((key) => {
42
+ groupValue[key].checked = false;
43
+ groupValue[key].setValue(false);
44
+ });
45
+ };
46
+ if (formValuesMap) {
47
+ if (!props.name) {
48
+ warn('If a form component is used, the name attribute is required.');
49
+ }
50
+ else {
51
+ formValuesMap.set(props.name, { getValue, resetValue });
52
+ }
53
+ }
54
+ const notifyChange = (evt) => {
55
+ bindchange &&
56
+ bindchange(getCustomEvent('tap', evt, {
57
+ layoutRef,
58
+ detail: {
59
+ value: getSelectionValue()
60
+ }
61
+ }, props));
62
+ };
63
+ const innerProps = useInnerProps(props, {
64
+ ref: nodeRef,
65
+ style: { ...normalStyle, ...layoutStyle },
66
+ ...layoutProps
67
+ }, [], {
68
+ layoutRef
69
+ });
70
+ return (<View {...innerProps}>
71
+ <RadioGroupContext.Provider value={{ groupValue, notifyChange }}>
72
+ {wrapChildren(props, {
73
+ hasVarDec,
74
+ varContext: varContextRef.current
75
+ })}
76
+ </RadioGroupContext.Provider>
77
+ </View>);
78
+ });
79
+ radioGroup.displayName = 'mpx-radio-group';
80
+ export default radioGroup;