@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.
- package/lib/config.js +2 -1
- package/lib/index.js +1 -1
- package/lib/platform/json/wx/index.js +6 -3
- package/lib/platform/style/wx/index.js +23 -12
- package/lib/platform/template/wx/component-config/button.js +19 -2
- package/lib/platform/template/wx/component-config/canvas.js +4 -0
- package/lib/platform/template/wx/component-config/checkbox-group.js +4 -0
- package/lib/platform/template/wx/component-config/checkbox.js +4 -0
- package/lib/platform/template/wx/component-config/cover-image.js +7 -1
- package/lib/platform/template/wx/component-config/cover-view.js +4 -0
- package/lib/platform/template/wx/component-config/fix-component-name.js +3 -2
- package/lib/platform/template/wx/component-config/form.js +7 -1
- package/lib/platform/template/wx/component-config/icon.js +4 -0
- package/lib/platform/template/wx/component-config/image.js +7 -1
- package/lib/platform/template/wx/component-config/input.js +18 -3
- package/lib/platform/template/wx/component-config/label.js +4 -0
- package/lib/platform/template/wx/component-config/movable-area.js +7 -1
- package/lib/platform/template/wx/component-config/movable-view.js +12 -3
- package/lib/platform/template/wx/component-config/navigator.js +4 -0
- package/lib/platform/template/wx/component-config/picker-view-column.js +4 -0
- package/lib/platform/template/wx/component-config/picker-view.js +7 -1
- package/lib/platform/template/wx/component-config/picker.js +7 -1
- package/lib/platform/template/wx/component-config/radio-group.js +4 -0
- package/lib/platform/template/wx/component-config/radio.js +4 -0
- package/lib/platform/template/wx/component-config/rich-text.js +4 -0
- package/lib/platform/template/wx/component-config/root-portal.js +4 -0
- package/lib/platform/template/wx/component-config/scroll-view.js +10 -2
- package/lib/platform/template/wx/component-config/swiper-item.js +7 -1
- package/lib/platform/template/wx/component-config/swiper.js +12 -3
- package/lib/platform/template/wx/component-config/switch.js +4 -0
- package/lib/platform/template/wx/component-config/text.js +24 -3
- package/lib/platform/template/wx/component-config/textarea.js +17 -2
- package/lib/platform/template/wx/component-config/unsupported.js +7 -0
- package/lib/platform/template/wx/component-config/video.js +10 -2
- package/lib/platform/template/wx/component-config/view.js +11 -1
- package/lib/platform/template/wx/component-config/web-view.js +4 -0
- package/lib/platform/template/wx/index.js +42 -75
- package/lib/react/processScript.js +1 -18
- package/lib/runtime/components/react/dist/event.config.js +1 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +18 -7
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-inline-text.jsx +11 -0
- package/lib/runtime/components/react/dist/mpx-input.jsx +3 -6
- package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-picker/date.jsx +194 -68
- package/lib/runtime/components/react/dist/mpx-picker/dateData.js +17 -0
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +178 -96
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +79 -139
- package/lib/runtime/components/react/dist/mpx-picker/region.jsx +190 -90
- package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +60 -75
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +100 -228
- package/lib/runtime/components/react/dist/{mpx-picker-view.jsx → mpx-picker-view/index.jsx} +3 -3
- package/lib/runtime/components/react/dist/{mpx-picker-view-column.jsx → mpx-picker-view-column/index.jsx} +64 -16
- package/lib/runtime/components/react/dist/{mpx-picker-view-column-item.jsx → mpx-picker-view-column/pickerViewColumnItem.jsx} +8 -5
- package/lib/runtime/components/react/dist/{pickerFaces.js → mpx-picker-view-column/pickerViewFaces.js} +6 -0
- package/lib/runtime/components/react/dist/mpx-popup/index.jsx +61 -0
- package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +92 -0
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +192 -25
- package/lib/runtime/components/react/dist/mpx-simple-text.jsx +8 -7
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +11 -15
- package/lib/runtime/components/react/dist/mpx-video.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +7 -4
- package/lib/runtime/components/react/dist/utils.jsx +2 -1
- package/lib/runtime/components/react/event.config.ts +2 -0
- package/lib/runtime/components/react/getInnerListeners.ts +28 -25
- package/lib/runtime/components/react/mpx-canvas/index.tsx +2 -2
- package/lib/runtime/components/react/mpx-inline-text.tsx +18 -0
- package/lib/runtime/components/react/mpx-input.tsx +2 -6
- package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +1 -1
- package/lib/runtime/components/react/mpx-picker/date.tsx +226 -69
- package/lib/runtime/components/react/mpx-picker/dateData.ts +22 -0
- package/lib/runtime/components/react/mpx-picker/index.tsx +239 -118
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +96 -139
- package/lib/runtime/components/react/mpx-picker/region.tsx +217 -89
- package/lib/runtime/components/react/mpx-picker/selector.tsx +75 -80
- package/lib/runtime/components/react/mpx-picker/time.tsx +119 -236
- package/lib/runtime/components/react/mpx-picker/type.ts +85 -71
- package/lib/runtime/components/react/{mpx-picker-view.tsx → mpx-picker-view/index.tsx} +7 -7
- package/lib/runtime/components/react/{mpx-picker-view-column.tsx → mpx-picker-view-column/index.tsx} +70 -19
- package/lib/runtime/components/react/{mpx-picker-view-column-item.tsx → mpx-picker-view-column/pickerViewColumnItem.tsx} +8 -5
- package/lib/runtime/components/react/{pickerFaces.ts → mpx-picker-view-column/pickerViewFaces.ts} +7 -0
- package/lib/runtime/components/react/mpx-popup/index.tsx +86 -0
- package/lib/runtime/components/react/mpx-popup/popupBase.tsx +130 -0
- package/lib/runtime/components/react/mpx-scroll-view.tsx +249 -43
- package/lib/runtime/components/react/mpx-simple-text.tsx +10 -8
- package/lib/runtime/components/react/mpx-simple-view.tsx +11 -16
- package/lib/runtime/components/react/mpx-video.tsx +2 -2
- package/lib/runtime/components/react/mpx-web-view.tsx +7 -4
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +5 -1
- package/lib/runtime/components/react/types/global.d.ts +1 -1
- package/lib/runtime/components/react/utils.tsx +3 -2
- package/lib/runtime/components/web/mini-video-controls.min.js +1 -1
- package/lib/runtime/components/web/mpx-input.vue +1 -1
- package/lib/runtime/stringify.wxs +2 -2
- package/lib/template-compiler/compiler.js +8 -8
- package/lib/utils/env.js +1 -1
- package/package.json +4 -5
- /package/lib/runtime/components/react/dist/{pickerVIewContext.js → mpx-picker-view/pickerVIewContext.js} +0 -0
- /package/lib/runtime/components/react/dist/{pickerViewIndicator.jsx → mpx-picker-view-column/pickerViewIndicator.jsx} +0 -0
- /package/lib/runtime/components/react/dist/{pickerViewMask.jsx → mpx-picker-view-column/pickerViewMask.jsx} +0 -0
- /package/lib/runtime/components/react/{pickerVIewContext.ts → mpx-picker-view/pickerVIewContext.ts} +0 -0
- /package/lib/runtime/components/react/{pickerViewIndicator.tsx → mpx-picker-view-column/pickerViewIndicator.tsx} +0 -0
- /package/lib/runtime/components/react/{pickerViewMask.tsx → mpx-picker-view-column/pickerViewMask.tsx} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useRef, useMemo, RefObject } from 'react'
|
|
2
2
|
import { hasOwn, collectDataset } from '@mpxjs/utils'
|
|
3
3
|
import { omit, extendObject, useNavigation } from './utils'
|
|
4
|
-
import eventConfigMap, { TAP_EVENTS } from './event.config'
|
|
4
|
+
import eventConfigMap, { TAP_EVENTS, LONGPRESS_EVENTS } from './event.config'
|
|
5
5
|
import {
|
|
6
6
|
Props,
|
|
7
7
|
AdditionalProps,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
InnerRef,
|
|
11
11
|
SetTimeoutReturnType,
|
|
12
12
|
LayoutRef,
|
|
13
|
-
|
|
13
|
+
ExtendedNativeTouchEvent,
|
|
14
14
|
Navigation
|
|
15
15
|
} from './types/getInnerListeners'
|
|
16
16
|
|
|
@@ -20,7 +20,7 @@ const globalEventState = {
|
|
|
20
20
|
|
|
21
21
|
const getTouchEvent = (
|
|
22
22
|
type: string,
|
|
23
|
-
event:
|
|
23
|
+
event: ExtendedNativeTouchEvent,
|
|
24
24
|
props: Props,
|
|
25
25
|
config: UseInnerPropsConfig,
|
|
26
26
|
navigation: Navigation
|
|
@@ -110,7 +110,7 @@ export const getCustomEvent = (
|
|
|
110
110
|
function handleEmitEvent (
|
|
111
111
|
events: string[],
|
|
112
112
|
type: string,
|
|
113
|
-
oe:
|
|
113
|
+
oe: ExtendedNativeTouchEvent,
|
|
114
114
|
propsRef: Record<string, any>,
|
|
115
115
|
config: UseInnerPropsConfig,
|
|
116
116
|
navigation: Navigation
|
|
@@ -118,8 +118,22 @@ function handleEmitEvent (
|
|
|
118
118
|
events.forEach((event) => {
|
|
119
119
|
if (propsRef.current[event]) {
|
|
120
120
|
const match = /^(catch|capture-catch):?(.*?)(?:\.(.*))?$/.exec(event)
|
|
121
|
+
// 检查是否已经被上层的 catch 阻止
|
|
122
|
+
if ((type === 'tap' || type === 'longpress') && oe._stoppedEventTypes?.has(type)) {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
121
125
|
if (match) {
|
|
122
|
-
|
|
126
|
+
const eventBase = match[2] || ''
|
|
127
|
+
if (eventBase === 'tap' || eventBase === 'longpress') {
|
|
128
|
+
// 为 tap、longpress 添加标记,影响后续的冒泡
|
|
129
|
+
if (!oe._stoppedEventTypes) {
|
|
130
|
+
oe._stoppedEventTypes = new Set()
|
|
131
|
+
}
|
|
132
|
+
oe._stoppedEventTypes.add(eventBase)
|
|
133
|
+
} else {
|
|
134
|
+
// 原生 touch 事件使用 stopPropagation
|
|
135
|
+
oe.stopPropagation()
|
|
136
|
+
}
|
|
123
137
|
}
|
|
124
138
|
propsRef.current[event](
|
|
125
139
|
getTouchEvent(type, oe, propsRef.current, config, navigation)
|
|
@@ -128,7 +142,7 @@ function handleEmitEvent (
|
|
|
128
142
|
})
|
|
129
143
|
}
|
|
130
144
|
|
|
131
|
-
function checkIsNeedPress (e:
|
|
145
|
+
function checkIsNeedPress (e: ExtendedNativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>) {
|
|
132
146
|
const tapDetailInfo = ref.current!.mpxPressInfo.detail || { x: 0, y: 0 }
|
|
133
147
|
const nativeEvent = e.nativeEvent
|
|
134
148
|
const currentPageX = nativeEvent.changedTouches[0].pageX
|
|
@@ -144,7 +158,7 @@ function checkIsNeedPress (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
144
158
|
}
|
|
145
159
|
}
|
|
146
160
|
|
|
147
|
-
function handleTouchstart (e:
|
|
161
|
+
function handleTouchstart (e: ExtendedNativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) {
|
|
148
162
|
e.persist()
|
|
149
163
|
const bubbleTouchEvent = ['catchtouchstart', 'bindtouchstart']
|
|
150
164
|
const bubblePressEvent = ['catchlongpress', 'bindlongpress']
|
|
@@ -168,18 +182,7 @@ function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
168
182
|
const currentPressEvent =
|
|
169
183
|
type === 'bubble' ? bubblePressEvent : capturePressEvent
|
|
170
184
|
handleEmitEvent(currentTouchEvent, 'touchstart', e, propsRef, config, navigation)
|
|
171
|
-
|
|
172
|
-
catchlongpress,
|
|
173
|
-
bindlongpress,
|
|
174
|
-
'capture-catchlongpress': captureCatchlongpress,
|
|
175
|
-
'capture-bindlongpress': captureBindlongpress
|
|
176
|
-
} = propsRef.current
|
|
177
|
-
if (
|
|
178
|
-
catchlongpress ||
|
|
179
|
-
bindlongpress ||
|
|
180
|
-
captureCatchlongpress ||
|
|
181
|
-
captureBindlongpress
|
|
182
|
-
) {
|
|
185
|
+
if (LONGPRESS_EVENTS.some(eventName => propsRef.current[eventName])) {
|
|
183
186
|
ref.current!.startTimer[type] = setTimeout(() => {
|
|
184
187
|
// 只要触发过longpress, 全局就不再触发tap
|
|
185
188
|
globalEventState.needPress = false
|
|
@@ -188,7 +191,7 @@ function handleTouchstart (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
188
191
|
}
|
|
189
192
|
}
|
|
190
193
|
|
|
191
|
-
function handleTouchmove (e:
|
|
194
|
+
function handleTouchmove (e: ExtendedNativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) {
|
|
192
195
|
const bubbleTouchEvent = ['catchtouchmove', 'bindtouchmove']
|
|
193
196
|
const captureTouchEvent = [
|
|
194
197
|
'capture-catchtouchmove',
|
|
@@ -202,7 +205,7 @@ function handleTouchmove (e: NativeTouchEvent, type: 'bubble' | 'capture', ref:
|
|
|
202
205
|
}
|
|
203
206
|
}
|
|
204
207
|
|
|
205
|
-
function handleTouchend (e:
|
|
208
|
+
function handleTouchend (e: ExtendedNativeTouchEvent, type: 'bubble' | 'capture', ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) {
|
|
206
209
|
// move event may not be triggered
|
|
207
210
|
if (TAP_EVENTS.some(eventName => propsRef.current[eventName])) {
|
|
208
211
|
checkIsNeedPress(e, type, ref)
|
|
@@ -231,7 +234,7 @@ function handleTouchend (e: NativeTouchEvent, type: 'bubble' | 'capture', ref: R
|
|
|
231
234
|
}
|
|
232
235
|
|
|
233
236
|
function handleTouchcancel (
|
|
234
|
-
e:
|
|
237
|
+
e: ExtendedNativeTouchEvent,
|
|
235
238
|
type: 'bubble' | 'capture',
|
|
236
239
|
ref: RefObject<InnerRef>,
|
|
237
240
|
propsRef: Record<string, any>,
|
|
@@ -252,7 +255,7 @@ function handleTouchcancel (
|
|
|
252
255
|
}
|
|
253
256
|
|
|
254
257
|
function createTouchEventHandler (eventName: 'onTouchStart'|'onTouchMove'|'onTouchEnd'|'onTouchCancel', type: 'bubble' | 'capture') {
|
|
255
|
-
return (e:
|
|
258
|
+
return (e: ExtendedNativeTouchEvent, ref: RefObject<InnerRef>, propsRef: Record<string, any>, config: UseInnerPropsConfig, navigation: Navigation) => {
|
|
256
259
|
const handlerMap = {
|
|
257
260
|
onTouchStart: handleTouchstart,
|
|
258
261
|
onTouchMove: handleTouchmove,
|
|
@@ -341,11 +344,11 @@ const useInnerProps = (
|
|
|
341
344
|
return acc
|
|
342
345
|
}, [])
|
|
343
346
|
const finalEventKeys = [...new Set(transformedEventKeys)]
|
|
344
|
-
const events: Record<string, (e:
|
|
347
|
+
const events: Record<string, (e: ExtendedNativeTouchEvent) => void> = {}
|
|
345
348
|
|
|
346
349
|
touchEventList.forEach((item) => {
|
|
347
350
|
if (finalEventKeys.includes(item.eventName)) {
|
|
348
|
-
events[item.eventName] = (e:
|
|
351
|
+
events[item.eventName] = (e: ExtendedNativeTouchEvent) =>
|
|
349
352
|
item.handler(e, ref, propsRef, config, navigation)
|
|
350
353
|
}
|
|
351
354
|
})
|
|
@@ -251,8 +251,8 @@ const _Canvas = forwardRef<HandlerRef<CanvasProps & View, CanvasProps>, CanvasPr
|
|
|
251
251
|
context: context2D
|
|
252
252
|
})
|
|
253
253
|
|
|
254
|
-
if (
|
|
255
|
-
const isAndroid9 = Platform.Version >= 28
|
|
254
|
+
if (__mpx_mode__ !== 'ios') {
|
|
255
|
+
const isAndroid9 = Platform.Version as number >= 28
|
|
256
256
|
return createElement(View, innerProps, createElement(
|
|
257
257
|
WebView,
|
|
258
258
|
{
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Text, TextProps } from 'react-native'
|
|
2
|
+
import { JSX, createElement } from 'react'
|
|
3
|
+
|
|
4
|
+
import { extendObject } from './utils'
|
|
5
|
+
|
|
6
|
+
const InlineText = (props: TextProps): JSX.Element => {
|
|
7
|
+
const {
|
|
8
|
+
allowFontScaling = false
|
|
9
|
+
} = props
|
|
10
|
+
|
|
11
|
+
return createElement(Text, extendObject({}, props, {
|
|
12
|
+
allowFontScaling
|
|
13
|
+
}))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
InlineText.displayName = 'MpxInlineText'
|
|
17
|
+
|
|
18
|
+
export default InlineText
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
TextInputSubmitEditingEventData
|
|
55
55
|
} from 'react-native'
|
|
56
56
|
import { warn } from '@mpxjs/utils'
|
|
57
|
-
import { useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils'
|
|
57
|
+
import { useUpdateEffect, useTransformStyle, useLayout, extendObject, isIOS } from './utils'
|
|
58
58
|
import useInnerProps, { getCustomEvent } from './getInnerListeners'
|
|
59
59
|
import useNodesRef, { HandlerRef } from './useNodesRef'
|
|
60
60
|
import { FormContext, FormFieldValue, KeyboardAvoidContext } from './context'
|
|
@@ -121,11 +121,7 @@ const keyboardTypeMap: Record<Type, string> = {
|
|
|
121
121
|
text: 'default',
|
|
122
122
|
number: 'numeric',
|
|
123
123
|
idcard: 'default',
|
|
124
|
-
digit:
|
|
125
|
-
Platform.select({
|
|
126
|
-
ios: 'decimal-pad',
|
|
127
|
-
android: 'numeric'
|
|
128
|
-
}) || ''
|
|
124
|
+
digit: isIOS ? 'decimal-pad' : 'numeric'
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps>((props: FinalInputProps, ref): JSX.Element => {
|
|
@@ -3,6 +3,7 @@ import { DimensionValue, EmitterSubscription, Keyboard, Platform, View, ViewStyl
|
|
|
3
3
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, runOnJS } from 'react-native-reanimated'
|
|
4
4
|
import { GestureDetector, Gesture } from 'react-native-gesture-handler'
|
|
5
5
|
import { KeyboardAvoidContext } from './context'
|
|
6
|
+
import { isIOS } from './utils'
|
|
6
7
|
|
|
7
8
|
type KeyboardAvoidViewProps = {
|
|
8
9
|
children?: ReactNode
|
|
@@ -11,7 +12,6 @@ type KeyboardAvoidViewProps = {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: KeyboardAvoidViewProps) => {
|
|
14
|
-
const isIOS = Platform.OS === 'ios'
|
|
15
15
|
const duration = isIOS ? 250 : 300
|
|
16
16
|
const easing = isIOS ? Easing.inOut(Easing.ease) : Easing.out(Easing.quad)
|
|
17
17
|
|
|
@@ -1,86 +1,243 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { DateProps,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import React, { forwardRef, useCallback, useMemo, useRef, useState, useEffect, useImperativeHandle } from 'react'
|
|
2
|
+
import { StyleSheet, Text, View } from 'react-native'
|
|
3
|
+
import MpxPickerView from '../mpx-picker-view'
|
|
4
|
+
import MpxPickerViewColumn from '../mpx-picker-view-column'
|
|
5
|
+
import { DateProps, TimeValue } from './type'
|
|
6
|
+
import { HandlerRef } from '../useNodesRef'
|
|
7
|
+
import { useUpdateEffect } from '../utils'
|
|
8
|
+
import { years, months, daysInMonth, wrapDate, daysInMonthLength, START_YEAR, END_YEAR } from './dateData'
|
|
9
|
+
|
|
10
|
+
type FormatObj = {
|
|
11
|
+
indexArr: number[]
|
|
12
|
+
rangeArr: string[][]
|
|
13
|
+
nameArr?: string[]
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
const START_DATE: TimeValue = `${START_YEAR}-01-01`
|
|
17
|
+
const END_DATE: TimeValue = `${END_YEAR}-12-31`
|
|
18
|
+
const START_DATE_ARR = [START_YEAR, 1, 1]
|
|
19
|
+
const END_DATE_ARR = [END_YEAR, 12, 31]
|
|
20
|
+
|
|
21
|
+
const styles = StyleSheet.create({
|
|
22
|
+
pickerContainer: {
|
|
23
|
+
height: 240,
|
|
24
|
+
paddingHorizontal: 10,
|
|
25
|
+
borderTopLeftRadius: 10,
|
|
26
|
+
borderTopRightRadius: 10
|
|
27
|
+
},
|
|
28
|
+
pickerIndicator: {
|
|
29
|
+
height: 45
|
|
30
|
+
},
|
|
31
|
+
pickerItem: {
|
|
32
|
+
fontSize: 16,
|
|
33
|
+
lineHeight: 45,
|
|
34
|
+
textAlign: 'center'
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const getColumnLength = (fields: DateProps['fields'] = 'day') => {
|
|
39
|
+
return fields === 'year' ? 1 : fields === 'month' ? 2 : 3
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const compareDateStr = (date1: TimeValue | number[], date2: TimeValue | number[]) => {
|
|
43
|
+
const [y1 = START_YEAR, m1 = 0, d1 = 0] = typeof date1 === 'string' ? date1.split('-').map(Number) : date1
|
|
44
|
+
const [y2 = START_YEAR, m2 = 0, d2 = 0] = typeof date2 === 'string' ? date2.split('-').map(Number) : date2
|
|
45
|
+
const num1 = y1 * 10000 + m1 * 100 + d1
|
|
46
|
+
const num2 = y2 * 10000 + m2 * 100 + d2
|
|
47
|
+
if (num1 === num2) {
|
|
48
|
+
return 0
|
|
25
49
|
}
|
|
26
|
-
return
|
|
50
|
+
return num1 > num2 ? 1 : -1
|
|
27
51
|
}
|
|
28
52
|
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const layoutRef = useRef({})
|
|
34
|
-
const viewRef = useRef<View>(null)
|
|
35
|
-
const nodeRef = useRef<View>(null)
|
|
36
|
-
useNodesRef<View, DateProps>(props, ref, nodeRef, {
|
|
37
|
-
style
|
|
38
|
-
})
|
|
53
|
+
const getDateArr = (date: TimeValue | number[]): number[] => {
|
|
54
|
+
const [y, m, d] = typeof date === 'string' ? date.split('-').map(Number) : date
|
|
55
|
+
return [y || 0, m || 0, d || 0]
|
|
56
|
+
}
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
const calibrateDate = (date: TimeValue | number[], start: TimeValue, end: TimeValue): number[] => {
|
|
59
|
+
let startArr = getDateArr(start)
|
|
60
|
+
let endArr = getDateArr(end)
|
|
61
|
+
let dateArr = getDateArr(date)
|
|
62
|
+
if (compareDateStr(startArr, endArr) > 0) {
|
|
63
|
+
startArr = START_DATE_ARR
|
|
64
|
+
}
|
|
65
|
+
if (compareDateStr(endArr, startArr) < 0) {
|
|
66
|
+
endArr = END_DATE_ARR
|
|
67
|
+
}
|
|
68
|
+
if (compareDateStr(start, end) > 0) {
|
|
69
|
+
startArr = START_DATE_ARR
|
|
70
|
+
endArr = END_DATE_ARR
|
|
49
71
|
}
|
|
72
|
+
if (compareDateStr(dateArr, endArr) > 0) {
|
|
73
|
+
dateArr = endArr
|
|
74
|
+
}
|
|
75
|
+
if (compareDateStr(dateArr, startArr) < 0) {
|
|
76
|
+
dateArr = startArr
|
|
77
|
+
}
|
|
78
|
+
return dateArr
|
|
79
|
+
}
|
|
50
80
|
|
|
51
|
-
|
|
52
|
-
|
|
81
|
+
const initDateStr2Arr = (dateStr: TimeValue | number[], start: TimeValue, end: TimeValue): number[] => {
|
|
82
|
+
if (!dateStr) {
|
|
83
|
+
const today = new Date()
|
|
84
|
+
const todayYear = today.getFullYear()
|
|
85
|
+
const todayMonth = today.getMonth() + 1
|
|
86
|
+
const todayDay = today.getDate()
|
|
87
|
+
dateStr = [todayYear, todayMonth, todayDay]
|
|
53
88
|
}
|
|
89
|
+
const [y, m, d] = getDateArr(dateStr)
|
|
90
|
+
const year = Math.min(Math.max(START_YEAR, y), END_YEAR)
|
|
91
|
+
const month = Math.min(Math.max(1, m), 12)
|
|
92
|
+
const day = Math.min(Math.max(1, d), daysInMonthLength(year, month))
|
|
93
|
+
const res = [year, month, day]
|
|
94
|
+
return calibrateDate(res, start, end)
|
|
95
|
+
}
|
|
54
96
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
97
|
+
const valueStr2Obj = (
|
|
98
|
+
_value: TimeValue | number[] = '', // eg: 2025-2-12
|
|
99
|
+
limit: number,
|
|
100
|
+
start: TimeValue,
|
|
101
|
+
end: TimeValue
|
|
102
|
+
): FormatObj => {
|
|
103
|
+
const [y, m, d] = initDateStr2Arr(_value, start, end)
|
|
104
|
+
const ans = {
|
|
105
|
+
indexArr: [y - START_YEAR],
|
|
106
|
+
rangeArr: [years]
|
|
107
|
+
}
|
|
108
|
+
if (limit === 2) {
|
|
109
|
+
ans.indexArr.push(m - 1)
|
|
110
|
+
ans.rangeArr.push(months)
|
|
111
|
+
} else if (limit === 3) {
|
|
112
|
+
const days = daysInMonth(y, m)
|
|
113
|
+
ans.indexArr.push(m - 1, d - 1)
|
|
114
|
+
ans.rangeArr.push(months, days)
|
|
60
115
|
}
|
|
116
|
+
return ans
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const valueChanged2Obj = (currentObj: FormatObj, value: number[], limit = 3) => {
|
|
120
|
+
const currentValue = currentObj.indexArr
|
|
121
|
+
const rangeArr = currentObj.rangeArr
|
|
61
122
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
onDismiss,
|
|
70
|
-
disabled
|
|
123
|
+
if (limit === 3 && (currentValue[0] !== value[0] || currentValue[1] !== value[1])) {
|
|
124
|
+
const days = daysInMonth(value[0], value[1] + 1)
|
|
125
|
+
rangeArr[2] = days
|
|
126
|
+
const maxIndex = days.length - 1
|
|
127
|
+
if (value[2] > maxIndex) {
|
|
128
|
+
value[2] = maxIndex
|
|
129
|
+
}
|
|
71
130
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
indexArr: value,
|
|
134
|
+
rangeArr
|
|
75
135
|
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const valueChanged2Obj2 = (value: number[], limit = 3, start: TimeValue, end: TimeValue) => {
|
|
139
|
+
const y = value[0] + START_YEAR
|
|
140
|
+
const m = value[1] + 1
|
|
141
|
+
const d = value[2] + 1
|
|
142
|
+
return valueStr2Obj([y, m, d], limit, start, end)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const valueNum2String = (value: number[]) => {
|
|
146
|
+
return value.map((item, index) => {
|
|
147
|
+
if (index === 0) {
|
|
148
|
+
return item + START_YEAR
|
|
149
|
+
} else {
|
|
150
|
+
return wrapDate()(item + 1)
|
|
151
|
+
}
|
|
152
|
+
}).join('-')
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const hasDiff = (currentValue: number[], value: number[], limit = 3) => {
|
|
156
|
+
for (let i = 0; i < limit; i++) {
|
|
157
|
+
if (currentValue[i] !== value[i]) {
|
|
158
|
+
return true
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const PickerDate = forwardRef<
|
|
165
|
+
HandlerRef<View, DateProps>,
|
|
166
|
+
DateProps
|
|
167
|
+
>((props: DateProps, ref): React.JSX.Element => {
|
|
168
|
+
const { value = '', start = START_DATE, end = END_DATE, fields, bindchange } = props
|
|
169
|
+
const nodeRef = useRef(null)
|
|
170
|
+
const columnLength = useMemo(() => getColumnLength(fields), [fields])
|
|
171
|
+
const [formatObj, setFormatObj] = useState<FormatObj>(valueStr2Obj(value, columnLength, start, end))
|
|
172
|
+
const timerRef = useRef<NodeJS.Timeout | null>(null)
|
|
173
|
+
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
return () => {
|
|
176
|
+
timerRef.current && clearTimeout(timerRef.current)
|
|
177
|
+
}
|
|
178
|
+
}, [])
|
|
179
|
+
|
|
180
|
+
useUpdateEffect(() => {
|
|
181
|
+
const calibratedValue = valueStr2Obj(value, columnLength, start, end)
|
|
182
|
+
setFormatObj(calibratedValue)
|
|
183
|
+
}, [value, columnLength, start, end])
|
|
184
|
+
|
|
185
|
+
const updateValue = useCallback((value: TimeValue = '') => {
|
|
186
|
+
const calibratedValue = valueStr2Obj(value, columnLength, start, end)
|
|
187
|
+
setFormatObj(calibratedValue)
|
|
188
|
+
}, [columnLength, start, end])
|
|
189
|
+
|
|
190
|
+
const _props = useRef(props)
|
|
191
|
+
_props.current = props
|
|
192
|
+
useImperativeHandle(ref, () => ({
|
|
193
|
+
updateValue,
|
|
194
|
+
getNodeInstance: () => ({
|
|
195
|
+
props: _props,
|
|
196
|
+
nodeRef,
|
|
197
|
+
instance: {
|
|
198
|
+
style: {}
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
}))
|
|
202
|
+
|
|
203
|
+
const onChange = useCallback((e: { detail: { value: number[] } }) => {
|
|
204
|
+
const { value } = e.detail
|
|
205
|
+
const currentValue = formatObj.indexArr
|
|
206
|
+
const newObj = valueChanged2Obj(formatObj, value, columnLength)
|
|
207
|
+
if (hasDiff(currentValue, value, columnLength)) {
|
|
208
|
+
setFormatObj(newObj)
|
|
209
|
+
const newObj2 = valueChanged2Obj2(value, columnLength, start, end)
|
|
210
|
+
if (hasDiff(newObj.indexArr, newObj2.indexArr, columnLength)) {
|
|
211
|
+
timerRef.current && clearTimeout(timerRef.current)
|
|
212
|
+
timerRef.current = setTimeout(() => setFormatObj(newObj2))
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
bindchange?.({ detail: { value: valueNum2String(newObj.indexArr) } })
|
|
216
|
+
}, [formatObj, columnLength, bindchange, start, end])
|
|
217
|
+
|
|
218
|
+
const renderColumn = () => {
|
|
219
|
+
return formatObj.rangeArr?.map((item, index) => (
|
|
220
|
+
// @ts-expect-error ignore
|
|
221
|
+
<MpxPickerViewColumn key={index}>
|
|
222
|
+
{item.map((item, index) => {
|
|
223
|
+
return <Text key={index} style={styles.pickerItem}>
|
|
224
|
+
{item}
|
|
225
|
+
</Text>
|
|
226
|
+
})}
|
|
227
|
+
</MpxPickerViewColumn>
|
|
228
|
+
))
|
|
229
|
+
}
|
|
230
|
+
|
|
76
231
|
return (
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
232
|
+
<MpxPickerView
|
|
233
|
+
style={styles.pickerContainer}
|
|
234
|
+
indicator-style={styles.pickerIndicator}
|
|
235
|
+
value={formatObj.indexArr}
|
|
236
|
+
bindchange={onChange}
|
|
237
|
+
>
|
|
238
|
+
{renderColumn()}
|
|
239
|
+
</MpxPickerView>)
|
|
83
240
|
})
|
|
84
241
|
|
|
85
|
-
|
|
86
|
-
export default
|
|
242
|
+
PickerDate.displayName = 'MpxPickerDate'
|
|
243
|
+
export default PickerDate
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const wrapDate = (union = '') => (num: number) => String(num).padStart(2, '0') + union
|
|
2
|
+
|
|
3
|
+
export const START_YEAR = 1900
|
|
4
|
+
export const END_YEAR = 2099
|
|
5
|
+
|
|
6
|
+
export const years = Array.from({ length: 200 }, (_, index) => index + START_YEAR + '年')
|
|
7
|
+
|
|
8
|
+
export const months = Array.from({ length: 12 }, (_, index) => index + 1).map(wrapDate('月'))
|
|
9
|
+
|
|
10
|
+
export const daysInMonthLength = (year: number, month: number) => {
|
|
11
|
+
return month === 2
|
|
12
|
+
? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
13
|
+
? 29
|
|
14
|
+
: 28
|
|
15
|
+
: [4, 6, 9, 11].includes(month)
|
|
16
|
+
? 30
|
|
17
|
+
: 31
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const daysInMonth = (year: number, month: number) => {
|
|
21
|
+
return Array.from({ length: daysInMonthLength(year, month) }, (_, index) => index + 1).map(wrapDate('日'))
|
|
22
|
+
}
|