From 3ed7118ca033564272fbdf749681947c02585ec4 Mon Sep 17 00:00:00 2001 From: 07akioni <07akioni2@gmail.com> Date: Mon, 27 Jun 2022 02:21:39 +0800 Subject: [PATCH] feat(date-picker): `type` prop supports `'quarterrange'` and `'yearrange'` --- CHANGELOG.en-US.md | 6 +++ CHANGELOG.zh-CN.md | 4 ++ .../demos/enUS/index.demo-entry.md | 4 +- .../demos/enUS/quarterrange.demo.vue | 20 ++++++++ src/date-picker/demos/enUS/yearrange.demo.vue | 20 ++++++++ .../demos/zhCN/index.demo-entry.md | 4 +- .../demos/zhCN/quarterrange.demo.vue | 20 ++++++++ src/date-picker/demos/zhCN/yearrange.demo.vue | 20 ++++++++ src/date-picker/src/DatePicker.tsx | 18 +++++-- src/date-picker/src/config.ts | 2 + src/date-picker/src/panel/monthrange.tsx | 44 ++++++++++------- .../src/panel/use-dual-calendar.ts | 47 ++++++++++++++++--- src/date-picker/src/utils.ts | 4 +- src/date-picker/styles/_common.ts | 6 ++- 14 files changed, 187 insertions(+), 32 deletions(-) create mode 100644 src/date-picker/demos/enUS/quarterrange.demo.vue create mode 100644 src/date-picker/demos/enUS/yearrange.demo.vue create mode 100644 src/date-picker/demos/zhCN/quarterrange.demo.vue create mode 100644 src/date-picker/demos/zhCN/yearrange.demo.vue diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index ddc0625dc..af25e79c2 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -10,6 +10,12 @@ - Fix `n-select` will remove select value in multiple mode in `form` if Enter key is pressed in input element. Closes [#3169](https://github.com/TuSimple/naive-ui/issues/3169). - Fix `n-select`'s filter prop not working, closes [#3175](https://github.com/TuSimple/naive-ui/issues/3175). +### Feats + +### Feats + +- `n-date-picker`'s `type` prop supports `'quarterrange'` and `'yearrange'`. + ## 2.30.6 ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 753b35183..cc5959e3a 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -10,6 +10,10 @@ - 修复 `n-select` 在 `form` 中,多选的情况下,在 input 元素中按下 Enter 键会导致选项被清除,关闭 [#3169](https://github.com/TuSimple/naive-ui/issues/3169) - 修复 `n-select` 的 `filter` 属性不生效,关闭 [#3175](https://github.com/TuSimple/naive-ui/issues/3175) +### Feats + +- `n-date-picker` `type` 属性支持 `'quarterrange'` 和 `'yearrange'` + ## 2.30.6 ### Fixes diff --git a/src/date-picker/demos/enUS/index.demo-entry.md b/src/date-picker/demos/enUS/index.demo-entry.md index be1bdb413..878b413ab 100644 --- a/src/date-picker/demos/enUS/index.demo-entry.md +++ b/src/date-picker/demos/enUS/index.demo-entry.md @@ -13,7 +13,9 @@ datetimerange.vue month.vue monthrange.vue year.vue +yearrange.vue quarter.vue +quarterrange.vue size.vue default-time.vue disabled.vue @@ -134,7 +136,7 @@ panel.vue | on-update:formatted-value | `(value: string \| null, timestampValue: number \| null) => void` | `undefined` | Formatted value changed callback. | 2.24.0 | | on-update:value | `(value: number \| null, formattedValue: string \| null) => void` | `undefined` | Value changed callback. | `formattedValue` 2.24.0 | -### MonthRange Type Props +### MonthRange, QuarterRange, YearRange Type Props | Name | Type | Default | Description | Version | | --- | --- | --- | --- | --- | diff --git a/src/date-picker/demos/enUS/quarterrange.demo.vue b/src/date-picker/demos/enUS/quarterrange.demo.vue new file mode 100644 index 000000000..7d181f766 --- /dev/null +++ b/src/date-picker/demos/enUS/quarterrange.demo.vue @@ -0,0 +1,20 @@ + +# 季度范围 + + + + + diff --git a/src/date-picker/demos/enUS/yearrange.demo.vue b/src/date-picker/demos/enUS/yearrange.demo.vue new file mode 100644 index 000000000..ee4db95c2 --- /dev/null +++ b/src/date-picker/demos/enUS/yearrange.demo.vue @@ -0,0 +1,20 @@ + +# 年份范围 + + + + + diff --git a/src/date-picker/demos/zhCN/index.demo-entry.md b/src/date-picker/demos/zhCN/index.demo-entry.md index ecea6a6cb..78232c0d3 100644 --- a/src/date-picker/demos/zhCN/index.demo-entry.md +++ b/src/date-picker/demos/zhCN/index.demo-entry.md @@ -13,7 +13,9 @@ datetimerange.vue month.vue monthrange.vue year.vue +yearrange.vue quarter.vue +quarterrange.vue size.vue default-time.vue disabled.vue @@ -133,7 +135,7 @@ panel-debug.vue | on-update:formatted-value | `(value: string \| null, timestampValue: number \| null) => void` | `undefined` | 可控数据更新时触发的回调函数 | 2.24.0 | | on-update:value | `(value: number \| null, formattedValue: string \| null) => void` | `undefined` | 可控数据更新时触发的回调函数 | `formattedValue` 2.24.0 | -### MonthRange 类型的 Props +### MonthRange、QuarterRange、YearRange 类型的 Props | 名称 | 类型 | 默认值 | 说明 | 版本 | | --- | --- | --- | --- | --- | diff --git a/src/date-picker/demos/zhCN/quarterrange.demo.vue b/src/date-picker/demos/zhCN/quarterrange.demo.vue new file mode 100644 index 000000000..7d181f766 --- /dev/null +++ b/src/date-picker/demos/zhCN/quarterrange.demo.vue @@ -0,0 +1,20 @@ + +# 季度范围 + + + + + diff --git a/src/date-picker/demos/zhCN/yearrange.demo.vue b/src/date-picker/demos/zhCN/yearrange.demo.vue new file mode 100644 index 000000000..ee4db95c2 --- /dev/null +++ b/src/date-picker/demos/zhCN/yearrange.demo.vue @@ -0,0 +1,20 @@ + +# 年份范围 + + + + + diff --git a/src/date-picker/src/DatePicker.tsx b/src/date-picker/src/DatePicker.tsx index 7a2ca25fe..bc277a5c2 100644 --- a/src/date-picker/src/DatePicker.tsx +++ b/src/date-picker/src/DatePicker.tsx @@ -206,11 +206,13 @@ export default defineComponent({ case 'datetimerange': return localeRef.value.dateTimeFormat case 'year': + case 'yearrange': return localeRef.value.yearTypeFormat case 'month': case 'monthrange': return localeRef.value.monthTypeFormat case 'quarter': + case 'quarterrange': return localeRef.value.quarterFormat } }) @@ -287,7 +289,13 @@ export default defineComponent({ ) }) const isRangeRef = computed(() => { - return ['daterange', 'datetimerange', 'monthrange'].includes(props.type) + return [ + 'daterange', + 'datetimerange', + 'monthrange', + 'quarterrange', + 'yearrange' + ].includes(props.type) }) const localizedPlacehoderRef = computed(() => { const { placeholder } = props @@ -978,11 +986,13 @@ export default defineComponent({ /> ) : type === 'month' || type === 'year' || type === 'quarter' ? ( - ) : type === 'monthrange' ? ( + ) : type === 'monthrange' || + type === 'yearrange' || + type === 'quarterrange' ? ( - ) : ( + ) : ( - ) + ) } if (this.panel) { return renderPanel() diff --git a/src/date-picker/src/config.ts b/src/date-picker/src/config.ts index c1b0fa487..5ee404e57 100644 --- a/src/date-picker/src/config.ts +++ b/src/date-picker/src/config.ts @@ -11,3 +11,5 @@ export type DatePickerType = | 'year' | 'quarter' | 'monthrange' + | 'quarterrange' + | 'yearrange' diff --git a/src/date-picker/src/panel/monthrange.tsx b/src/date-picker/src/panel/monthrange.tsx index 62f968183..a0154fc98 100644 --- a/src/date-picker/src/panel/monthrange.tsx +++ b/src/date-picker/src/panel/monthrange.tsx @@ -11,7 +11,7 @@ import { VirtualList } from 'vueuc' import { NxButton } from '../../../button' import { NBaseFocusDetector, NScrollbar } from '../../../_internal' import { warnOnce } from '../../../_utils' -import type { MonthItem, YearItem } from '../utils' +import type { MonthItem, QuarterItem, YearItem } from '../utils' import { MONTH_ITEM_HEIGHT } from '../config' import { useDualCalendar, useDualCalendarProps } from './use-dual-calendar' @@ -20,7 +20,7 @@ export default defineComponent({ props: { ...useDualCalendarProps, type: { - type: String as PropType<'monthrange'>, + type: String as PropType<'monthrange' | 'yearrange' | 'quarterrange'>, required: true } }, @@ -39,7 +39,7 @@ export default defineComponent({ } const useCalendarRef = useDualCalendar(props, props.type) const renderItem = ( - item: YearItem | MonthItem, + item: YearItem | MonthItem | QuarterItem, i: number, mergedClsPrefix: string, type: 'start' | 'end' @@ -72,7 +72,9 @@ export default defineComponent({ > {item.type === 'month' ? item.dateObject.month + 1 - : item.dateObject.year} + : item.type === 'quarter' + ? item.dateObject.quarter + : item.dateObject.year} ) } @@ -137,7 +139,7 @@ export default defineComponent({ ) }} - {type === 'monthrange' ? ( + {type === 'monthrange' || type === 'quarterrange' ? (
@@ -148,12 +150,17 @@ export default defineComponent({ > {{ default: () => [ - this.startMonthArray.map((monthItem, i) => - renderItem(monthItem, i, mergedClsPrefix, 'start') + (type === 'monthrange' + ? this.startMonthArray + : this.startQuarterArray + ).map((item, i) => + renderItem(item, i, mergedClsPrefix, 'start') ), -
+ type === 'monthrange' && ( +
+ ) ] }} @@ -203,7 +210,7 @@ export default defineComponent({ ) }} - {type === 'monthrange' ? ( + {type === 'monthrange' || type === 'quarterrange' ? (
@@ -214,12 +221,17 @@ export default defineComponent({ > {{ default: () => [ - this.endMonthArray.map((monthItem, i) => - renderItem(monthItem, i, mergedClsPrefix, 'end') + (type === 'monthrange' + ? this.endMonthArray + : this.endQuarterArray + ).map((item, i) => + renderItem(item, i, mergedClsPrefix, 'end') ), -
+ type === 'monthrange' && ( +
+ ) ] }} diff --git a/src/date-picker/src/panel/use-dual-calendar.ts b/src/date-picker/src/panel/use-dual-calendar.ts index 1380ec308..11082d445 100644 --- a/src/date-picker/src/panel/use-dual-calendar.ts +++ b/src/date-picker/src/panel/use-dual-calendar.ts @@ -10,7 +10,8 @@ import { startOfDay, set, getDate, - getTime + getTime, + startOfQuarter } from 'date-fns/esm' import { VirtualListInst } from 'vueuc' import { @@ -22,7 +23,9 @@ import { yearArray, monthArray, getDefaultTime, - pluckValueFromRange + pluckValueFromRange, + QuarterItem, + quarterArray } from '../utils' import { usePanelCommon, usePanelCommonProps } from './use-panel-common' import { @@ -47,7 +50,12 @@ const useDualCalendarProps = { // eslint-disable-next-line @typescript-eslint/explicit-function-return-type function useDualCalendar ( props: ExtractPropTypes, - type: 'daterange' | 'datetimerange' | 'monthrange' + type: + | 'daterange' + | 'datetimerange' + | 'monthrange' + | 'quarterrange' + | 'yearrange' ) { const { isDateDisabledRef, @@ -217,6 +225,14 @@ function useDualCalendar ( const endYearArrayRef = computed(() => { return yearArray(pluckValueFromRange(props.value, 'end'), nowRef.value) }) + const startQuarterArrayRef = computed(() => { + const startValue = pluckValueFromRange(props.value, 'start') + return quarterArray(startValue ?? Date.now(), startValue, nowRef.value) + }) + const endQuarterArrayRef = computed(() => { + const endValue = pluckValueFromRange(props.value, 'end') + return quarterArray(endValue ?? Date.now(), endValue, nowRef.value) + }) const startMonthArrayRef = computed(() => { const startValue = pluckValueFromRange(props.value, 'start') return monthArray(startValue ?? Date.now(), startValue, nowRef.value) @@ -711,17 +727,27 @@ function useDualCalendar ( } // only for monthrange function handleColItemClick ( - dateItem: MonthItem | YearItem, + dateItem: MonthItem | QuarterItem | YearItem, clickType: 'start' | 'end' ): void { const { value } = props const noCurrentValue = !Array.isArray(value) const itemTs = - dateItem.type === 'year' + dateItem.type === 'year' && type !== 'yearrange' ? noCurrentValue - ? set(dateItem.ts, { month: getMonth(new Date()) }).valueOf() + ? set(dateItem.ts, { + month: getMonth( + type === 'quarterrange' + ? startOfQuarter(new Date()) + : new Date() + ) + }).valueOf() : set(dateItem.ts, { - month: getMonth(value[clickType === 'start' ? 0 : 1]) + month: getMonth( + type === 'quarterrange' + ? startOfQuarter(value[clickType === 'start' ? 0 : 1]) + : value[clickType === 'start' ? 0 : 1] + ) }).valueOf() : dateItem.ts if (noCurrentValue) { @@ -750,6 +776,7 @@ function useDualCalendar ( panelCommon.doUpdateValue(nextValue, props.panel) switch (type) { case 'monthrange': + case 'quarterrange': panelCommon.disableTransitionOneTick() if (otherPartsChanged) { justifyColumnsScrollState(nextValue, 'start') @@ -758,6 +785,10 @@ function useDualCalendar ( justifyColumnsScrollState(nextValue, clickType) } break + case 'yearrange': + panelCommon.disableTransitionOneTick() + justifyColumnsScrollState(nextValue, 'start') + justifyColumnsScrollState(nextValue, 'end') } } function handleStartYearVlScroll (): void { @@ -816,8 +847,10 @@ function useDualCalendar ( endDateArray: endDateArrayRef, startYearArray: startYearArrayRef, startMonthArray: startMonthArrayRef, + startQuarterArray: startQuarterArrayRef, endYearArray: endYearArrayRef, endMonthArray: endMonthArrayRef, + endQuarterArray: endQuarterArrayRef, isSelecting: isSelectingRef, handleRangeShortcutMouseenter, handleRangeShortcutClick, diff --git a/src/date-picker/src/utils.ts b/src/date-picker/src/utils.ts index f2500b211..9f1bd28ed 100644 --- a/src/date-picker/src/utils.ts +++ b/src/date-picker/src/utils.ts @@ -267,12 +267,12 @@ function monthArray ( } function quarterArray ( - quarterTs: number, + yearAnchorTs: number, valueTs: number | null, currentTs: number ): QuarterItem[] { const calendarQuarters: QuarterItem[] = [] - const yearStart = startOfYear(quarterTs) + const yearStart = startOfYear(yearAnchorTs) for (let i = 0; i < 4; i++) { calendarQuarters.push( quarterItem(getTime(addQuarters(yearStart, i)), valueTs, currentTs) diff --git a/src/date-picker/styles/_common.ts b/src/date-picker/styles/_common.ts index 1542204e8..e1082f138 100644 --- a/src/date-picker/styles/_common.ts +++ b/src/date-picker/styles/_common.ts @@ -21,6 +21,8 @@ export default { calendarLeftPaddingYear: '0', calendarLeftPaddingQuarter: '0', calendarLeftPaddingMonthrange: '0', + calendarLeftPaddingQuarterrange: '0', + calendarLeftPaddingYearrange: '0', calendarRightPaddingDate: '6px 12px 4px 12px', calendarRightPaddingDatetime: '4px 12px', calendarRightPaddingDaterange: '6px 12px 4px 12px', @@ -28,5 +30,7 @@ export default { calendarRightPaddingMonth: '0', calendarRightPaddingYear: '0', calendarRightPaddingQuarter: '0', - calendarRightPaddingMonthrange: '0' + calendarRightPaddingMonthrange: '0', + calendarRightPaddingQuarterrange: '0', + calendarRightPaddingYearrange: '0' }