@fruits-chain/react-native-xiaoshu
Version:
🌈 React Native UI library
206 lines (182 loc) • 5.54 kB
text/typescript
import { useMemo } from 'react'
import { usePersistFn } from '../hooks'
import Locale from '../locale'
import type { PickerOption, PickerValue } from '../picker-view/interface'
import {
COLUMN_SERIALIZE_TYPES,
serializeMode,
getMonthDays,
toDateObject,
getDateBoundary,
} from './helper'
import type {
DatePickerColumnMode,
DatePickerColumnType,
RenderLabel,
} from './interface'
import useDateMinMax from './useDateMinMax'
export interface UseDatePickerOption {
mode: DatePickerColumnMode
value: Date
onChange: (value: Date) => void
min?: Date
max?: Date
renderLabel?: RenderLabel
}
type ColumnItem = PickerOption[]
type Columns = ColumnItem[]
type Values = number[]
const buildColumnData = (
mode: DatePickerColumnType,
start: number,
end: number,
renderLabel: RenderLabel,
// eslint-disable-next-line max-params
) => {
const items: PickerOption[] = []
for (let index = start; index <= end; index++) {
items.push({
value: index,
label: renderLabel(mode, index),
})
}
return items
}
const useDatePicker = ({
mode,
value,
onChange,
min,
max,
renderLabel,
}: UseDatePickerOption) => {
const locale = Locale.useLocale().DatePickerView
const modes = useMemo(
() => serializeMode(mode.split('-') as DatePickerColumnType[]),
[mode],
)
const [minDate, maxDate] = useDateMinMax(mode, min, max)
const renderLabelPersistFn: RenderLabel = usePersistFn((t, n) => {
if (renderLabel) {
return renderLabel(t, n)
}
switch (t) {
case 'Y':
return `${n}${locale.labelYear}`
case 'M':
return `${n}${locale.labelMonth}`
case 'D':
return `${n}${locale.labelDay}`
case 'h':
return `${n}${locale.labelHour}`
case 'm':
return `${n}${locale.labelMinute}`
case 's':
return `${n}${locale.labelSecond}`
default:
return `${n}`
}
})
const [pickerValues, pickerColumns] = useMemo<[Values, Columns]>(() => {
const _columns: Columns = []
const _values: Values = []
const boundary = getDateBoundary(value, modes, {
defaultMin: minDate,
defaultMax: maxDate,
min,
max,
})
const valueDateObject = toDateObject(value)
// 根据格式化方式挑选值
COLUMN_SERIALIZE_TYPES.forEach(key => {
const ab = boundary[key]
const a = key === 'M' ? ab[0] + 1 : ab[0]
const b = key === 'M' ? ab[1] + 1 : ab[1]
const v = key === 'M' ? valueDateObject[key] + 1 : valueDateObject[key]
_values.push(v)
_columns.push(buildColumnData(key, a, b, renderLabelPersistFn))
})
// 挑选值
const _pickerColumns: Columns = []
const _pickerValues: Values = []
modes.forEach(key => {
const keyIndex = COLUMN_SERIALIZE_TYPES.findIndex(cst => cst === key)
_pickerColumns.push(_columns[keyIndex])
_pickerValues.push(_values[keyIndex])
})
return [_pickerValues, _pickerColumns]
}, [max, maxDate, min, minDate, modes, renderLabelPersistFn, value])
const onChangePicker = usePersistFn((v: PickerValue[]) => {
// console.log('values =>>>> ', v)
const newValue = new Date(value)
modes.forEach((key, index) => {
const num = v[index] as number
switch (key) {
case 'Y':
newValue.setFullYear(num)
break
case 'M': {
// 对 D 进行修正
const days = getMonthDays(newValue.getFullYear(), num)
const valueDays = newValue.getDate()
newValue.setMonth(num - 1, valueDays > days ? days : valueDays)
break
}
case 'D': {
// 对 D 进行修正
const days = getMonthDays(
newValue.getFullYear(),
newValue.getMonth() + 1,
)
newValue.setDate(num > days ? days : num)
break
}
case 'h':
newValue.setHours(num)
break
case 'm':
newValue.setMinutes(num)
break
case 's':
newValue.setSeconds(num)
break
default:
break
}
})
// console.log('newValue???? => ', toDateObject(newValue))
// // 最后边界值判断
// const _minDate = isDate(min) ? min : defaultMinDate
// const _maxDate = isDate(max) ? max : defaultMaxDate
const finallyValue =
newValue.getTime() >= minDate.getTime() &&
newValue.getTime() <= maxDate.getTime()
? newValue
: newValue.getTime() < minDate.getTime()
? minDate
: maxDate
// console.log('_minDate => ', toDateObject(_minDate))
// console.log('_maxDate => ', toDateObject(_maxDate))
// console.log('newValue => ', toDateObject(newValue))
// console.log('_minDate t => ', _minDate.getTime())
// console.log('_maxDate t => ', _maxDate.getTime())
// console.log('newValue t => ', newValue.getTime())
// console.log('finallyValue => ', toDateObject(finallyValue))
// console.log(
// newValue.getTime() >= _minDate.getTime() &&
// newValue.getTime() <= _maxDate.getTime(),
// )
// console.log(newValue.getTime() < _minDate.getTime())
// console.log('finallyValue =>>>> ', finallyValue.toString())
// console.log('finallyValue =========>>>>>>>>>>>>>>>>>>>>>>>>>')
onChange(finallyValue)
})
return [
pickerValues,
pickerColumns,
onChangePicker,
minDate,
maxDate,
] as const
}
export default useDatePicker