Skip to content

Commit

Permalink
perf(date-picker): 范围选择交互优化 (#3055) (#3056)
Browse files Browse the repository at this point in the history
* perf(date-picker): 范围选择交互优化 (#3055)

* perf(date-picker): 范围选择交互优化 (#3055)

---------

Co-authored-by: wanjinping <[email protected]>
  • Loading branch information
fcppddl and wanjinping authored Nov 26, 2024
1 parent fbec9aa commit 1adc538
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .changeset/selfish-seas-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@hi-ui/date-picker": patch
"@hi-ui/hiui": patch
---

perf(date-picker): 范围选择交互优化 (#3055)
15 changes: 14 additions & 1 deletion packages/ui/date-picker/src/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import { getBelongWeek, getBelongWeekYear } from './utils/week'
import { DateRangeTimePanel } from './components/date-range-time-panel'
import { GranularityMap } from './utils/constants'
import { CalenderSelectedRange } from './hooks/useCalenderData'

const DATE_PICKER_PREFIX = getPrefixCls('date-picker')

Expand Down Expand Up @@ -94,6 +95,7 @@ export const DatePicker = forwardRef<HTMLDivElement | null, DatePickerProps>(
const cacheDate = useRef<(moment.Moment | null)[]>([])
const [inputFocus, setInputFocus] = useState(false)
const [type, setType] = useState<DatePickerTypeEnum>(propType)
const rangeRef = useRef<CalenderSelectedRange | null>(null)

const needConfirm = useMemo(() => {
// 如果是日期时间范围选择,则默认返回 true
Expand Down Expand Up @@ -318,12 +320,22 @@ export const DatePicker = forwardRef<HTMLDivElement | null, DatePickerProps>(
if (!needConfirm) {
const outDateValue = outDate[0]
const isValid = moment(outDateValue).isValid()
const start = rangeRef.current?.start
const end = rangeRef.current?.end
let newDate
if (!!start && !!end) {
newDate = [start, end]
} else {
newDate = outDate
}

// @ts-ignore
const { startDate, endDate } = isValid && getInRangeDate(outDate[0], outDate[1], max, min)
const { startDate, endDate } = isValid && getInRangeDate(newDate[0], newDate[1], max, min)
const _outDate = isValid ? [moment(startDate), moment(endDate)] : [null]
callback(_outDate, true)

changeOutDate(_outDate)
rangeRef.current = null
}
// 日期时间范围选择模式,弹窗关闭,重新刷入缓存,视作取消
else {
Expand Down Expand Up @@ -447,6 +459,7 @@ export const DatePicker = forwardRef<HTMLDivElement | null, DatePickerProps>(
cellRender,
footerRender,
strideSelectMode,
rangeRef,
}}
>
<div className={cx(prefixCls, className)} {...otherProps}>
Expand Down
31 changes: 27 additions & 4 deletions packages/ui/date-picker/src/components/range-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const RangePanel = () => {
prefixCls,
disabledDate,
strideSelectMode,
rangeRef,
} = useContext(DPContext)
const calendarClickIsEnd = useRef(false)
const [showRangeMask, setShowRangeMask] = useState(false)
Expand Down Expand Up @@ -92,7 +93,7 @@ const RangePanel = () => {
const setRanges = (date: moment.Moment, panelIndex: number = 0) => {
const newRange = { ...range }

if (newRange.start && (range.selecting || !calendarClickIsEnd.current)) {
if (newRange.start && range.selecting) {
if (date.isSameOrBefore(newRange.start)) {
newRange.selecting = false
newRange.end = newRange.start
Expand All @@ -101,7 +102,7 @@ const RangePanel = () => {

// 此处是明显的语法错误,故而注释修改
// onSelect(date, calendarClickIsEnd)
onSelect(date as any, !calendarClickIsEnd.current, panelIndex)
onSelect(date as any, true, panelIndex)

if (type === 'weekrange') {
// 固定模式下,即使跨月选择了日期,仍然显示当前月的日期选择面板
Expand Down Expand Up @@ -142,7 +143,7 @@ const RangePanel = () => {
} else {
newRange.selecting = true
newRange.start = date
newRange.end = null
newRange.end = newRange.end ? newRange.end : null
onSelect(date as any, false, panelIndex)
}
setRange(newRange)
Expand Down Expand Up @@ -187,6 +188,28 @@ const RangePanel = () => {
})
}

const onMouseLeave = () => {
// todo: 结束的日期如果被禁用,则不设置end,更优方法是获取第一个可用的日期
if (
type.includes('range') &&
outDate?.[1] &&
range.selecting &&
!disabledDate?.(outDate[1].toDate(), views[0])
) {
setRange((range) => {
const newRange = { ...range }
newRange.end = outDate[1]
if (newRange.end?.isBefore(newRange.start)) {
const temp = newRange.start
newRange.start = newRange.end
newRange.end = temp
}
rangeRef.current = newRange
return newRange
})
}
}

const onTimeChange = (date: string[]) => {
// 关闭之后,不再响应事件
if (showPanel) {
Expand Down Expand Up @@ -309,7 +332,7 @@ const RangePanel = () => {

return (
<React.Fragment>
<div className={panelCls}>
<div className={panelCls} onMouseLeave={onMouseLeave}>
{renderShortcut()}
<div className={`${prefixCls}__panel--left`}>
{calRenderDates[0] && (
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/date-picker/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { CalendarItemV3, DatePickerProps, DatePickerValueV3 } from './types'
import moment from 'moment'
import type { UseLocaleContext } from '@hi-ui/core'
import { CalenderSelectedRange } from './hooks/useCalenderData'

const DPContext = React.createContext<DPContextData>({} as DPContextData)

Expand Down Expand Up @@ -61,5 +62,6 @@ export interface DPContextData extends ExtendsType {
// 内部现在暂时使用 v3 的数据格式
altCalendar?: CalendarItemV3[]
onPanelChange?: (data: Date) => void
rangeRef: React.MutableRefObject<CalenderSelectedRange | null>
}
export default DPContext

0 comments on commit 1adc538

Please sign in to comment.