From 47fac44d35d6090eed614c2a4c2c6169104424b0 Mon Sep 17 00:00:00 2001 From: 07akioni <07akioni2@gmail.com> Date: Wed, 6 Oct 2021 13:44:51 +0800 Subject: [PATCH] wip(date-picker): clean codes --- CHANGELOG.en-US.md | 4 +- CHANGELOG.zh-CN.md | 4 +- src/date-picker/src/DatePicker.tsx | 35 +++++---- src/date-picker/src/interface.ts | 3 +- src/date-picker/src/panel/month.tsx | 94 +++++++++++------------ src/date-picker/src/panel/use-calendar.ts | 15 ++-- src/date-picker/src/styles/index.cssr.ts | 75 ++++++++++-------- src/date-picker/styles/dark.ts | 4 +- src/date-picker/styles/light.ts | 6 +- 9 files changed, 128 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 66b9be762..f1d051dac 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -22,6 +22,7 @@ - `n-dropdown` support options with `type='render'`. - `n-data-table` supports multiple column sorting. - `n-date-picker` add `first-day-of-week` prop. +- `n-date-picker`'s `type` prop support `month` option. ### Fixes @@ -52,9 +53,6 @@ ### i18n - Add ukUA locale. -### Feats - -- `n-date-picker`'s `type` prop support `month` option. ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 677f6b30e..a6ec9f7f3 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -22,6 +22,7 @@ - `n-dropdown` 支持 `type='render'` 的选项 - `n-data-table` 支持多列排序 - `n-date-picker` 新增 `first-day-of-week` 属性 +- `n-date-picker` 属性 `type` 支持 `month` 选项 ### Fixes @@ -52,9 +53,6 @@ ### i18n - 新增 ukUA locale -### Feats - -- `n-date-picker` 属性 `type` 支持 `month` 选项 ### Fixes diff --git a/src/date-picker/src/DatePicker.tsx b/src/date-picker/src/DatePicker.tsx index 84c3bd561..4552b5209 100644 --- a/src/date-picker/src/DatePicker.tsx +++ b/src/date-picker/src/DatePicker.tsx @@ -17,7 +17,7 @@ import { } from 'vue' import { VBinder, VTarget, VFollower, FollowerPlacement } from 'vueuc' import { clickoutside } from 'vdirs' -import { format, getTime, isValid, getYear } from 'date-fns' +import { format, getTime, isValid, getYear, getMonth } from 'date-fns' import { useIsMounted, useMergedState } from 'vooks' import { happensIn } from 'seemly' import { InputInst, InputProps, NInput } from '../../input' @@ -255,6 +255,9 @@ export default defineComponent({ case 'datetimerange': { return ['clear', 'confirm'] } + case 'month': { + return ['clear', 'now', 'confirm'] + } default: { warn( 'data-picker', @@ -338,22 +341,27 @@ export default defineComponent({ disableUpdateOnClose }) } - function scrollTimer (): void { + function scrollYearMonth (value?: number): void { if (!panelInstRef.value) return const { monthScrollRef, yearScrollRef } = panelInstRef.value + const { value: mergedValue } = mergedValueRef if (monthScrollRef) { - const month = monthScrollRef.contentRef?.querySelector( - '[data-selected]' - ) as HTMLElement - if (month) { - monthScrollRef.scrollTo({ top: month.offsetTop }) - } + const monthIndex = + value === undefined + ? mergedValue === null + ? getMonth(Date.now()) + : getMonth(mergedValue as number) + : getMonth(value) + monthScrollRef.scrollTo({ top: monthIndex * 40 }) } if (yearScrollRef) { - if (mergedValueRef.value) { - const yearIndex = getYear(mergedValueRef.value as number) - 1900 - yearScrollRef.scrollTo({ top: yearIndex * 40 }) - } + const yearIndex = + (value === undefined + ? mergedValue === null + ? getYear(Date.now()) + : getYear(mergedValue as number) + : getYear(value)) - 1900 + yearScrollRef.scrollTo({ top: yearIndex * 40 }) } } // --- Panel update value @@ -498,7 +506,7 @@ export default defineComponent({ if (mergedDisabledRef.value || mergedShowRef.value) return doUpdateShow(true) if (props.type === 'month') { - void nextTick(scrollTimer) + void nextTick(scrollYearMonth) } } function closeCalendar ({ @@ -544,6 +552,7 @@ export default defineComponent({ const uniVaidation = uniCalendarValidation(props, pendingValueRef) const dualValidation = dualCalendarValidation(props, pendingValueRef) provide(datePickerInjectionKey, { + scrollYearMonth, mergedClsPrefixRef, mergedThemeRef: themeRef, timePickerSizeRef, diff --git a/src/date-picker/src/interface.ts b/src/date-picker/src/interface.ts index 2e692e905..af3835196 100644 --- a/src/date-picker/src/interface.ts +++ b/src/date-picker/src/interface.ts @@ -1,7 +1,7 @@ import { InjectionKey, Ref, Slots } from 'vue' import { VirtualListInst } from 'vueuc' import { NLocale, NDateLocale } from '../../locales' -import { ScrollbarInst } from '../../scrollbar' +import type { ScrollbarInst } from '../../_internal' import { IsHourDisabled, IsMinuteDisabled, @@ -62,6 +62,7 @@ export type DatePickerInjection = { updateValueOnCloseRef: Ref firstDayOfWeekRef: Ref datePickerSlots: Slots + scrollYearMonth: (value?: number) => void } & ReturnType & ReturnType diff --git a/src/date-picker/src/panel/month.tsx b/src/date-picker/src/panel/month.tsx index a05abc670..a500b4ad3 100644 --- a/src/date-picker/src/panel/month.tsx +++ b/src/date-picker/src/panel/month.tsx @@ -1,11 +1,9 @@ -import { h, defineComponent, renderSlot, watchEffect, VNode } from 'vue' -import { NButton, NxButton } from '../../../button' -import { NBaseFocusDetector } from '../../../_internal' -import { useCalendar } from './use-calendar' -import { warnOnce } from '../../../_utils' -import { NScrollbar } from '../../../scrollbar' +import { h, defineComponent, renderSlot, VNode } from 'vue' import { VirtualList } from 'vueuc' -import { MonthItem, YearItem } from '../utils' +import { NButton, NxButton } from '../../../button' +import { NBaseFocusDetector, NScrollbar } from '../../../_internal' +import { useCalendar } from './use-calendar' +import type { MonthItem, YearItem } from '../utils' /** * Month Panel @@ -17,18 +15,8 @@ export default defineComponent({ name: 'MonthPanel', props: useCalendar.props, setup (props) { - if (__DEV__) { - watchEffect(() => { - if (props.actions?.includes('confirm')) { - warnOnce( - 'date-picker', - 'The `confirm` action is not supported for n-date-picker of `date` type' - ) - } - }) - } const useCalendarRef = useCalendar(props, 'month') - const itemRenderer = ( + const renderItem = ( item: YearItem | MonthItem, i: number, mergedClsPrefix: string @@ -38,7 +26,6 @@ export default defineComponent({
handleDateClick(item)} > {item.type === 'month' ? item.formattedText : item.dateObject.year} - {( - item.type === 'month' ? item.inCurrentMonth : item.inCurrentYear - ) ? ( -
- ) : null}
) } - return { ...useCalendarRef, itemRenderer } + return { ...useCalendarRef, renderItem } }, render () { - const { mergedClsPrefix, mergedTheme, shortcuts, itemRenderer } = this - + const { mergedClsPrefix, mergedTheme, shortcuts, renderItem } = this return (
- - itemRenderer(yearItem, i, mergedClsPrefix) - )} - itemSize={40} - showScrollbar={false} - onScroll={this.handleVirtualListScroll} - > - {{ - default: ({ item }: { item: VNode }) => { - return item - } - }} - + {{ + default: () => ( + + renderItem(yearItem, i, mergedClsPrefix) + )} + itemSize={40} + showScrollbar={false} + onScroll={this.handleVirtualListScroll} + > + {{ + default: ({ item }: { item: VNode }) => { + return item + } + }} + + ) + }} -
{{ default: () => [ ...this.monthArray.map((monthItem, i) => - itemRenderer(monthItem, i, mergedClsPrefix) + renderItem(monthItem, i, mergedClsPrefix) ),
this.locale.now }} ) : null} - {/** we don't need a confirm button for date picking */} + {this.actions?.includes('confirm') ? ( + + {{ default: () => this.locale.confirm }} + + ) : null}
) : null} diff --git a/src/date-picker/src/panel/use-calendar.ts b/src/date-picker/src/panel/use-calendar.ts index f8671880a..562f96645 100644 --- a/src/date-picker/src/panel/use-calendar.ts +++ b/src/date-picker/src/panel/use-calendar.ts @@ -19,7 +19,7 @@ import { usePanelCommon } from './use-panel-common' import { IsSingleDateDisabled, datePickerInjectionKey } from '../interface' import type { DateItem, MonthItem, YearItem } from '../utils' import { VirtualListInst } from 'vueuc' -import { ScrollbarInst } from '../../../scrollbar' +import { ScrollbarInst } from '../../../_internal' const useCalendarProps = { ...usePanelCommon.props, @@ -46,7 +46,8 @@ function useCalendar ( isSecondDisabledRef, localeRef, firstDayOfWeekRef, - datePickerSlots + datePickerSlots, + scrollYearMonth // eslint-disable-next-line @typescript-eslint/no-non-null-assertion } = inject(datePickerInjectionKey)! const validation = { @@ -222,12 +223,12 @@ function useCalendar ( newValue = Date.now() } newValue = getTime(set(newValue, dateItem.dateObject)) - panelCommon.doUpdateValue( - getTime(sanitizeValue(newValue)), - type === 'month' || type === 'date' - ) - if (type === 'date' || (type === 'month' && dateItem.type === 'month')) { + panelCommon.doUpdateValue(getTime(sanitizeValue(newValue)), type === 'date') + if (type === 'date') { panelCommon.doClose() + } else if (type === 'month') { + panelCommon.disableTransitionOneTick() + scrollYearMonth(newValue) } } function deriveDateInputValue (time?: number): void { diff --git a/src/date-picker/src/styles/index.cssr.ts b/src/date-picker/src/styles/index.cssr.ts index 7252b90f5..6ca6057fc 100644 --- a/src/date-picker/src/styles/index.cssr.ts +++ b/src/date-picker/src/styles/index.cssr.ts @@ -92,54 +92,65 @@ export default c([ }) ]), cB('date-panel-month-calendar', { - padding: 'var(--calendar-left-padding)', display: 'flex', gridArea: 'left-calendar' }, [ cE('picker-col', ` min-width: var(--item-month-cell-width); - height: calc(var(--item-month-cell-height) * 7);; + height: calc(var(--item-month-cell-height) * 7); `, [ + c('&:first-child', [ + cE('picker-col-item', [ + c('&::before', 'left: 4px;') + ]) + ]), + c('&:last-child', [ + cE('picker-col-item', [ + c('&::before', 'right: 4px;') + ]) + ]), cE('padding', ` height: calc(var(--item-month-cell-height) * 6) `) ]), cE('picker-col-item', ` + z-index: 0; cursor: pointer; height: var(--item-month-cell-height); + box-sizing: border-box; + padding-top: 4px; display: flex; align-items: center; justify-content: center; position: relative; transition: color .3s var(--bezier), - background-color .3s var(--bezier), + background-color .3s var(--bezier); background: #0000; color: var(--item-text-color); `, [ - cNotM('disabled', [ - c('&:hover', { - backgroundColor: 'var(--item-color-hover)' - }) - ]), - cM('current', [ - cE('sup', ` - position: absolute; - top: 2px; - right: 2px; - content: ""; - height: 4px; - width: 4px; - border-radius: 2px; - background-color: var(--item-color-active); - transition: - background-color .2s var(--bezier); - `) - ]), - cM('selected', ` - background-color: var(--item-color-hover); - color: var(--item-color-active); + c('&::before', ` + z-index: -1; + content: ""; + position: absolute; + left: 2px; + right: 2px; + top: 4px; + bottom: 0; + border-radius: var(--panel-border-radius); + transition: + background-color .3s var(--bezier); `), + cNotM('disabled', [ + c('&:hover::before', ` + background-color: var(--item-color-hover); + `), + cM('selected', ` + color: var(--item-color-active); + `, [ + c('&::before', 'background-color: var(--item-color-hover);') + ]) + ]), cM('disabled', ` background-color: var(--item-color-disabled); cursor: not-allowed; @@ -284,13 +295,6 @@ export default c([ background-color .2s var(--bezier), color .2s var(--bezier); `, [ - c('&.transition-disabled', { - transition: 'none !important' - }, [ - c('&::before, &::after', { - transition: 'none !important' - }) - ]), cNotM('disabled', [ cNotM('selected', [ c('&:hover', { @@ -430,5 +434,12 @@ export default c([ `) ]) ]) + ]), + c('[data-n-date].transition-disabled', { + transition: 'none !important' + }, [ + c('&::before, &::after', { + transition: 'none !important' + }) ]) ]) diff --git a/src/date-picker/styles/dark.ts b/src/date-picker/styles/dark.ts index 20f6f9de8..45ff7be0e 100644 --- a/src/date-picker/styles/dark.ts +++ b/src/date-picker/styles/dark.ts @@ -3,6 +3,7 @@ import { inputDark } from '../../input/styles' import { commonDark } from '../../_styles/common' import { buttonDark } from '../../button/styles' import { timePickerDark } from '../../time-picker/styles' +import { scrollbarDark } from '../../_internal/scrollbar/styles' import type { DatePickerTheme } from './light' import { self } from './light' @@ -12,7 +13,8 @@ const datePickerDark: DatePickerTheme = { peers: { Input: inputDark, Button: buttonDark, - TimePicker: timePickerDark + TimePicker: timePickerDark, + Scrollbar: scrollbarDark }, self (vars) { const { popoverColor, hoverColor, primaryColor } = vars diff --git a/src/date-picker/styles/light.ts b/src/date-picker/styles/light.ts index 326f4cab3..653711943 100644 --- a/src/date-picker/styles/light.ts +++ b/src/date-picker/styles/light.ts @@ -1,10 +1,11 @@ +import { changeColor } from 'seemly' import { inputLight } from '../../input/styles' import { commonLight } from '../../_styles/common' import type { ThemeCommonVars } from '../../_styles/common' import { buttonLight } from '../../button/styles' import { timePickerLight } from '../../time-picker/styles' +import { scrollbarLight } from '../../_internal/scrollbar/styles' import commonVars from './_common' -import { changeColor } from 'seemly' import { createTheme } from '../../_mixins' export const self = (vars: ThemeCommonVars) => { @@ -63,7 +64,8 @@ const datePickerLight = createTheme({ peers: { Input: inputLight, Button: buttonLight, - TimePicker: timePickerLight + TimePicker: timePickerLight, + Scrollbar: scrollbarLight }, self })