mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-21 04:50:14 +08:00
wip(date-picker): clean codes
This commit is contained in:
parent
56fb18e9d1
commit
47fac44d35
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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 {
|
||||
|
@ -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'
|
||||
})
|
||||
])
|
||||
])
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user