wip(date-picker): clean codes

This commit is contained in:
07akioni 2021-10-06 13:44:51 +08:00
parent 56fb18e9d1
commit 47fac44d35
9 changed files with 128 additions and 112 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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<boolean>
firstDayOfWeekRef: Ref<FirstDayOfWeek | undefined>
datePickerSlots: Slots
scrollYearMonth: (value?: number) => void
} & ReturnType<typeof uniCalendarValidation> &
ReturnType<typeof dualCalendarValidation>

View File

@ -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({
<div
data-n-date
key={i}
data-selected={item.selected ? '' : null}
class={[
`${mergedClsPrefix}-date-panel-month-calendar__picker-col-item`,
{
@ -55,19 +42,13 @@ export default defineComponent({
onClick={() => handleDateClick(item)}
>
{item.type === 'month' ? item.formattedText : item.dateObject.year}
{(
item.type === 'month' ? item.inCurrentMonth : item.inCurrentYear
) ? (
<div class={`${mergedClsPrefix}-date-panel-month-calendar__sup`} />
) : null}
</div>
)
}
return { ...useCalendarRef, itemRenderer }
return { ...useCalendarRef, renderItem }
},
render () {
const { mergedClsPrefix, mergedTheme, shortcuts, itemRenderer } = this
const { mergedClsPrefix, mergedTheme, shortcuts, renderItem } = this
return (
<div
ref="selfRef"
@ -80,43 +61,45 @@ export default defineComponent({
<NScrollbar
ref="scrollbarInstRef"
class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}
// theme={mergedTheme.peers.Scrollbar}
// themeOverrides={mergedTheme.peerOverrides.Scrollbar}
theme={mergedTheme.peers.Scrollbar}
themeOverrides={mergedTheme.peerOverrides.Scrollbar}
container={this.virtualListContainer}
content={this.virtualListContent}
horizontalRailStyle={{ zIndex: 3 }}
verticalRailStyle={{ zIndex: 3 }}
// internalOnUpdateScrollLeft={setHeaderScrollLeft}
>
<VirtualList
ref="yearScrollRef"
items={this.yearArray.map((yearItem, i) =>
itemRenderer(yearItem, i, mergedClsPrefix)
)}
itemSize={40}
showScrollbar={false}
onScroll={this.handleVirtualListScroll}
>
{{
default: ({ item }: { item: VNode }) => {
return item
}
}}
</VirtualList>
{{
default: () => (
<VirtualList
ref="yearScrollRef"
items={this.yearArray.map((yearItem, i) =>
renderItem(yearItem, i, mergedClsPrefix)
)}
itemSize={40}
showScrollbar={false}
onScroll={this.handleVirtualListScroll}
>
{{
default: ({ item }: { item: VNode }) => {
return item
}
}}
</VirtualList>
)
}}
</NScrollbar>
<div
class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}
>
<NScrollbar
ref="monthScrollRef"
// theme={mergedTheme.peers.Scrollbar}
// themeOverrides={mergedTheme.peerOverrides.Scrollbar}
theme={mergedTheme.peers.Scrollbar}
themeOverrides={mergedTheme.peerOverrides.Scrollbar}
>
{{
default: () => [
...this.monthArray.map((monthItem, i) =>
itemRenderer(monthItem, i, mergedClsPrefix)
renderItem(monthItem, i, mergedClsPrefix)
),
<div
class={`${mergedClsPrefix}-date-panel-month-calendar__padding`}
@ -179,7 +162,18 @@ export default defineComponent({
{{ default: () => this.locale.now }}
</NButton>
) : null}
{/** we don't need a confirm button for date picking */}
{this.actions?.includes('confirm') ? (
<NButton
theme={mergedTheme.peers.Button}
themeOverrides={mergedTheme.peerOverrides.Button}
size="tiny"
type="primary"
disabled={this.isDateInvalid}
onClick={this.handleConfirmClick}
>
{{ default: () => this.locale.confirm }}
</NButton>
) : null}
</div>
</div>
) : null}

View File

@ -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 {

View File

@ -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'
})
])
])

View File

@ -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

View File

@ -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
})