@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,91 @@
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, PickerColumn, PickerValue } from '@ant-design/react-native'
7
+ import { SelectorProps, Obj, LayoutType } from './type'
8
+ import useNodesRef, { HandlerRef } from '../useNodesRef' // 引入辅助函数
9
+
10
+ type RangeItemType = Obj | number | string
11
+
12
+ const formatRangeFun = (range: Array<RangeItemType>, rangeKey = ''): any => {
13
+ let newRange: Object[] = []
14
+ newRange = (range || []).map((item: RangeItemType, index) => {
15
+ if (typeof item === 'object') {
16
+ return { value: index, label: item[rangeKey as string] }
17
+ } else {
18
+ return { value: index, label: item }
19
+ }
20
+ })
21
+ return newRange as PickerColumn
22
+ }
23
+
24
+ const _SelectorPicker = forwardRef<HandlerRef<View, SelectorProps>, SelectorProps>((props: SelectorProps, ref): React.JSX.Element => {
25
+ const { range, children, value, disabled, bindchange, bindcancel } = props
26
+ // 格式化数据为Array<*>
27
+ const formatRange: PickerColumn = formatRangeFun(range, props['range-key'])
28
+ // 选中的索引值
29
+ const [selected, setSelected] = useState<PickerValue>(value || 0)
30
+ // range数据源
31
+ const [data, setData] = useState(formatRange || [])
32
+ // 存储layout布局信息
33
+ const layoutRef = useRef({})
34
+ const { nodeRef: viewRef } = useNodesRef<View, SelectorProps>(props, ref, {
35
+ })
36
+
37
+ useEffect(() => {
38
+ if (range) {
39
+ const newFormatRange = formatRangeFun(range, props['range-key'])
40
+ setData(newFormatRange)
41
+ }
42
+ setSelected(() => {
43
+ return value
44
+ })
45
+ }, [range, value])
46
+ const defaultValue = [value]
47
+
48
+ const onChange = (value: PickerValue[]) => {
49
+ bindchange && bindchange({
50
+ detail: {
51
+ value: value && value[0]
52
+ }
53
+ })
54
+ }
55
+
56
+ const onElementLayout = (layout: LayoutType) => {
57
+ viewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
58
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
59
+ props.getInnerLayout && props.getInnerLayout(layoutRef)
60
+ })
61
+ }
62
+
63
+ const antPickerProps = {
64
+ data,
65
+ value: [selected],
66
+ cols: 1,
67
+ defaultValue,
68
+ itemHeight: 40,
69
+ onChange,
70
+ onDismiss: bindcancel && bindcancel
71
+ } as any
72
+
73
+ const touchProps = {
74
+ onLayout: onElementLayout,
75
+ ref: viewRef
76
+ }
77
+ return (
78
+ <Picker
79
+ {...antPickerProps}>
80
+ <TouchableWithoutFeedback>
81
+ <View {...touchProps}>
82
+ {children}
83
+ </View>
84
+ </TouchableWithoutFeedback>
85
+ </Picker>
86
+ )
87
+ })
88
+
89
+ _SelectorPicker.displayName = 'mpx-picker-selector'
90
+
91
+ export default _SelectorPicker
@@ -0,0 +1,270 @@
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, { HandlerRef } from '../useNodesRef' // 引入辅助函数
5
+ import { TimeProps } from './type'
6
+
7
+ // 可见应用窗口的大小。
8
+ // const { height: dHeight, width: dWidth } = Dimensions.get('window');
9
+ // modal属性: {"height": 298.33331298828125, "offsetLeft": 0, "offsetTop": 513.6666870117188, "width": 375, "x": 0, "y": 513.6666870117188}
10
+ // const { height: sHeight, width: sWidth } = Dimensions.get('screen');
11
+ // 设备屏幕的大小。 screen
12
+ const styles: { [key: string]: Object } = {
13
+ showModal: {
14
+ backgroundColor: 'black',
15
+ opacity: 0.5,
16
+ position: 'absolute',
17
+ width: '100%'
18
+ },
19
+ hideModal: {
20
+ opacity: 1,
21
+ height: 0
22
+ },
23
+ modal: {
24
+ backgroundColor: 'black',
25
+ opacity: 0.5
26
+ },
27
+ centeredView: {
28
+ position: 'absolute',
29
+ bottom: 0,
30
+ width: '100%',
31
+ overflow: 'scroll'
32
+ },
33
+ btnLine: {
34
+ width: '100%',
35
+ flex: 1,
36
+ flexDirection: 'row',
37
+ justifyContent: 'space-between',
38
+ borderColor: 20,
39
+ borderBottomWidth: 1,
40
+ backgroundColor: 'white',
41
+ paddingLeft: 40,
42
+ paddingRight: 40
43
+ },
44
+ cancel: {
45
+ height: 50,
46
+ display: 'flex',
47
+ justifyContent: 'center'
48
+ },
49
+ ok: {
50
+ height: 50,
51
+ display: 'flex',
52
+ justifyContent: 'center'
53
+ },
54
+ btntext: {
55
+ color: '#0ae',
56
+ fontSize: 18
57
+ }
58
+ }
59
+
60
+ function formatStrToInt (timestr: string) {
61
+ const [start, end] = timestr.split(':')
62
+ return [parseInt(start), parseInt(end)]
63
+ }
64
+ // [9, 59] to 09:59
65
+ function formatStr (arr: any[]) {
66
+ let [hour, minute] = arr
67
+ if (hour < 10) {
68
+ hour = '0' + hour
69
+ }
70
+ if (minute < 10) {
71
+ minute = '0' + minute
72
+ }
73
+ return hour + ':' + minute
74
+ }
75
+
76
+ function generateMinute () {
77
+ const arrMinute: any[] = []
78
+ for (let i = 0; i <= 59; i++) {
79
+ const obj = {
80
+ label: toSingleStr(i),
81
+ value: i,
82
+ children: []
83
+ }
84
+ arrMinute.push(obj)
85
+ }
86
+ return arrMinute
87
+ }
88
+ function generateColumns (): any[] {
89
+ const pickData: any[] = []
90
+ for (let i = 0; i <= 23; i++) {
91
+ const obj = {
92
+ label: toSingleStr(i),
93
+ value: i,
94
+ children: generateMinute()
95
+ }
96
+ pickData.push(obj)
97
+ }
98
+
99
+ return pickData
100
+ }
101
+
102
+ function toSingleStr (str: number) {
103
+ return str < 10 ? '0' + str : str
104
+ }
105
+
106
+ function toStr (time: string): string {
107
+ const [hour, minute]: any = formatStrToInt(time)
108
+ const newHour = toSingleStr(hour)
109
+ const newMinute = toSingleStr(minute)
110
+ return '' + newHour + newMinute
111
+ }
112
+
113
+ function checkSelectedIsValid (strStart: string, strEnd: string, selected: number[]): boolean {
114
+ const strSel = '' + toSingleStr(selected[0]) + toSingleStr(selected[1])
115
+ if (strSel < strStart || strSel > strEnd) return false
116
+ return true
117
+ }
118
+ /**
119
+ * [{label:'', value: '', key: '', children: []}]
120
+ label: string | ReactNode
121
+ value: string | number
122
+ key?: string | number
123
+ children?: PickerColumnItem[]
124
+ */
125
+ // start="02:10" end = 23:01
126
+
127
+ const _TimePicker = forwardRef<HandlerRef<View, TimeProps>, TimeProps>((props: TimeProps, ref): React.JSX.Element => {
128
+ const { children, start, end, value, bindchange, bindcancel, disabled } = props
129
+ const defaultProps = {
130
+ start: '00:10',
131
+ end: '23:59'
132
+ }
133
+ const defaultValue = formatStrToInt(value)
134
+ const [timevalue, setTimeValue] = useState(defaultValue)
135
+ // 存储layout布局信息
136
+ const layoutRef = useRef({})
137
+ const { nodeRef: viewRef } = useNodesRef<View, TimeProps>(props, ref, {})
138
+ // 存储modal的布局信息
139
+ const modalLayoutRef = useRef({})
140
+ const { nodeRef: modalRef } = useNodesRef<View, TimeProps>(props, ref, {})
141
+ const [visible, setVisible] = useState(false)
142
+ const columnData = generateColumns()
143
+ const [data, setData] = useState(columnData)
144
+ const [offsetTop, setOffsetTop] = useState(0)
145
+ const strStart = toStr(start)
146
+ const strEnd = toStr(end)
147
+
148
+ useEffect(() => {
149
+ const newColumnData = generateColumns()
150
+ setData(newColumnData)
151
+ }, [start, end])
152
+
153
+ useEffect(() => {
154
+ if (value) {
155
+ const nValue = formatStrToInt(value)
156
+ nValue && setTimeValue(nValue)
157
+ }
158
+ }, [value])
159
+
160
+ // console.log('---------------visible---', visible, JSON.stringify(columnData))
161
+ const handleModalStatus = (status: boolean) => {
162
+ setVisible(status)
163
+ }
164
+ const handleConfirm = () => {
165
+ handleModalStatus(false)
166
+ bindchange && bindchange({
167
+ detail: {
168
+ value: formatStr(timevalue)
169
+ }
170
+ })
171
+ }
172
+
173
+ const handleCancel = () => {
174
+ handleModalStatus(false)
175
+ bindcancel && bindcancel()
176
+ }
177
+
178
+ const handleChildClick = () => {
179
+ handleModalStatus(true)
180
+ }
181
+
182
+ const handlePickChange = (date: number[]): void => {
183
+ // 不是有效的值
184
+ if (!checkSelectedIsValid(strStart, strEnd, date)) {
185
+ setTimeValue(timevalue)
186
+ } else {
187
+ // [9, 13]
188
+ setTimeValue(date)
189
+ const strDate = formatStr(date)
190
+ bindchange && bindchange({
191
+ detail: {
192
+ value: strDate
193
+ }
194
+ })
195
+ }
196
+ }
197
+
198
+ const onElementLayout = () => {
199
+ viewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
200
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
201
+ props.getInnerLayout && props.getInnerLayout(layoutRef)
202
+ })
203
+ }
204
+
205
+ const onModalLayout = () => {
206
+ modalRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
207
+ modalLayoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
208
+ setOffsetTop(offsetTop)
209
+ })
210
+ }
211
+
212
+ const renderModalChildren = () => {
213
+ const pickerProps = {
214
+ data,
215
+ value: timevalue,
216
+ defaultValue: timevalue,
217
+ cols: 2,
218
+ onChange: handlePickChange
219
+ }
220
+ return (
221
+ <View style={styles.centeredView} ref={modalRef} onLayout={onModalLayout}>
222
+ <View style={styles.btnLine}>
223
+ <View style={styles.cancel}>
224
+ <TouchableWithoutFeedback onPress={handleCancel}>
225
+ <Text style={styles.btntext}>取消</Text>
226
+ </TouchableWithoutFeedback>
227
+ </View>
228
+ <View style={styles.ok}>
229
+ <TouchableWithoutFeedback onPress={handleConfirm}>
230
+ <Text style={styles.btntext}>确定</Text>
231
+ </TouchableWithoutFeedback>
232
+ </View>
233
+ </View>
234
+ <PickerView {...pickerProps}></PickerView>
235
+ </View>
236
+ )
237
+ }
238
+
239
+ const renderChildren = () => {
240
+ const touchProps = {
241
+ onLayout: onElementLayout,
242
+ ref: viewRef
243
+ }
244
+ return <View>
245
+ <TouchableWithoutFeedback onPress={handleChildClick}>
246
+ <View {...touchProps}>{children}</View>
247
+ </TouchableWithoutFeedback>
248
+ </View>
249
+ }
250
+ const strStyle = visible ? styles.showModal : styles.hideModal
251
+ const mheight = Math.floor(offsetTop)
252
+
253
+ // Animated.View
254
+ return (<>
255
+ <View style={{ ...strStyle, height: visible ? mheight : 0, bottom: 0 }}>
256
+ <Modal
257
+ animationType="slide"
258
+ transparent={true}
259
+ visible={visible}
260
+ >
261
+ {renderModalChildren()}
262
+ </Modal>
263
+ </View>
264
+ {renderChildren()}
265
+ </>)
266
+ })
267
+
268
+ _TimePicker.displayName = 'mpx-picker-time'
269
+
270
+ export default _TimePicker
@@ -0,0 +1,107 @@
1
+ import { ReactNode } from 'react'
2
+ import { PickerValue } from '@ant-design/react-native'
3
+
4
+ export type Obj = Record<string, any>
5
+ export type SelectorProps = {
6
+ mode: string,
7
+ // 表示选择了 range 中的第几个(下标从 0 开始)
8
+ value: PickerValue
9
+ disabled?: boolean,
10
+ children: ReactNode,
11
+ bindcancel?: Function,
12
+ bindchange: Function,
13
+ // mode 为 selector 或 multiSelector 时,range 有效
14
+ range: Array<number|string|Obj>,
15
+ // 当 range 是一个 Object Array 时,通过 range-key 来指定 Object 中 key 的值作为选择器《显示内容》 对象中的属性
16
+ 'range-key': string,
17
+ getInnerLayout: Function
18
+ // bindcolumnchange?: Function
19
+ }
20
+
21
+ export type MultiSelectorProps = {
22
+ mode: string,
23
+ // 表示选择了 range 中的第几个(下标从 0 开始)
24
+ value: Array<number>,
25
+ disabled?: boolean,
26
+ children: ReactNode,
27
+ bindcancel?: Function,
28
+ bindchange: Function,
29
+ bindcolumnchange?: Function,
30
+ // mode 为 selector 或 multiSelector 时,range 有效
31
+ range: Array<Array<any>>,
32
+ // 当 range 是一个 Object Array 时,通过 range-key 来指定 Object 中 key 的值作为选择器《显示内容》 对象中的属性
33
+ 'range-key': string,
34
+ getInnerLayout: Function
35
+ }
36
+
37
+ export type TimeProps = {
38
+ mode: string,
39
+ // 表示选择了 range 中的第几个(下标从 0 开始)
40
+ value: string,
41
+ disabled?: boolean,
42
+ children: ReactNode,
43
+ bindcancel?: Function,
44
+ bindchange: Function,
45
+ start: string,
46
+ end: string,
47
+ getInnerLayout: Function
48
+ }
49
+
50
+ export type DateProps = {
51
+ mode: string,
52
+ // 表示选择了 range 中的第几个(下标从 0 开始)
53
+ value: string,
54
+ fields?: 'day' | 'month' | 'year',
55
+ disabled?: boolean,
56
+ children: ReactNode,
57
+ bindcancel?: Function,
58
+ bindchange: Function,
59
+ start: string,
60
+ end: string,
61
+ getInnerLayout: Function
62
+ }
63
+
64
+ export type RegionProps = {
65
+ mode: string,
66
+ // 表示选择了 range 中的第几个(下标从 0 开始)
67
+ value: Array<string>,
68
+ level: 'province' | 'city' | 'region' | 'sub-district'
69
+ 'custom-item'?: string,
70
+ disabled?: boolean,
71
+ children: ReactNode,
72
+ bindcancel?: Function,
73
+ bindchange: Function,
74
+ getInnerLayout: Function
75
+ }
76
+
77
+ export type RegionObj = {
78
+ value: string,
79
+ code: string
80
+ postcode?: string
81
+ children?: RegionObj[]
82
+ }
83
+
84
+ export type PickerData = {
85
+ value: string,
86
+ label: string,
87
+ children?: Array<Object>
88
+ }
89
+
90
+ export type EventType = {
91
+ detail: {
92
+ value: PickerValue[]
93
+ }
94
+ }
95
+
96
+ export type LayoutType = {
97
+ nativeEvent: {
98
+ layout: Obj
99
+ }
100
+ }
101
+
102
+ type FormType = {
103
+ name: string
104
+ }
105
+
106
+ export type PickerProps = SelectorProps & MultiSelectorProps & TimeProps & DateProps & RegionProps & FormType
107
+ export type ValueType = string | number | Array<number> | Array<string>
@@ -0,0 +1,156 @@
1
+
2
+ import { View, Animated, SafeAreaView, NativeScrollEvent, NativeSyntheticEvent, LayoutChangeEvent, ScrollView } from 'react-native'
3
+ import React, { forwardRef, useState, useEffect, ReactElement, ReactNode } from 'react'
4
+ import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils'
5
+ import useNodesRef, { HandlerRef } from './useNodesRef' // 引入辅助函数
6
+ interface ColumnProps {
7
+ children: React.ReactNode,
8
+ selectedIndex: number,
9
+ onColumnLayoutChange: Function,
10
+ getInnerLayout: Function,
11
+ onSelectChange: Function,
12
+ style: {
13
+ [key: string]: any
14
+ },
15
+ 'enable-var': boolean
16
+ 'external-var-context'?: Record<string, any>
17
+ wrapperStyle: {
18
+ height?: number,
19
+ itemHeight: string
20
+ },
21
+ prefix: number
22
+ }
23
+ const defaultItemHeight = 36
24
+ // 每个Column 都有个外层的高度, 内部的元素高度
25
+ // 默认的高度
26
+ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>, ColumnProps>((props: ColumnProps, ref) => {
27
+ const { children, selectedIndex, onColumnLayoutChange, onSelectChange, getInnerLayout, style, wrapperStyle, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props
28
+ // PickerViewColumn
29
+ const {
30
+ normalStyle,
31
+ hasVarDec,
32
+ varContextRef,
33
+ hasSelfPercent,
34
+ setWidth,
35
+ setHeight
36
+ } = useTransformStyle(style, { enableVar, externalVarContext })
37
+ const { textStyle } = splitStyle(normalStyle)
38
+ const { textProps } = splitProps(props)
39
+ // const { innerStyle } = splitStyle(normalStyle)
40
+ // scrollView的ref
41
+ const { nodeRef: scrollViewRef } = useNodesRef(props, ref, {})
42
+ // 每个元素的高度
43
+ let [itemH, setItemH] = useState(0)
44
+
45
+ useEffect(() => {
46
+ if (selectedIndex && itemH) {
47
+ const offsetY = selectedIndex * itemH
48
+ scrollViewRef.current?.scrollTo({ x: 0, y: offsetY, animated: true })
49
+ }
50
+ }, [selectedIndex, itemH])
51
+
52
+ const onScrollViewLayout = () => {
53
+ getInnerLayout && getInnerLayout(layoutRef)
54
+ }
55
+
56
+ const {
57
+ // 存储layout布局信息
58
+ layoutRef,
59
+ layoutProps
60
+ } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout: onScrollViewLayout })
61
+
62
+ const onItemLayout = (e: LayoutChangeEvent) => {
63
+ const layout = e.nativeEvent.layout
64
+ if (layout.height && itemH !== layout.height) {
65
+ itemH = layout.height
66
+ setItemH(layout.height)
67
+ onColumnLayoutChange && onColumnLayoutChange({ height: layout.height * 5 })
68
+ }
69
+ }
70
+
71
+ const onMomentumScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
72
+ if (scrollViewRef && itemH) {
73
+ const { y: scrollY } = e.nativeEvent.contentOffset
74
+ const selIndex = Math.floor(scrollY / itemH)
75
+ onSelectChange(selIndex)
76
+ }
77
+ }
78
+
79
+ const renderInnerchild = () => {
80
+ // Fragment 节点
81
+ let realElement: Array<ReactNode> = []
82
+ const getRealChilds = () => {
83
+ if (Array.isArray(children)) {
84
+ realElement = children
85
+ } else {
86
+ const tempChild = children as ReactElement
87
+ if (tempChild.props.children && tempChild.props.children) {
88
+ realElement = tempChild.props.children
89
+ } else {
90
+ realElement = [children]
91
+ }
92
+ }
93
+ return realElement
94
+ }
95
+
96
+ const realChilds = getRealChilds()
97
+ const arrChild = realChilds.map((item: React.ReactNode, index: number) => {
98
+ const InnerProps = index === 0 ? { onLayout: onItemLayout } : {}
99
+ const strKey = 'picker' + props.prefix + '-column' + index
100
+ const arrHeight = (wrapperStyle.itemHeight + '').match(/\d+/g) || []
101
+ const iHeight = (arrHeight[0] || defaultItemHeight) as number
102
+ return <View key={strKey} {...InnerProps} style={[{ height: iHeight, width: '100%' }]}>
103
+ {wrapChildren(
104
+ {
105
+ children: item
106
+ },
107
+ {
108
+ hasVarDec,
109
+ varContext: varContextRef.current,
110
+ textStyle,
111
+ textProps
112
+ }
113
+ )}
114
+ </View>
115
+ })
116
+ const totalHeight = itemH * 5
117
+ if (wrapperStyle.height && totalHeight !== wrapperStyle.height) {
118
+ const fix = Math.ceil((totalHeight - wrapperStyle.height) / 2)
119
+ arrChild.unshift(<View key="picker-column-0" style={[{ height: itemH - fix }]}></View>)
120
+ arrChild.unshift(<View key="picker-column-1" style={[{ height: itemH }]}></View>)
121
+ arrChild.push(<View key="picker-column-2" style={[{ height: itemH }]}></View>)
122
+ arrChild.push(<View key="picker-column-3" style={[{ height: itemH - fix }]}></View>)
123
+ } else {
124
+ arrChild.unshift(<View key="picker-column-0" style={[{ height: itemH }]}></View>)
125
+ arrChild.unshift(<View key="picker-column-1" style={[{ height: itemH }]}></View>)
126
+ arrChild.push(<View key="picker-column-2" style={[{ height: itemH }]}></View>)
127
+ arrChild.push(<View key="picker-column-3" style={[{ height: itemH }]}></View>)
128
+ }
129
+ return arrChild
130
+ }
131
+
132
+ const renderScollView = () => {
133
+ return (<Animated.ScrollView
134
+ horizontal={false}
135
+ ref={scrollViewRef}
136
+ bounces={false}
137
+ scrollsToTop={false}
138
+ removeClippedSubviews={true}
139
+ showsHorizontalScrollIndicator={false}
140
+ showsVerticalScrollIndicator={false}
141
+ pagingEnabled={false}
142
+ snapToInterval={itemH}
143
+ automaticallyAdjustContentInsets={false}
144
+ {...layoutProps}
145
+ onMomentumScrollEnd={onMomentumScrollEnd}>
146
+ {renderInnerchild()}
147
+ </Animated.ScrollView>)
148
+ }
149
+
150
+ return (<SafeAreaView style={[{ display: 'flex', flex: 1 }]}>
151
+ { renderScollView() }
152
+ </SafeAreaView>)
153
+ })
154
+
155
+ _PickerViewColumn.displayName = 'mpx-picker-view-column'
156
+ export default _PickerViewColumn