@mpxjs/webpack-plugin 2.9.62 → 2.9.65
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/config.js +38 -10
- package/lib/index.js +1 -3
- package/lib/platform/style/wx/index.js +115 -66
- package/lib/platform/template/wx/index.js +12 -8
- package/lib/react/processStyles.js +1 -0
- package/lib/react/processTemplate.js +2 -3
- package/lib/react/style-helper.js +9 -7
- package/lib/runtime/components/react/context.ts +9 -7
- package/lib/runtime/components/react/dist/context.js +1 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +12 -1
- package/lib/runtime/components/react/dist/mpx-button.jsx +53 -74
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +20 -18
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +30 -42
- package/lib/runtime/components/react/dist/mpx-form.jsx +18 -15
- package/lib/runtime/components/react/dist/mpx-icon.jsx +15 -17
- package/lib/runtime/components/react/dist/mpx-image/index.jsx +36 -34
- package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +36 -31
- package/lib/runtime/components/react/dist/mpx-label.jsx +30 -37
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +15 -19
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +10 -9
- package/lib/runtime/components/react/dist/mpx-picker/date.jsx +2 -1
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +11 -10
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +9 -5
- package/lib/runtime/components/react/dist/mpx-picker/region.jsx +13 -8
- package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +22 -20
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +103 -10
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +149 -54
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +20 -18
- package/lib/runtime/components/react/dist/mpx-radio.jsx +29 -43
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +8 -4
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +36 -27
- package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +141 -75
- package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +16 -7
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +20 -11
- package/lib/runtime/components/react/dist/mpx-switch.jsx +18 -14
- package/lib/runtime/components/react/dist/mpx-text.jsx +20 -35
- package/lib/runtime/components/react/dist/mpx-textarea.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-view.jsx +296 -210
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +11 -7
- package/lib/runtime/components/react/dist/parser.js +218 -0
- package/lib/runtime/components/react/dist/useNodesRef.js +1 -5
- package/lib/runtime/components/react/dist/utils.jsx +445 -0
- package/lib/runtime/components/react/getInnerListeners.ts +18 -8
- package/lib/runtime/components/react/mpx-button.tsx +83 -91
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +50 -43
- package/lib/runtime/components/react/mpx-checkbox.tsx +56 -64
- package/lib/runtime/components/react/mpx-form.tsx +51 -22
- package/lib/runtime/components/react/mpx-icon.tsx +31 -27
- package/lib/runtime/components/react/mpx-image/index.tsx +54 -47
- package/lib/runtime/components/react/mpx-image/svg.tsx +5 -3
- package/lib/runtime/components/react/mpx-input.tsx +59 -38
- package/lib/runtime/components/react/mpx-label.tsx +55 -59
- package/lib/runtime/components/react/mpx-movable-area.tsx +40 -25
- package/lib/runtime/components/react/mpx-movable-view.tsx +29 -29
- package/lib/runtime/components/react/mpx-navigator.tsx +2 -2
- package/lib/runtime/components/react/mpx-picker/date.tsx +4 -4
- package/lib/runtime/components/react/mpx-picker/index.tsx +12 -11
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +17 -13
- package/lib/runtime/components/react/mpx-picker/region.tsx +23 -19
- package/lib/runtime/components/react/mpx-picker/selector.tsx +7 -7
- package/lib/runtime/components/react/mpx-picker/time.tsx +29 -31
- package/lib/runtime/components/react/mpx-picker/type.ts +1 -1
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +149 -20
- package/lib/runtime/components/react/mpx-picker-view.tsx +180 -63
- package/lib/runtime/components/react/mpx-radio-group.tsx +51 -47
- package/lib/runtime/components/react/mpx-radio.tsx +57 -72
- package/lib/runtime/components/react/mpx-root-portal.tsx +10 -8
- package/lib/runtime/components/react/mpx-scroll-view.tsx +136 -104
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +175 -96
- package/lib/runtime/components/react/mpx-swiper/index.tsx +21 -9
- package/lib/runtime/components/react/mpx-swiper/type.ts +16 -5
- package/lib/runtime/components/react/mpx-swiper-item.tsx +48 -14
- package/lib/runtime/components/react/mpx-switch.tsx +46 -24
- package/lib/runtime/components/react/mpx-text.tsx +38 -45
- package/lib/runtime/components/react/mpx-textarea.tsx +1 -1
- package/lib/runtime/components/react/mpx-view.tsx +401 -241
- package/lib/runtime/components/react/mpx-web-view.tsx +22 -22
- package/lib/runtime/components/react/parser.ts +245 -0
- package/lib/runtime/components/react/types/common.ts +4 -4
- package/lib/runtime/components/react/types/global.d.ts +24 -2
- package/lib/runtime/components/react/useNodesRef.ts +1 -7
- package/lib/runtime/components/react/utils.tsx +524 -0
- package/lib/runtime/components/web/mpx-scroll-view.vue +25 -5
- package/lib/style-compiler/index.js +5 -4
- package/lib/template-compiler/compiler.js +133 -161
- package/lib/template-compiler/gen-node-react.js +1 -3
- package/lib/utils/const.js +2 -1
- package/lib/web/processStyles.js +2 -1
- package/lib/web/processTemplate.js +2 -3
- package/lib/wxml/loader.js +1 -1
- package/package.json +7 -4
- package/lib/runtime/components/react/dist/utils.js +0 -148
- package/lib/runtime/components/react/utils.ts +0 -170
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { View } from 'react-native';
|
|
2
2
|
import React, { forwardRef, useRef, useContext, useState } from 'react';
|
|
3
|
+
import { warn } from '@mpxjs/utils';
|
|
3
4
|
import useInnerProps, { getCustomEvent } from '../getInnerListeners';
|
|
4
5
|
import useNodesRef from '../useNodesRef'; // 引入辅助函数
|
|
5
6
|
import Selector from './selector';
|
|
@@ -8,7 +9,6 @@ import DateSelector from './date';
|
|
|
8
9
|
import MultiSelector from './multiSelector';
|
|
9
10
|
import RegionSelector from './region';
|
|
10
11
|
import { FormContext } from '../context';
|
|
11
|
-
import { throwReactWarning } from '../utils';
|
|
12
12
|
/**
|
|
13
13
|
* ✔ mode
|
|
14
14
|
* ✔ disabled
|
|
@@ -29,8 +29,9 @@ import { throwReactWarning } from '../utils';
|
|
|
29
29
|
*/
|
|
30
30
|
const _Picker = forwardRef((props, ref) => {
|
|
31
31
|
const { mode = 'selector', value, bindcancel, bindchange, children, bindcolumnchange } = props;
|
|
32
|
-
|
|
33
|
-
const
|
|
32
|
+
const innerLayout = useRef({});
|
|
33
|
+
const nodeRef = useRef(null);
|
|
34
|
+
useNodesRef(props, ref, nodeRef, {});
|
|
34
35
|
const innerProps = useInnerProps(props, {
|
|
35
36
|
ref: nodeRef
|
|
36
37
|
}, [], { layoutRef: innerLayout });
|
|
@@ -57,7 +58,7 @@ const _Picker = forwardRef((props, ref) => {
|
|
|
57
58
|
};
|
|
58
59
|
if (formValuesMap) {
|
|
59
60
|
if (!props.name) {
|
|
60
|
-
|
|
61
|
+
warn('If a form component is used, the name attribute is required.');
|
|
61
62
|
}
|
|
62
63
|
else {
|
|
63
64
|
formValuesMap.set(props.name, { getValue, resetValue });
|
|
@@ -88,26 +89,26 @@ const _Picker = forwardRef((props, ref) => {
|
|
|
88
89
|
const selectorProps = {
|
|
89
90
|
...commonProps,
|
|
90
91
|
value: pickerValue,
|
|
91
|
-
range: props
|
|
92
|
+
range: props.range,
|
|
92
93
|
'range-key': props['range-key']
|
|
93
94
|
};
|
|
94
95
|
const multiProps = {
|
|
95
96
|
...commonProps,
|
|
96
97
|
value: pickerValue,
|
|
97
|
-
range: props
|
|
98
|
+
range: props.range,
|
|
98
99
|
'range-key': props['range-key']
|
|
99
100
|
};
|
|
100
101
|
const timeProps = {
|
|
101
102
|
...commonProps,
|
|
102
103
|
value: pickerValue,
|
|
103
|
-
start: props
|
|
104
|
-
end: props
|
|
104
|
+
start: props.start,
|
|
105
|
+
end: props.end
|
|
105
106
|
};
|
|
106
107
|
const dateProps = {
|
|
107
108
|
...commonProps,
|
|
108
109
|
value: pickerValue,
|
|
109
|
-
start: props
|
|
110
|
-
end: props
|
|
110
|
+
start: props.start,
|
|
111
|
+
end: props.end,
|
|
111
112
|
fileds: props.fields || 'day'
|
|
112
113
|
};
|
|
113
114
|
const regionProps = {
|
|
@@ -17,7 +17,7 @@ function formatRangeFun(range = [], rangeKey) {
|
|
|
17
17
|
});
|
|
18
18
|
let tmp = result;
|
|
19
19
|
for (let i = 1; i < range.length; i++) {
|
|
20
|
-
|
|
20
|
+
const child = Array.isArray(range[i]) ? range[i] : [];
|
|
21
21
|
const nextColData = child.map(item => {
|
|
22
22
|
return convertToObj(item, rangeKey);
|
|
23
23
|
});
|
|
@@ -44,7 +44,7 @@ function getIndexByValues(range = [], value = []) {
|
|
|
44
44
|
function getInnerValueByIndex(range = [], value = []) {
|
|
45
45
|
let tmp = range;
|
|
46
46
|
return value.map(v => {
|
|
47
|
-
|
|
47
|
+
const current = tmp[v].value;
|
|
48
48
|
tmp = tmp[v].children;
|
|
49
49
|
return current;
|
|
50
50
|
});
|
|
@@ -60,6 +60,7 @@ function getColumnIndexByValue(range = [], column, value = []) {
|
|
|
60
60
|
if (ritem.value === item) {
|
|
61
61
|
changeIndex = rindex;
|
|
62
62
|
}
|
|
63
|
+
return ritem;
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
66
|
else {
|
|
@@ -67,23 +68,26 @@ function getColumnIndexByValue(range = [], column, value = []) {
|
|
|
67
68
|
if (citem.value === item) {
|
|
68
69
|
tmpRange = citem.children;
|
|
69
70
|
}
|
|
71
|
+
return citem;
|
|
70
72
|
});
|
|
71
73
|
curRange = tmpRange;
|
|
72
74
|
}
|
|
75
|
+
return item;
|
|
73
76
|
});
|
|
74
77
|
return changeIndex;
|
|
75
78
|
}
|
|
76
79
|
const _MultiSelectorPicker = forwardRef((props, ref) => {
|
|
77
80
|
const { range, value, disabled, bindchange, bindcancel, children, bindcolumnchange } = props;
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
const formatRange = formatRangeFun(range, props['range-key']);
|
|
82
|
+
const initValue = getInnerValueByIndex(formatRange, value);
|
|
80
83
|
// 选中的索引值
|
|
81
84
|
const [selected, setSelected] = useState(initValue);
|
|
82
85
|
// range数据源
|
|
83
86
|
const [data, setData] = useState(formatRange || []);
|
|
84
87
|
// 存储layout布局信息
|
|
85
88
|
const layoutRef = useRef({});
|
|
86
|
-
const
|
|
89
|
+
const viewRef = useRef(null);
|
|
90
|
+
useNodesRef(props, ref, viewRef, {});
|
|
87
91
|
useEffect(() => {
|
|
88
92
|
if (range) {
|
|
89
93
|
const newFormatRange = formatRangeFun(range, props['range-key']);
|
|
@@ -5,6 +5,8 @@ import React, { forwardRef, useState, useRef } from 'react';
|
|
|
5
5
|
import useNodesRef from '../useNodesRef'; // 引入辅助函数
|
|
6
6
|
function formateRegionData(clObj = [], customItem, depth = 2) {
|
|
7
7
|
const l = depth;
|
|
8
|
+
// 'PickerData[]' is not assignable to type 'PickerColumn | PickerColumn[]'.
|
|
9
|
+
// const obj: PickerColumnItem[] = []
|
|
8
10
|
const obj = [];
|
|
9
11
|
if (customItem) {
|
|
10
12
|
const objClone = {
|
|
@@ -23,7 +25,7 @@ function formateRegionData(clObj = [], customItem, depth = 2) {
|
|
|
23
25
|
for (let i = 0; i < clObj.length; i++) {
|
|
24
26
|
const region = {
|
|
25
27
|
value: clObj[i].value,
|
|
26
|
-
label: clObj[i].value
|
|
28
|
+
label: clObj[i].value
|
|
27
29
|
};
|
|
28
30
|
if (clObj[i].children) {
|
|
29
31
|
region.children = formateRegionData(clObj[i].children, customItem, l - 1);
|
|
@@ -34,11 +36,12 @@ function formateRegionData(clObj = [], customItem, depth = 2) {
|
|
|
34
36
|
}
|
|
35
37
|
const _RegionPicker = forwardRef((props, ref) => {
|
|
36
38
|
const { children, value, bindchange, bindcancel, disabled } = props;
|
|
37
|
-
|
|
39
|
+
const formatRegionData = formateRegionData(regionData, props['custom-item']);
|
|
38
40
|
const [regionvalue, setRegionValue] = useState(value);
|
|
39
41
|
// 存储layout布局信息
|
|
40
42
|
const layoutRef = useRef({});
|
|
41
|
-
const
|
|
43
|
+
const viewRef = useRef(null);
|
|
44
|
+
useNodesRef(props, ref, viewRef, {});
|
|
42
45
|
const onChange = (value) => {
|
|
43
46
|
// 通过 value 查找 code
|
|
44
47
|
let tmp = regionData;
|
|
@@ -52,6 +55,7 @@ const _RegionPicker = forwardRef((props, ref) => {
|
|
|
52
55
|
return code;
|
|
53
56
|
}
|
|
54
57
|
}
|
|
58
|
+
return item;
|
|
55
59
|
}).filter(code => !!code);
|
|
56
60
|
const detail = { value, code };
|
|
57
61
|
if (postcode[2])
|
|
@@ -67,24 +71,25 @@ const _RegionPicker = forwardRef((props, ref) => {
|
|
|
67
71
|
props.getInnerLayout && props.getInnerLayout(layoutRef);
|
|
68
72
|
});
|
|
69
73
|
};
|
|
74
|
+
const onDismiss = () => {
|
|
75
|
+
bindcancel && bindcancel();
|
|
76
|
+
};
|
|
70
77
|
const regionProps = {
|
|
71
78
|
data: formatRegionData,
|
|
72
79
|
value: regionvalue,
|
|
73
80
|
onChange,
|
|
74
81
|
disabled,
|
|
75
|
-
onDismiss
|
|
82
|
+
onDismiss
|
|
76
83
|
};
|
|
77
84
|
const touchProps = {
|
|
78
85
|
onLayout: onElementLayout,
|
|
79
86
|
ref: viewRef
|
|
80
87
|
};
|
|
81
|
-
return (
|
|
82
|
-
// @ts-ignore
|
|
83
|
-
<Picker {...regionProps}>
|
|
88
|
+
return (<Picker {...regionProps}>
|
|
84
89
|
<TouchableWithoutFeedback>
|
|
85
90
|
<View {...touchProps}>{children}</View>
|
|
86
91
|
</TouchableWithoutFeedback>
|
|
87
92
|
</Picker>);
|
|
88
93
|
});
|
|
89
|
-
_RegionPicker.displayName
|
|
94
|
+
_RegionPicker.displayName = 'mpx-picker-region';
|
|
90
95
|
export default _RegionPicker;
|
|
@@ -20,14 +20,15 @@ const formatRangeFun = (range, rangeKey = '') => {
|
|
|
20
20
|
const _SelectorPicker = forwardRef((props, ref) => {
|
|
21
21
|
const { range, children, value, disabled, bindchange, bindcancel } = props;
|
|
22
22
|
// 格式化数据为Array<*>
|
|
23
|
-
|
|
23
|
+
const formatRange = formatRangeFun(range, props['range-key']);
|
|
24
24
|
// 选中的索引值
|
|
25
25
|
const [selected, setSelected] = useState(value || 0);
|
|
26
26
|
// range数据源
|
|
27
27
|
const [data, setData] = useState(formatRange || []);
|
|
28
28
|
// 存储layout布局信息
|
|
29
29
|
const layoutRef = useRef({});
|
|
30
|
-
const
|
|
30
|
+
const viewRef = useRef(null);
|
|
31
|
+
useNodesRef(props, ref, viewRef, {});
|
|
31
32
|
useEffect(() => {
|
|
32
33
|
if (range) {
|
|
33
34
|
const newFormatRange = formatRangeFun(range, props['range-key']);
|
|
@@ -6,47 +6,47 @@ import useNodesRef from '../useNodesRef'; // 引入辅助函数
|
|
|
6
6
|
// const { height: dHeight, width: dWidth } = Dimensions.get('window');
|
|
7
7
|
// modal属性: {"height": 298.33331298828125, "offsetLeft": 0, "offsetTop": 513.6666870117188, "width": 375, "x": 0, "y": 513.6666870117188}
|
|
8
8
|
// const { height: sHeight, width: sWidth } = Dimensions.get('screen');
|
|
9
|
-
//
|
|
9
|
+
// 设备屏幕的大小。 screen
|
|
10
10
|
const styles = {
|
|
11
11
|
showModal: {
|
|
12
|
-
backgroundColor:
|
|
12
|
+
backgroundColor: 'black',
|
|
13
13
|
opacity: 0.5,
|
|
14
|
-
position:
|
|
15
|
-
width:
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
width: '100%'
|
|
16
16
|
},
|
|
17
17
|
hideModal: {
|
|
18
18
|
opacity: 1,
|
|
19
19
|
height: 0
|
|
20
20
|
},
|
|
21
21
|
modal: {
|
|
22
|
-
backgroundColor:
|
|
22
|
+
backgroundColor: 'black',
|
|
23
23
|
opacity: 0.5
|
|
24
24
|
},
|
|
25
25
|
centeredView: {
|
|
26
26
|
position: 'absolute',
|
|
27
27
|
bottom: 0,
|
|
28
|
-
width:
|
|
28
|
+
width: '100%',
|
|
29
29
|
overflow: 'scroll'
|
|
30
30
|
},
|
|
31
31
|
btnLine: {
|
|
32
|
-
width:
|
|
32
|
+
width: '100%',
|
|
33
33
|
flex: 1,
|
|
34
|
-
flexDirection:
|
|
35
|
-
justifyContent:
|
|
34
|
+
flexDirection: 'row',
|
|
35
|
+
justifyContent: 'space-between',
|
|
36
36
|
borderColor: 20,
|
|
37
37
|
borderBottomWidth: 1,
|
|
38
|
-
backgroundColor:
|
|
38
|
+
backgroundColor: 'white',
|
|
39
39
|
paddingLeft: 40,
|
|
40
40
|
paddingRight: 40
|
|
41
41
|
},
|
|
42
42
|
cancel: {
|
|
43
43
|
height: 50,
|
|
44
|
-
display:
|
|
44
|
+
display: 'flex',
|
|
45
45
|
justifyContent: 'center'
|
|
46
46
|
},
|
|
47
47
|
ok: {
|
|
48
48
|
height: 50,
|
|
49
|
-
display:
|
|
49
|
+
display: 'flex',
|
|
50
50
|
justifyContent: 'center'
|
|
51
51
|
},
|
|
52
52
|
btntext: {
|
|
@@ -55,7 +55,7 @@ const styles = {
|
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
57
|
function formatStrToInt(timestr) {
|
|
58
|
-
|
|
58
|
+
const [start, end] = timestr.split(':');
|
|
59
59
|
return [parseInt(start), parseInt(end)];
|
|
60
60
|
}
|
|
61
61
|
// [9, 59] to 09:59
|
|
@@ -70,9 +70,9 @@ function formatStr(arr) {
|
|
|
70
70
|
return hour + ':' + minute;
|
|
71
71
|
}
|
|
72
72
|
function generateMinute() {
|
|
73
|
-
|
|
73
|
+
const arrMinute = [];
|
|
74
74
|
for (let i = 0; i <= 59; i++) {
|
|
75
|
-
|
|
75
|
+
const obj = {
|
|
76
76
|
label: toSingleStr(i),
|
|
77
77
|
value: i,
|
|
78
78
|
children: []
|
|
@@ -82,9 +82,9 @@ function generateMinute() {
|
|
|
82
82
|
return arrMinute;
|
|
83
83
|
}
|
|
84
84
|
function generateColumns() {
|
|
85
|
-
|
|
85
|
+
const pickData = [];
|
|
86
86
|
for (let i = 0; i <= 23; i++) {
|
|
87
|
-
|
|
87
|
+
const obj = {
|
|
88
88
|
label: toSingleStr(i),
|
|
89
89
|
value: i,
|
|
90
90
|
children: generateMinute()
|
|
@@ -126,10 +126,12 @@ const _TimePicker = forwardRef((props, ref) => {
|
|
|
126
126
|
const [timevalue, setTimeValue] = useState(defaultValue);
|
|
127
127
|
// 存储layout布局信息
|
|
128
128
|
const layoutRef = useRef({});
|
|
129
|
-
const
|
|
129
|
+
const viewRef = useRef(null);
|
|
130
|
+
useNodesRef(props, ref, viewRef, {});
|
|
130
131
|
// 存储modal的布局信息
|
|
131
132
|
const modalLayoutRef = useRef({});
|
|
132
|
-
const
|
|
133
|
+
const modalRef = useRef(null);
|
|
134
|
+
useNodesRef(props, ref, modalRef, {});
|
|
133
135
|
const [visible, setVisible] = useState(false);
|
|
134
136
|
const columnData = generateColumns();
|
|
135
137
|
const [data, setData] = useState(columnData);
|
|
@@ -228,7 +230,7 @@ const _TimePicker = forwardRef((props, ref) => {
|
|
|
228
230
|
</TouchableWithoutFeedback>
|
|
229
231
|
</View>;
|
|
230
232
|
};
|
|
231
|
-
const strStyle = visible ? styles
|
|
233
|
+
const strStyle = visible ? styles.showModal : styles.hideModal;
|
|
232
234
|
const mheight = Math.floor(offsetTop);
|
|
233
235
|
// Animated.View
|
|
234
236
|
return (<>
|
|
@@ -1,15 +1,108 @@
|
|
|
1
|
-
import { View } from 'react-native';
|
|
2
|
-
import React, { forwardRef, useRef } from 'react';
|
|
3
|
-
import
|
|
1
|
+
import { View, Animated, SafeAreaView } from 'react-native';
|
|
2
|
+
import React, { forwardRef, useRef, useState, useEffect } from 'react';
|
|
3
|
+
import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils';
|
|
4
4
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
5
|
+
const defaultItemHeight = 36;
|
|
6
|
+
// 每个Column 都有个外层的高度, 内部的元素高度
|
|
7
|
+
// 默认的高度
|
|
5
8
|
const _PickerViewColumn = forwardRef((props, ref) => {
|
|
6
|
-
const { children } = props;
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
{
|
|
12
|
-
|
|
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 scrollViewRef = useRef(null);
|
|
17
|
+
useNodesRef(props, ref, scrollViewRef, {});
|
|
18
|
+
// 每个元素的高度
|
|
19
|
+
let [itemH, setItemH] = useState(0);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (selectedIndex && itemH) {
|
|
22
|
+
const offsetY = selectedIndex * itemH;
|
|
23
|
+
scrollViewRef.current?.scrollTo({ x: 0, y: offsetY, animated: true });
|
|
24
|
+
}
|
|
25
|
+
}, [selectedIndex, itemH]);
|
|
26
|
+
const onScrollViewLayout = () => {
|
|
27
|
+
getInnerLayout && getInnerLayout(layoutRef);
|
|
28
|
+
};
|
|
29
|
+
const {
|
|
30
|
+
// 存储layout布局信息
|
|
31
|
+
layoutRef, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout: onScrollViewLayout });
|
|
32
|
+
const onItemLayout = (e) => {
|
|
33
|
+
const layout = e.nativeEvent.layout;
|
|
34
|
+
if (layout.height && itemH !== layout.height) {
|
|
35
|
+
itemH = layout.height;
|
|
36
|
+
setItemH(layout.height);
|
|
37
|
+
onColumnLayoutChange && onColumnLayoutChange({ height: layout.height * 5 });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const onMomentumScrollEnd = (e) => {
|
|
41
|
+
if (scrollViewRef && itemH) {
|
|
42
|
+
const { y: scrollY } = e.nativeEvent.contentOffset;
|
|
43
|
+
const selIndex = Math.floor(scrollY / itemH);
|
|
44
|
+
onSelectChange(selIndex);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const renderInnerchild = () => {
|
|
48
|
+
// Fragment 节点
|
|
49
|
+
let realElement = [];
|
|
50
|
+
const getRealChilds = () => {
|
|
51
|
+
if (Array.isArray(children)) {
|
|
52
|
+
realElement = children;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const tempChild = children;
|
|
56
|
+
if (tempChild.props.children && tempChild.props.children) {
|
|
57
|
+
realElement = tempChild.props.children;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
realElement = [children];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return realElement;
|
|
64
|
+
};
|
|
65
|
+
const realChilds = getRealChilds();
|
|
66
|
+
const arrChild = realChilds.map((item, index) => {
|
|
67
|
+
const InnerProps = index === 0 ? { onLayout: onItemLayout } : {};
|
|
68
|
+
const strKey = 'picker' + props.prefix + '-column' + index;
|
|
69
|
+
const arrHeight = (wrapperStyle.itemHeight + '').match(/\d+/g) || [];
|
|
70
|
+
const iHeight = (arrHeight[0] || defaultItemHeight);
|
|
71
|
+
return <View key={strKey} {...InnerProps} style={[{ height: iHeight, width: '100%' }]}>
|
|
72
|
+
{wrapChildren({
|
|
73
|
+
children: item
|
|
74
|
+
}, {
|
|
75
|
+
hasVarDec,
|
|
76
|
+
varContext: varContextRef.current,
|
|
77
|
+
textStyle,
|
|
78
|
+
textProps
|
|
79
|
+
})}
|
|
80
|
+
</View>;
|
|
81
|
+
});
|
|
82
|
+
const totalHeight = itemH * 5;
|
|
83
|
+
if (wrapperStyle.height && totalHeight !== wrapperStyle.height) {
|
|
84
|
+
const fix = Math.ceil((totalHeight - wrapperStyle.height) / 2);
|
|
85
|
+
arrChild.unshift(<View key="picker-column-0" style={[{ height: itemH - fix }]}></View>);
|
|
86
|
+
arrChild.unshift(<View key="picker-column-1" style={[{ height: itemH }]}></View>);
|
|
87
|
+
arrChild.push(<View key="picker-column-2" style={[{ height: itemH }]}></View>);
|
|
88
|
+
arrChild.push(<View key="picker-column-3" style={[{ height: itemH - fix }]}></View>);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
arrChild.unshift(<View key="picker-column-0" style={[{ height: itemH }]}></View>);
|
|
92
|
+
arrChild.unshift(<View key="picker-column-1" style={[{ height: itemH }]}></View>);
|
|
93
|
+
arrChild.push(<View key="picker-column-2" style={[{ height: itemH }]}></View>);
|
|
94
|
+
arrChild.push(<View key="picker-column-3" style={[{ height: itemH }]}></View>);
|
|
95
|
+
}
|
|
96
|
+
return arrChild;
|
|
97
|
+
};
|
|
98
|
+
const renderScollView = () => {
|
|
99
|
+
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}>
|
|
100
|
+
{renderInnerchild()}
|
|
101
|
+
</Animated.ScrollView>);
|
|
102
|
+
};
|
|
103
|
+
return (<SafeAreaView style={[{ display: 'flex', flex: 1 }]}>
|
|
104
|
+
{renderScollView()}
|
|
105
|
+
</SafeAreaView>);
|
|
13
106
|
});
|
|
14
107
|
_PickerViewColumn.displayName = 'mpx-picker-view-column';
|
|
15
108
|
export default _PickerViewColumn;
|
|
@@ -1,68 +1,163 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { getCustomEvent } from './getInnerListeners';
|
|
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
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
|
+
};
|
|
6
27
|
const _PickerView = forwardRef((props, ref) => {
|
|
7
|
-
const { children,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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 = useRef(null);
|
|
34
|
+
useNodesRef(props, ref, nodeRef, {});
|
|
35
|
+
// picker-view 设置的color等textStyle,在小程序上的表现是可以继承到最内层的text样式, 但是RN内部column是slot无法设置, 需要业务自己在column内的元素上设置
|
|
36
|
+
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
|
|
37
|
+
const { textStyle } = splitStyle(normalStyle);
|
|
38
|
+
const { textProps } = splitProps(props);
|
|
39
|
+
const {
|
|
40
|
+
// 存储layout布局信息
|
|
41
|
+
layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef });
|
|
42
|
+
const isSetW = indicatorW !== undefined ? 1 : 0;
|
|
43
|
+
const cloneRef = useRef(null);
|
|
44
|
+
const maskPos = {};
|
|
45
|
+
let [pickH, setPickH] = useState(0);
|
|
46
|
+
const itemH = pickH / 5;
|
|
47
|
+
if (normalStyle?.height && pickH && pickH !== normalStyle?.height) {
|
|
48
|
+
maskPos.height = itemH * 2 + Math.ceil((normalStyle.height - pickH) / 2);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
maskPos.height = itemH * 2;
|
|
52
|
+
}
|
|
53
|
+
const onColumnLayoutChange = (layoutConfig) => {
|
|
54
|
+
pickH = layoutConfig.height;
|
|
55
|
+
setPickH(layoutConfig.height);
|
|
19
56
|
};
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
57
|
+
const onSelectChange = (columnIndex, selIndex) => {
|
|
58
|
+
const changeValue = value.slice();
|
|
59
|
+
changeValue[columnIndex] = selIndex;
|
|
60
|
+
const eventData = getCustomEvent('change', {}, { detail: { value: changeValue, source: 'change' }, layoutRef });
|
|
61
|
+
bindchange && bindchange(eventData);
|
|
25
62
|
};
|
|
26
|
-
const
|
|
27
|
-
|
|
63
|
+
const innerProps = useInnerProps(props, {
|
|
64
|
+
ref: nodeRef,
|
|
65
|
+
style: {
|
|
66
|
+
...normalStyle,
|
|
67
|
+
...layoutStyle,
|
|
68
|
+
position: 'relative',
|
|
69
|
+
overflow: 'hidden'
|
|
70
|
+
},
|
|
71
|
+
...layoutProps
|
|
72
|
+
}, [
|
|
73
|
+
'enable-offset'
|
|
74
|
+
], { layoutRef });
|
|
75
|
+
const cloneChild = (child, index) => {
|
|
76
|
+
// const extraProps = index === 0 ? { getInnerLayout: getInnerLayout, innerProps } : {}
|
|
77
|
+
const extraProps = {};
|
|
78
|
+
const childProps = {
|
|
79
|
+
...child?.props,
|
|
80
|
+
ref: cloneRef,
|
|
81
|
+
prefix: index,
|
|
82
|
+
key: 'pick-view' + index,
|
|
83
|
+
wrapperStyle: {
|
|
84
|
+
height: normalStyle?.height || 0,
|
|
85
|
+
itemHeight: indicatorH || 0
|
|
86
|
+
},
|
|
87
|
+
onColumnLayoutChange,
|
|
88
|
+
onSelectChange: onSelectChange.bind(null, index),
|
|
89
|
+
selectedIndex: value?.[index] || 0,
|
|
90
|
+
...extraProps
|
|
91
|
+
};
|
|
92
|
+
const realElement = React.cloneElement(child, childProps);
|
|
93
|
+
return wrapChildren({
|
|
94
|
+
children: realElement
|
|
95
|
+
}, {
|
|
96
|
+
hasVarDec,
|
|
97
|
+
varContext: varContextRef.current,
|
|
98
|
+
textStyle,
|
|
99
|
+
textProps
|
|
100
|
+
});
|
|
28
101
|
};
|
|
29
|
-
const
|
|
30
|
-
|
|
102
|
+
const renderTopMask = () => {
|
|
103
|
+
const linearProps = {
|
|
104
|
+
colors: ['rgba(255,255,255,0.8)', 'rgba(255,255,255,0.2)'],
|
|
105
|
+
style: [
|
|
106
|
+
styles.maskTop,
|
|
107
|
+
{
|
|
108
|
+
height: maskPos.height,
|
|
109
|
+
top: 0,
|
|
110
|
+
pointerEvents: 'none'
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
};
|
|
114
|
+
return (<LinearGradient {...linearProps}/>);
|
|
31
115
|
};
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
116
|
+
const renderBottomMask = () => {
|
|
117
|
+
const linearProps = {
|
|
118
|
+
colors: ['rgba(255,255,255,0.2)', 'rgba(255,255,255,0.8)'],
|
|
119
|
+
style: [
|
|
120
|
+
styles.maskBottom,
|
|
121
|
+
{
|
|
122
|
+
height: maskPos.height,
|
|
123
|
+
bottom: 0,
|
|
124
|
+
pointerEvents: 'none'
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
};
|
|
128
|
+
return <LinearGradient {...linearProps}></LinearGradient>;
|
|
39
129
|
};
|
|
40
|
-
const
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
|
|
130
|
+
const renderLine = () => {
|
|
131
|
+
return <View style={[{
|
|
132
|
+
position: 'absolute',
|
|
133
|
+
top: '50%',
|
|
134
|
+
transform: [{ translateY: -(itemH / 2) }],
|
|
135
|
+
height: itemH,
|
|
136
|
+
borderTopWidth: 1,
|
|
137
|
+
borderBottomWidth: 1,
|
|
138
|
+
borderColor: '#f0f0f0',
|
|
139
|
+
width: '100%',
|
|
140
|
+
zIndex: 101
|
|
141
|
+
}]}></View>;
|
|
44
142
|
};
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
});
|
|
51
|
-
const defaultValue = (props.value || []).map((item, index) => {
|
|
52
|
-
if (item > subChildLength[index]) {
|
|
53
|
-
return subChildLength[index] - 1;
|
|
143
|
+
const renderSubChild = () => {
|
|
144
|
+
if (Array.isArray(children)) {
|
|
145
|
+
return children.map((item, index) => {
|
|
146
|
+
return cloneChild(item, index);
|
|
147
|
+
});
|
|
54
148
|
}
|
|
55
149
|
else {
|
|
56
|
-
return
|
|
150
|
+
return cloneChild(children, 0);
|
|
57
151
|
}
|
|
58
|
-
}
|
|
59
|
-
return (<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
152
|
+
};
|
|
153
|
+
return (<View {...innerProps}>
|
|
154
|
+
{renderTopMask()}
|
|
155
|
+
<View style={[styles.wrapper]}>
|
|
156
|
+
{renderSubChild()}
|
|
157
|
+
</View>
|
|
158
|
+
{renderBottomMask()}
|
|
159
|
+
{!isSetW && renderLine()}
|
|
160
|
+
</View>);
|
|
66
161
|
});
|
|
67
162
|
_PickerView.displayName = 'mpx-picker-view';
|
|
68
163
|
export default _PickerView;
|