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 @@
+
+# 季度范围
+
+
+
+
+ {{ JSON.stringify(timestamp) }}
+
+
+
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 @@
+
+# 年份范围
+
+
+
+
+ {{ JSON.stringify(timestamp) }}
+
+
+
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 @@
+
+# 季度范围
+
+
+
+
+ {{ JSON.stringify(timestamp) }}
+
+
+
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 @@
+
+# 年份范围
+
+
+
+
+ {{ JSON.stringify(timestamp) }}
+
+
+
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'
}