@mpxjs/webpack-plugin 2.10.3 → 2.10.4

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 (103) hide show
  1. package/lib/config.js +2 -1
  2. package/lib/index.js +1 -1
  3. package/lib/platform/json/wx/index.js +6 -3
  4. package/lib/platform/style/wx/index.js +23 -12
  5. package/lib/platform/template/wx/component-config/button.js +19 -2
  6. package/lib/platform/template/wx/component-config/canvas.js +4 -0
  7. package/lib/platform/template/wx/component-config/checkbox-group.js +4 -0
  8. package/lib/platform/template/wx/component-config/checkbox.js +4 -0
  9. package/lib/platform/template/wx/component-config/cover-image.js +7 -1
  10. package/lib/platform/template/wx/component-config/cover-view.js +4 -0
  11. package/lib/platform/template/wx/component-config/fix-component-name.js +3 -2
  12. package/lib/platform/template/wx/component-config/form.js +7 -1
  13. package/lib/platform/template/wx/component-config/icon.js +4 -0
  14. package/lib/platform/template/wx/component-config/image.js +7 -1
  15. package/lib/platform/template/wx/component-config/input.js +18 -3
  16. package/lib/platform/template/wx/component-config/label.js +4 -0
  17. package/lib/platform/template/wx/component-config/movable-area.js +7 -1
  18. package/lib/platform/template/wx/component-config/movable-view.js +12 -3
  19. package/lib/platform/template/wx/component-config/navigator.js +4 -0
  20. package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
  21. package/lib/platform/template/wx/component-config/picker-view.js +7 -1
  22. package/lib/platform/template/wx/component-config/picker.js +7 -1
  23. package/lib/platform/template/wx/component-config/radio-group.js +4 -0
  24. package/lib/platform/template/wx/component-config/radio.js +4 -0
  25. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  26. package/lib/platform/template/wx/component-config/root-portal.js +4 -0
  27. package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
  28. package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
  29. package/lib/platform/template/wx/component-config/swiper.js +12 -3
  30. package/lib/platform/template/wx/component-config/switch.js +4 -0
  31. package/lib/platform/template/wx/component-config/text.js +24 -3
  32. package/lib/platform/template/wx/component-config/textarea.js +17 -2
  33. package/lib/platform/template/wx/component-config/unsupported.js +7 -0
  34. package/lib/platform/template/wx/component-config/video.js +10 -2
  35. package/lib/platform/template/wx/component-config/view.js +11 -1
  36. package/lib/platform/template/wx/component-config/web-view.js +4 -0
  37. package/lib/platform/template/wx/index.js +42 -75
  38. package/lib/react/processScript.js +1 -18
  39. package/lib/runtime/components/react/dist/event.config.js +1 -0
  40. package/lib/runtime/components/react/dist/getInnerListeners.js +18 -7
  41. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -1
  42. package/lib/runtime/components/react/dist/mpx-inline-text.jsx +11 -0
  43. package/lib/runtime/components/react/dist/mpx-input.jsx +3 -6
  44. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +2 -2
  45. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +194 -68
  46. package/lib/runtime/components/react/dist/mpx-picker/dateData.js +17 -0
  47. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +178 -96
  48. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +79 -139
  49. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +190 -90
  50. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +60 -75
  51. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +100 -228
  52. package/lib/runtime/components/react/dist/{mpx-picker-view.jsx → mpx-picker-view/index.jsx} +3 -3
  53. package/lib/runtime/components/react/dist/{mpx-picker-view-column.jsx → mpx-picker-view-column/index.jsx} +64 -16
  54. package/lib/runtime/components/react/dist/{mpx-picker-view-column-item.jsx → mpx-picker-view-column/pickerViewColumnItem.jsx} +8 -5
  55. package/lib/runtime/components/react/dist/{pickerFaces.js → mpx-picker-view-column/pickerViewFaces.js} +6 -0
  56. package/lib/runtime/components/react/dist/mpx-popup/index.jsx +61 -0
  57. package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +92 -0
  58. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +192 -25
  59. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +8 -7
  60. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +11 -15
  61. package/lib/runtime/components/react/dist/mpx-video.jsx +3 -3
  62. package/lib/runtime/components/react/dist/mpx-web-view.jsx +7 -4
  63. package/lib/runtime/components/react/dist/utils.jsx +2 -1
  64. package/lib/runtime/components/react/event.config.ts +2 -0
  65. package/lib/runtime/components/react/getInnerListeners.ts +28 -25
  66. package/lib/runtime/components/react/mpx-canvas/index.tsx +2 -2
  67. package/lib/runtime/components/react/mpx-inline-text.tsx +18 -0
  68. package/lib/runtime/components/react/mpx-input.tsx +2 -6
  69. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +1 -1
  70. package/lib/runtime/components/react/mpx-picker/date.tsx +226 -69
  71. package/lib/runtime/components/react/mpx-picker/dateData.ts +22 -0
  72. package/lib/runtime/components/react/mpx-picker/index.tsx +239 -118
  73. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +96 -139
  74. package/lib/runtime/components/react/mpx-picker/region.tsx +217 -89
  75. package/lib/runtime/components/react/mpx-picker/selector.tsx +75 -80
  76. package/lib/runtime/components/react/mpx-picker/time.tsx +119 -236
  77. package/lib/runtime/components/react/mpx-picker/type.ts +85 -71
  78. package/lib/runtime/components/react/{mpx-picker-view.tsx → mpx-picker-view/index.tsx} +7 -7
  79. package/lib/runtime/components/react/{mpx-picker-view-column.tsx → mpx-picker-view-column/index.tsx} +70 -19
  80. package/lib/runtime/components/react/{mpx-picker-view-column-item.tsx → mpx-picker-view-column/pickerViewColumnItem.tsx} +8 -5
  81. package/lib/runtime/components/react/{pickerFaces.ts → mpx-picker-view-column/pickerViewFaces.ts} +7 -0
  82. package/lib/runtime/components/react/mpx-popup/index.tsx +86 -0
  83. package/lib/runtime/components/react/mpx-popup/popupBase.tsx +130 -0
  84. package/lib/runtime/components/react/mpx-scroll-view.tsx +249 -43
  85. package/lib/runtime/components/react/mpx-simple-text.tsx +10 -8
  86. package/lib/runtime/components/react/mpx-simple-view.tsx +11 -16
  87. package/lib/runtime/components/react/mpx-video.tsx +2 -2
  88. package/lib/runtime/components/react/mpx-web-view.tsx +7 -4
  89. package/lib/runtime/components/react/types/getInnerListeners.d.ts +5 -1
  90. package/lib/runtime/components/react/types/global.d.ts +1 -1
  91. package/lib/runtime/components/react/utils.tsx +3 -2
  92. package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
  93. package/lib/runtime/components/web/mpx-input.vue +1 -1
  94. package/lib/runtime/stringify.wxs +2 -2
  95. package/lib/template-compiler/compiler.js +8 -8
  96. package/lib/utils/env.js +1 -1
  97. package/package.json +4 -5
  98. /package/lib/runtime/components/react/dist/{pickerVIewContext.js → mpx-picker-view/pickerVIewContext.js} +0 -0
  99. /package/lib/runtime/components/react/dist/{pickerViewIndicator.jsx → mpx-picker-view-column/pickerViewIndicator.jsx} +0 -0
  100. /package/lib/runtime/components/react/dist/{pickerViewMask.jsx → mpx-picker-view-column/pickerViewMask.jsx} +0 -0
  101. /package/lib/runtime/components/react/{pickerVIewContext.ts → mpx-picker-view/pickerVIewContext.ts} +0 -0
  102. /package/lib/runtime/components/react/{pickerViewIndicator.tsx → mpx-picker-view-column/pickerViewIndicator.tsx} +0 -0
  103. /package/lib/runtime/components/react/{pickerViewMask.tsx → mpx-picker-view-column/pickerViewMask.tsx} +0 -0
@@ -1,74 +1,200 @@
1
- import { View, TouchableWithoutFeedback } from 'react-native';
2
- import { DatePicker } from '@ant-design/react-native';
3
- import React, { forwardRef, useState, useRef, useEffect } from 'react';
4
- import useNodesRef from '../useNodesRef'; // 引入辅助函数
5
- function formatTimeStr(time = '') {
6
- let [year, month, day] = time.split('-');
7
- year = ~~year || 2000;
8
- month = ~~month || 1;
9
- day = ~~day || 1;
10
- return new Date(year, month - 1, day);
11
- }
12
- function dateToString(date, fields = 'day') {
13
- const yyyy = date.getFullYear() + '';
14
- const MM = ('0' + (date.getMonth() + 1)).slice(-2);
15
- const dd = ('0' + date.getDate()).slice(-2);
16
- let ret = yyyy;
17
- if (fields === 'month' || fields === 'day') {
18
- ret += `-${MM}`;
19
- if (fields === 'day') {
20
- ret += `-${dd}`;
1
+ import React, { forwardRef, useCallback, useMemo, useRef, useState, useEffect, useImperativeHandle } from 'react';
2
+ import { StyleSheet, Text } from 'react-native';
3
+ import MpxPickerView from '../mpx-picker-view';
4
+ import MpxPickerViewColumn from '../mpx-picker-view-column';
5
+ import { useUpdateEffect } from '../utils';
6
+ import { years, months, daysInMonth, wrapDate, daysInMonthLength, START_YEAR, END_YEAR } from './dateData';
7
+ const START_DATE = `${START_YEAR}-01-01`;
8
+ const END_DATE = `${END_YEAR}-12-31`;
9
+ const START_DATE_ARR = [START_YEAR, 1, 1];
10
+ const END_DATE_ARR = [END_YEAR, 12, 31];
11
+ const styles = StyleSheet.create({
12
+ pickerContainer: {
13
+ height: 240,
14
+ paddingHorizontal: 10,
15
+ borderTopLeftRadius: 10,
16
+ borderTopRightRadius: 10
17
+ },
18
+ pickerIndicator: {
19
+ height: 45
20
+ },
21
+ pickerItem: {
22
+ fontSize: 16,
23
+ lineHeight: 45,
24
+ textAlign: 'center'
25
+ }
26
+ });
27
+ const getColumnLength = (fields = 'day') => {
28
+ return fields === 'year' ? 1 : fields === 'month' ? 2 : 3;
29
+ };
30
+ const compareDateStr = (date1, date2) => {
31
+ const [y1 = START_YEAR, m1 = 0, d1 = 0] = typeof date1 === 'string' ? date1.split('-').map(Number) : date1;
32
+ const [y2 = START_YEAR, m2 = 0, d2 = 0] = typeof date2 === 'string' ? date2.split('-').map(Number) : date2;
33
+ const num1 = y1 * 10000 + m1 * 100 + d1;
34
+ const num2 = y2 * 10000 + m2 * 100 + d2;
35
+ if (num1 === num2) {
36
+ return 0;
37
+ }
38
+ return num1 > num2 ? 1 : -1;
39
+ };
40
+ const getDateArr = (date) => {
41
+ const [y, m, d] = typeof date === 'string' ? date.split('-').map(Number) : date;
42
+ return [y || 0, m || 0, d || 0];
43
+ };
44
+ const calibrateDate = (date, start, end) => {
45
+ let startArr = getDateArr(start);
46
+ let endArr = getDateArr(end);
47
+ let dateArr = getDateArr(date);
48
+ if (compareDateStr(startArr, endArr) > 0) {
49
+ startArr = START_DATE_ARR;
50
+ }
51
+ if (compareDateStr(endArr, startArr) < 0) {
52
+ endArr = END_DATE_ARR;
53
+ }
54
+ if (compareDateStr(start, end) > 0) {
55
+ startArr = START_DATE_ARR;
56
+ endArr = END_DATE_ARR;
57
+ }
58
+ if (compareDateStr(dateArr, endArr) > 0) {
59
+ dateArr = endArr;
60
+ }
61
+ if (compareDateStr(dateArr, startArr) < 0) {
62
+ dateArr = startArr;
63
+ }
64
+ return dateArr;
65
+ };
66
+ const initDateStr2Arr = (dateStr, start, end) => {
67
+ if (!dateStr) {
68
+ const today = new Date();
69
+ const todayYear = today.getFullYear();
70
+ const todayMonth = today.getMonth() + 1;
71
+ const todayDay = today.getDate();
72
+ dateStr = [todayYear, todayMonth, todayDay];
73
+ }
74
+ const [y, m, d] = getDateArr(dateStr);
75
+ const year = Math.min(Math.max(START_YEAR, y), END_YEAR);
76
+ const month = Math.min(Math.max(1, m), 12);
77
+ const day = Math.min(Math.max(1, d), daysInMonthLength(year, month));
78
+ const res = [year, month, day];
79
+ return calibrateDate(res, start, end);
80
+ };
81
+ const valueStr2Obj = (_value = '', // eg: 2025-2-12
82
+ limit, start, end) => {
83
+ const [y, m, d] = initDateStr2Arr(_value, start, end);
84
+ const ans = {
85
+ indexArr: [y - START_YEAR],
86
+ rangeArr: [years]
87
+ };
88
+ if (limit === 2) {
89
+ ans.indexArr.push(m - 1);
90
+ ans.rangeArr.push(months);
91
+ }
92
+ else if (limit === 3) {
93
+ const days = daysInMonth(y, m);
94
+ ans.indexArr.push(m - 1, d - 1);
95
+ ans.rangeArr.push(months, days);
96
+ }
97
+ return ans;
98
+ };
99
+ const valueChanged2Obj = (currentObj, value, limit = 3) => {
100
+ const currentValue = currentObj.indexArr;
101
+ const rangeArr = currentObj.rangeArr;
102
+ if (limit === 3 && (currentValue[0] !== value[0] || currentValue[1] !== value[1])) {
103
+ const days = daysInMonth(value[0], value[1] + 1);
104
+ rangeArr[2] = days;
105
+ const maxIndex = days.length - 1;
106
+ if (value[2] > maxIndex) {
107
+ value[2] = maxIndex;
108
+ }
109
+ }
110
+ return {
111
+ indexArr: value,
112
+ rangeArr
113
+ };
114
+ };
115
+ const valueChanged2Obj2 = (value, limit = 3, start, end) => {
116
+ const y = value[0] + START_YEAR;
117
+ const m = value[1] + 1;
118
+ const d = value[2] + 1;
119
+ return valueStr2Obj([y, m, d], limit, start, end);
120
+ };
121
+ const valueNum2String = (value) => {
122
+ return value.map((item, index) => {
123
+ if (index === 0) {
124
+ return item + START_YEAR;
125
+ }
126
+ else {
127
+ return wrapDate()(item + 1);
128
+ }
129
+ }).join('-');
130
+ };
131
+ const hasDiff = (currentValue, value, limit = 3) => {
132
+ for (let i = 0; i < limit; i++) {
133
+ if (currentValue[i] !== value[i]) {
134
+ return true;
21
135
  }
22
136
  }
23
- return ret;
24
- }
25
- const _DatePicker = forwardRef((props, ref) => {
26
- const { children, start = '1970-01-01', end = '2999-01-01', value, bindchange, bindcancel, disabled, fields, style } = props;
27
- const [datevalue, setDateValue] = useState(value);
28
- // 存储layout布局信息
29
- const layoutRef = useRef({});
30
- const viewRef = useRef(null);
137
+ return false;
138
+ };
139
+ const PickerDate = forwardRef((props, ref) => {
140
+ const { value = '', start = START_DATE, end = END_DATE, fields, bindchange } = props;
31
141
  const nodeRef = useRef(null);
32
- useNodesRef(props, ref, nodeRef, {
33
- style
34
- });
142
+ const columnLength = useMemo(() => getColumnLength(fields), [fields]);
143
+ const [formatObj, setFormatObj] = useState(valueStr2Obj(value, columnLength, start, end));
144
+ const timerRef = useRef(null);
35
145
  useEffect(() => {
36
- value && setDateValue(value);
37
- }, [value]);
38
- const onChange = (date) => {
39
- const { fields = 'day' } = props;
40
- const ret = dateToString(date, fields);
41
- setDateValue(ret);
42
- bindchange && bindchange({ detail: { value: ret } });
43
- };
44
- const onDismiss = () => {
45
- bindcancel && bindcancel();
46
- };
47
- const onElementLayout = (layout) => {
48
- viewRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
49
- layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
50
- props.getInnerLayout && props.getInnerLayout(layoutRef);
51
- });
52
- };
53
- const dateProps = {
54
- ref: nodeRef,
55
- precision: fields,
56
- value: formatTimeStr(datevalue),
57
- minDate: formatTimeStr(start),
58
- maxDate: formatTimeStr(end),
59
- onChange,
60
- onDismiss,
61
- disabled
62
- };
63
- const touchProps = {
64
- onLayout: onElementLayout,
65
- ref: viewRef
146
+ return () => {
147
+ timerRef.current && clearTimeout(timerRef.current);
148
+ };
149
+ }, []);
150
+ useUpdateEffect(() => {
151
+ const calibratedValue = valueStr2Obj(value, columnLength, start, end);
152
+ setFormatObj(calibratedValue);
153
+ }, [value, columnLength, start, end]);
154
+ const updateValue = useCallback((value = '') => {
155
+ const calibratedValue = valueStr2Obj(value, columnLength, start, end);
156
+ setFormatObj(calibratedValue);
157
+ }, [columnLength, start, end]);
158
+ const _props = useRef(props);
159
+ _props.current = props;
160
+ useImperativeHandle(ref, () => ({
161
+ updateValue,
162
+ getNodeInstance: () => ({
163
+ props: _props,
164
+ nodeRef,
165
+ instance: {
166
+ style: {}
167
+ }
168
+ })
169
+ }));
170
+ const onChange = useCallback((e) => {
171
+ const { value } = e.detail;
172
+ const currentValue = formatObj.indexArr;
173
+ const newObj = valueChanged2Obj(formatObj, value, columnLength);
174
+ if (hasDiff(currentValue, value, columnLength)) {
175
+ setFormatObj(newObj);
176
+ const newObj2 = valueChanged2Obj2(value, columnLength, start, end);
177
+ if (hasDiff(newObj.indexArr, newObj2.indexArr, columnLength)) {
178
+ timerRef.current && clearTimeout(timerRef.current);
179
+ timerRef.current = setTimeout(() => setFormatObj(newObj2));
180
+ }
181
+ }
182
+ bindchange?.({ detail: { value: valueNum2String(newObj.indexArr) } });
183
+ }, [formatObj, columnLength, bindchange, start, end]);
184
+ const renderColumn = () => {
185
+ return formatObj.rangeArr?.map((item, index) => (
186
+ // @ts-expect-error ignore
187
+ <MpxPickerViewColumn key={index}>
188
+ {item.map((item, index) => {
189
+ return <Text key={index} style={styles.pickerItem}>
190
+ {item}
191
+ </Text>;
192
+ })}
193
+ </MpxPickerViewColumn>));
66
194
  };
67
- return (<DatePicker {...dateProps}>
68
- <TouchableWithoutFeedback>
69
- <View {...touchProps}>{children}</View>
70
- </TouchableWithoutFeedback>
71
- </DatePicker>);
195
+ return (<MpxPickerView style={styles.pickerContainer} indicator-style={styles.pickerIndicator} value={formatObj.indexArr} bindchange={onChange}>
196
+ {renderColumn()}
197
+ </MpxPickerView>);
72
198
  });
73
- _DatePicker.displayName = 'mpx-picker-date';
74
- export default _DatePicker;
199
+ PickerDate.displayName = 'MpxPickerDate';
200
+ export default PickerDate;
@@ -0,0 +1,17 @@
1
+ export const wrapDate = (union = '') => (num) => String(num).padStart(2, '0') + union;
2
+ export const START_YEAR = 1900;
3
+ export const END_YEAR = 2099;
4
+ export const years = Array.from({ length: 200 }, (_, index) => index + START_YEAR + '年');
5
+ export const months = Array.from({ length: 12 }, (_, index) => index + 1).map(wrapDate('月'));
6
+ export const daysInMonthLength = (year, month) => {
7
+ return month === 2
8
+ ? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
9
+ ? 29
10
+ : 28
11
+ : [4, 6, 9, 11].includes(month)
12
+ ? 30
13
+ : 31;
14
+ };
15
+ export const daysInMonth = (year, month) => {
16
+ return Array.from({ length: daysInMonthLength(year, month) }, (_, index) => index + 1).map(wrapDate('日'));
17
+ };
@@ -1,14 +1,16 @@
1
- import { View } from 'react-native';
2
- import React, { forwardRef, useRef, useContext, useState } from 'react';
1
+ import React, { forwardRef, useRef, useContext, useEffect } from 'react';
2
+ import { StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native';
3
3
  import { warn } from '@mpxjs/utils';
4
+ import PickerSelector from './selector';
5
+ import PickerMultiSelector from './multiSelector';
6
+ import PickerTime from './time';
7
+ import PickerDate from './date';
8
+ import PickerRegion from './region';
9
+ import { FormContext, RouteContext } from '../context';
10
+ import useNodesRef from '../useNodesRef';
4
11
  import useInnerProps, { getCustomEvent } from '../getInnerListeners';
5
- import useNodesRef from '../useNodesRef'; // 引入辅助函数
6
- import Selector from './selector';
7
- import TimeSelector from './time';
8
- import DateSelector from './date';
9
- import MultiSelector from './multiSelector';
10
- import RegionSelector from './region';
11
- import { FormContext } from '../context';
12
+ import { extendObject } from '../utils';
13
+ import { createPopupManager } from '../mpx-popup';
12
14
  /**
13
15
  * ✔ mode
14
16
  * ✔ disabled
@@ -24,40 +26,118 @@ import { FormContext } from '../context';
24
26
  * ✔ custom-item
25
27
  * ✔ level 选择器层级 province,city,region,<sub-district不支持>
26
28
  * ✔ level
27
- * header-text
28
- * bindcolumnchange
29
+ * header-text
30
+ * bindcolumnchange
29
31
  */
30
- const _Picker = forwardRef((props, ref) => {
31
- const { mode = 'selector', value, bindcancel, bindchange, children, bindcolumnchange, style } = props;
32
+ const styles = StyleSheet.create({
33
+ header: {
34
+ height: 40,
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ borderBottomWidth: StyleSheet.hairlineWidth,
38
+ borderBottomColor: '#eeeeee'
39
+ },
40
+ headerText: {
41
+ color: '#333333',
42
+ fontSize: 18,
43
+ textAlign: 'center'
44
+ },
45
+ footer: {
46
+ gap: 20,
47
+ height: 50,
48
+ marginBottom: 20,
49
+ alignItems: 'center',
50
+ flexDirection: 'row',
51
+ justifyContent: 'center'
52
+ },
53
+ footerItem: {
54
+ alignItems: 'center',
55
+ justifyContent: 'center',
56
+ height: 40,
57
+ width: 110,
58
+ borderRadius: 5
59
+ },
60
+ cancelButton: {
61
+ backgroundColor: '#eeeeee'
62
+ },
63
+ confirmButton: {
64
+ backgroundColor: '#1AAD19'
65
+ },
66
+ cancelText: {
67
+ color: 'green',
68
+ fontSize: 18,
69
+ textAlign: 'center'
70
+ },
71
+ confirmText: {
72
+ color: '#FFFFFF',
73
+ fontSize: 18,
74
+ textAlign: 'center'
75
+ }
76
+ });
77
+ const pickerModalMap = {
78
+ ["selector" /* PickerMode.SELECTOR */]: PickerSelector,
79
+ ["multiSelector" /* PickerMode.MULTI_SELECTOR */]: PickerMultiSelector,
80
+ ["time" /* PickerMode.TIME */]: PickerTime,
81
+ ["date" /* PickerMode.DATE */]: PickerDate,
82
+ ["region" /* PickerMode.REGION */]: PickerRegion
83
+ };
84
+ const getDefaultValue = (mode) => {
85
+ switch (mode) {
86
+ case "selector" /* PickerMode.SELECTOR */:
87
+ case "multiSelector" /* PickerMode.MULTI_SELECTOR */:
88
+ case "region" /* PickerMode.REGION */:
89
+ return [];
90
+ case "time" /* PickerMode.TIME */:
91
+ case "date" /* PickerMode.DATE */:
92
+ default:
93
+ return '';
94
+ }
95
+ };
96
+ const buttonTextMap = {
97
+ 'zh-CN': {
98
+ cancel: '取消',
99
+ confirm: '确定'
100
+ },
101
+ 'en-US': {
102
+ cancel: 'Cancel',
103
+ confirm: 'Confirm'
104
+ }
105
+ };
106
+ const Picker = forwardRef((props, ref) => {
107
+ const { mode, value, range = null, children, disabled, bindcancel, bindchange, 'header-text': headerText = '' } = props;
108
+ const { pageId } = useContext(RouteContext) || {};
109
+ const buttonText = buttonTextMap[global.__mpx?.i18n?.locale || 'zh-CN'];
110
+ const pickerValue = useRef(value);
111
+ pickerValue.current = Array.isArray(value) ? value.slice() : value;
32
112
  const innerLayout = useRef({});
33
113
  const nodeRef = useRef(null);
34
- useNodesRef(props, ref, nodeRef, {
35
- style
36
- });
114
+ const pickerRef = useRef(null);
115
+ const { open, show, hide, remove } = useRef(createPopupManager()).current;
116
+ useNodesRef(props, ref, nodeRef);
37
117
  const innerProps = useInnerProps(props, {
38
118
  ref: nodeRef
39
119
  }, [], { layoutRef: innerLayout });
40
- const [pickerValue, setPickerValue] = useState(value);
41
- const defaultValues = {
42
- selector: 0,
43
- multiSelector: [0],
44
- time: props.start,
45
- date: props.start,
46
- region: undefined
120
+ const getInnerLayout = (layout) => {
121
+ innerLayout.current = layout.current;
122
+ };
123
+ useEffect(() => {
124
+ if (range && pickerRef.current && mode === "multiSelector" /* PickerMode.MULTI_SELECTOR */) {
125
+ pickerRef.current.updateRange?.(range);
126
+ }
127
+ }, [JSON.stringify(range)]);
128
+ /** --- form 表单组件内部方法 --- */
129
+ const getValue = () => {
130
+ return pickerValue.current;
131
+ };
132
+ const resetValue = () => {
133
+ const defalutValue = getDefaultValue(mode); // 默认值
134
+ pickerRef.current.updateValue?.(defalutValue);
47
135
  };
48
136
  const formContext = useContext(FormContext);
49
137
  let formValuesMap;
50
- // 判断 context 是否存在,存在的话读取 context 中存的 formValuesMap
51
138
  if (formContext) {
52
139
  formValuesMap = formContext.formValuesMap;
53
140
  }
54
- const resetValue = () => {
55
- const defalutValue = (defaultValues[mode] !== undefined ? defaultValues[mode] : value);
56
- setPickerValue(defalutValue);
57
- };
58
- const getValue = () => {
59
- return pickerValue;
60
- };
61
141
  if (formValuesMap) {
62
142
  if (!props.name) {
63
143
  warn('If a form component is used, the name attribute is required.');
@@ -66,76 +146,78 @@ const _Picker = forwardRef((props, ref) => {
66
146
  formValuesMap.set(props.name, { getValue, resetValue });
67
147
  }
68
148
  }
69
- const getInnerLayout = (layout) => {
70
- innerLayout.current = layout.current;
149
+ useEffect(() => {
150
+ return () => {
151
+ if (formValuesMap && props.name) {
152
+ formValuesMap.delete(props.name);
153
+ }
154
+ };
155
+ }, []);
156
+ /** --- form 表单组件内部方法 --- */
157
+ const onChange = (e) => {
158
+ const { value } = e.detail;
159
+ pickerValue.current = value;
160
+ };
161
+ const onColumnChange = (columnIndex, value) => {
162
+ if (mode !== "multiSelector" /* PickerMode.MULTI_SELECTOR */) {
163
+ return;
164
+ }
165
+ const eventData = getCustomEvent('columnchange', {}, { detail: { column: columnIndex, value }, layoutRef: innerLayout });
166
+ props.bindcolumnchange?.(eventData);
71
167
  };
72
- const onChange = (event) => {
73
- const eventData = getCustomEvent('change', {}, { detail: event.detail, layoutRef: innerLayout });
74
- bindchange && bindchange(eventData);
75
- setPickerValue(event.detail.value);
168
+ const onCancel = () => {
169
+ bindcancel?.();
170
+ hide();
76
171
  };
77
- const columnChange = (value, index) => {
78
- // type: "columnchange", detail: {column: 1, value: 2}
79
- const eventData = getCustomEvent('columnchange', {}, { detail: { column: index, value }, layoutRef: innerLayout });
80
- bindcolumnchange && bindcolumnchange(eventData);
172
+ const onConfirm = () => {
173
+ const eventData = getCustomEvent('change', {}, { detail: { value: pickerValue.current }, layoutRef: innerLayout });
174
+ bindchange?.(eventData);
175
+ hide();
81
176
  };
82
- const commonProps = {
83
- ...innerProps,
177
+ const specificProps = extendObject(innerProps, {
84
178
  mode,
85
179
  children,
86
180
  bindchange: onChange,
87
- bindcolumnchange: columnChange,
88
- bindcancel,
89
- getInnerLayout
90
- };
91
- const selectorProps = {
92
- ...commonProps,
93
- value: pickerValue,
94
- range: props.range,
95
- 'range-key': props['range-key']
96
- };
97
- const multiProps = {
98
- ...commonProps,
99
- value: pickerValue,
100
- range: props.range,
101
- 'range-key': props['range-key']
102
- };
103
- const timeProps = {
104
- ...commonProps,
105
- value: pickerValue,
106
- start: props.start,
107
- end: props.end
108
- };
109
- const dateProps = {
110
- ...commonProps,
111
- value: pickerValue,
112
- start: props.start,
113
- end: props.end,
114
- fileds: props.fields || 'day'
115
- };
116
- const regionProps = {
117
- ...commonProps,
118
- value: pickerValue,
119
- level: props.level || 'sub-district'
181
+ bindcolumnchange: onColumnChange,
182
+ getInnerLayout,
183
+ getRange: () => range
184
+ });
185
+ const renderPickerContent = () => {
186
+ if (disabled) {
187
+ return null;
188
+ }
189
+ const _mode = mode ?? "selector" /* PickerMode.SELECTOR */;
190
+ if (!(_mode in pickerModalMap)) {
191
+ return warn(`[Mpx runtime warn]: Unsupported <picker> mode: ${mode}`);
192
+ }
193
+ const _value = value;
194
+ const PickerModal = pickerModalMap[_mode];
195
+ const renderPickerModal = (<>
196
+ {headerText && (<View style={[styles.header]}>
197
+ <Text style={[styles.headerText]}>{headerText}</Text>
198
+ </View>)}
199
+ <PickerModal {...specificProps} value={_value} ref={pickerRef}></PickerModal>
200
+ <View style={[styles.footer]}>
201
+ <View onTouchEnd={onCancel} style={[styles.footerItem, styles.cancelButton]}>
202
+ <Text style={[styles.cancelText]}>{buttonText.cancel}</Text>
203
+ </View>
204
+ <View onTouchEnd={onConfirm} style={[styles.footerItem, styles.confirmButton]}>
205
+ <Text style={[styles.confirmText]}>{buttonText.confirm}</Text>
206
+ </View>
207
+ </View>
208
+ </>);
209
+ const contentHeight = headerText ? 350 : 310;
210
+ open(renderPickerModal, pageId, { contentHeight });
120
211
  };
121
- if (mode === 'selector') {
122
- return <Selector {...selectorProps}></Selector>;
123
- }
124
- else if (mode === 'multiSelector') {
125
- return <MultiSelector {...multiProps}></MultiSelector>;
126
- }
127
- else if (mode === 'time') {
128
- return <TimeSelector {...timeProps}></TimeSelector>;
129
- }
130
- else if (mode === 'date') {
131
- return <DateSelector {...dateProps}></DateSelector>;
132
- }
133
- else if (mode === 'region') {
134
- return <RegionSelector {...regionProps}></RegionSelector>;
135
- }
136
- else {
137
- return <View>只支持selector, multiSelector, time, date, region 这些类型</View>;
138
- }
212
+ useEffect(() => {
213
+ renderPickerContent();
214
+ return () => {
215
+ remove();
216
+ };
217
+ }, []);
218
+ return (<TouchableWithoutFeedback onPress={show}>
219
+ {children}
220
+ </TouchableWithoutFeedback>);
139
221
  });
140
- _Picker.displayName = 'mpx-picker';
141
- export default _Picker;
222
+ Picker.displayName = 'MpxPicker';
223
+ export default Picker;