From 2e19e59e67cc55f6b2febff156330f86d9f75415 Mon Sep 17 00:00:00 2001 From: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com> Date: Thu, 21 Aug 2025 18:19:29 +0200 Subject: [PATCH] fix(components): [date-picker] add missing data slot (#19839) * feat: add missing date-picker data slot * chore: fix review & forward old test case Co-authored-by: btea <2356281422@qq.com> * Update docs/en-US/component/date-picker.md Co-authored-by: btea <2356281422@qq.com> * chore: update --------- Co-authored-by: btea <2356281422@qq.com> --- docs/en-US/component/date-picker.md | 7 ++- .../src/composables/use-basic-date-table.ts | 8 --- .../src/date-picker-com/basic-date-table.vue | 5 +- .../src/date-picker-com/basic-month-table.vue | 49 +++++++++++----- .../src/date-picker-com/basic-year-table.vue | 43 +++++++++++--- .../src/date-picker-com/panel-date-pick.vue | 2 + .../src/date-picker-com/panel-month-range.vue | 4 +- .../src/date-picker-com/panel-year-range.vue | 4 +- .../src/props/basic-date-table.ts | 5 +- .../date-picker-panel/src/props/shared.ts | 4 ++ .../date-picker/__tests__/date-picker.test.ts | 58 +++++++++++++++++++ 11 files changed, 147 insertions(+), 42 deletions(-) diff --git a/docs/en-US/component/date-picker.md b/docs/en-US/component/date-picker.md index 6840cd6ff5..a0e3d74f82 100644 --- a/docs/en-US/component/date-picker.md +++ b/docs/en-US/component/date-picker.md @@ -134,14 +134,15 @@ For data details, please refer: ```ts interface DateCell { column: number - customClass: string + customClass: string | undefined disabled: boolean end: boolean inRange: boolean row: number - selected: Dayjs - isCurrent: boolean + selected: Dayjs | undefined + isCurrent: boolean | undefined isSelected: boolean + renderText: string | undefined start: boolean text: number timestamp: number diff --git a/packages/components/date-picker-panel/src/composables/use-basic-date-table.ts b/packages/components/date-picker-panel/src/composables/use-basic-date-table.ts index 00bbf1733a..6200e3d9ed 100644 --- a/packages/components/date-picker-panel/src/composables/use-basic-date-table.ts +++ b/packages/components/date-picker-panel/src/composables/use-basic-date-table.ts @@ -259,13 +259,6 @@ export const useBasicDateTable = ( } } - const isSelectedCell = (cell: DateCell) => { - return ( - (!unref(hasCurrent) && cell?.text === 1 && cell.type === 'normal') || - cell.isCurrent - ) - } - const handleFocus = (event: FocusEvent) => { if (focusWithClick || unref(hasCurrent) || props.selectionMode !== 'date') return @@ -391,7 +384,6 @@ export const useBasicDateTable = ( focus, isCurrent, isWeekActive, - isSelectedCell, handlePickDate, handleMouseUp, diff --git a/packages/components/date-picker-panel/src/date-picker-com/basic-date-table.vue b/packages/components/date-picker-panel/src/date-picker-com/basic-date-table.vue index e9198c466f..cb61ec9dc0 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/basic-date-table.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/basic-date-table.vue @@ -30,11 +30,11 @@ @@ -68,7 +68,6 @@ const { focus, isCurrent, isWeekActive, - isSelectedCell, handlePickDate, handleMouseUp, diff --git a/packages/components/date-picker-panel/src/date-picker-com/basic-month-table.vue b/packages/components/date-picker-panel/src/date-picker-com/basic-month-table.vue index 2b642c643b..796a6b9354 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/basic-month-table.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/basic-month-table.vue @@ -11,11 +11,11 @@ @@ -40,15 +40,25 @@ import { basicMonthTableProps } from '../props/basic-month-table' import { datesInMonth, getValidDateOfMonth } from '../utils' import ElDatePickerCell from './basic-cell-render' +import type { Dayjs } from 'dayjs' + type MonthCell = { column: number - row: number + customClass: string | undefined disabled: boolean - start: boolean end: boolean - text: number - type: 'normal' | 'today' inRange: boolean + row: number + selected: Dayjs | undefined + isCurrent: boolean | undefined + isSelected: boolean + start: boolean + text: number + renderText: string | undefined + timestamp: number | undefined + date: Date | undefined + dayjs: Dayjs | undefined + type: 'normal' | 'today' } const props = defineProps(basicMonthTableProps) @@ -66,11 +76,7 @@ const months = ref( .monthsShort() .map((_) => _.toLowerCase()) ) -const tableRows = ref([ - [] as MonthCell[], - [] as MonthCell[], - [] as MonthCell[], -]) +const tableRows = ref([[], [], []]) const lastRow = ref() const lastColumn = ref() const rows = computed(() => { @@ -90,6 +96,14 @@ const rows = computed(() => { end: false, text: -1, disabled: false, + isSelected: false, + customClass: undefined, + date: undefined, + dayjs: undefined, + isCurrent: undefined, + selected: undefined, + renderText: undefined, + timestamp: undefined, }) cell.type = 'normal' @@ -130,8 +144,14 @@ const rows = computed(() => { cell.type = 'today' } + const cellDate = calTime.toDate() cell.text = index - cell.disabled = props.disabledDate?.(calTime.toDate()) || false + cell.disabled = props.disabledDate?.(cellDate) || false + cell.date = cellDate + cell.customClass = props.cellClassName?.(cellDate) + cell.dayjs = calTime + cell.timestamp = calTime.valueOf() + cell.isSelected = isSelectedCell(cell) } } return rows @@ -161,6 +181,9 @@ const getCellStyle = (cell: MonthCell) => { ) >= 0 style.today = today.getFullYear() === year && today.getMonth() === month + if (cell.customClass) { + style[cell.customClass] = true + } if (cell.inRange) { style['in-range'] = true diff --git a/packages/components/date-picker-panel/src/date-picker-com/basic-year-table.vue b/packages/components/date-picker-panel/src/date-picker-com/basic-year-table.vue index 5345461ef2..91940a9524 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/basic-year-table.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/basic-year-table.vue @@ -11,12 +11,12 @@ @@ -37,15 +37,25 @@ import { basicYearTableProps } from '../props/basic-year-table' import { getValidDateOfYear } from '../utils' import ElDatePickerCell from './basic-cell-render' +import type { Dayjs } from 'dayjs' + type YearCell = { column: number - row: number + customClass: string | undefined disabled: boolean - start: boolean end: boolean - text: number - type: 'normal' | 'today' inRange: boolean + row: number + selected: Dayjs | undefined + isCurrent: boolean | undefined + isSelected: boolean + start: boolean + text: number + renderText: string | undefined + timestamp: number | undefined + type: 'normal' | 'today' + date: Date | undefined + dayjs: Dayjs | undefined } const datesInYear = (year: number, lang: string) => { @@ -91,6 +101,14 @@ const rows = computed(() => { end: false, text: -1, disabled: false, + isSelected: false, + customClass: undefined, + date: undefined, + dayjs: undefined, + isCurrent: undefined, + selected: undefined, + renderText: undefined, + timestamp: undefined, } } cell.type = 'normal' @@ -131,8 +149,12 @@ const rows = computed(() => { } cell.text = index const cellDate = calTime.toDate() - cell.disabled = - (props.disabledDate && props.disabledDate(cellDate)) || false + cell.disabled = props.disabledDate?.(cellDate) || false + cell.date = cellDate + cell.customClass = props.cellClassName?.(cellDate) + cell.dayjs = calTime + cell.timestamp = calTime.valueOf() + cell.isSelected = isSelectedCell(cell) row[j] = cell } } @@ -158,6 +180,9 @@ const getCellKls = (cell: YearCell) => { kls.current = castArray(props.parsedValue).findIndex((d) => d!.year() === year) >= 0 + if (cell.customClass) { + kls[cell.customClass] = true + } if (cell.inRange) { kls['in-range'] = true diff --git a/packages/components/date-picker-panel/src/date-picker-com/panel-date-pick.vue b/packages/components/date-picker-panel/src/date-picker-com/panel-date-pick.vue index d59919788d..8ed9e36be8 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/panel-date-pick.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/panel-date-pick.vue @@ -166,6 +166,7 @@ :disabled-date="disabledDate" :disabled="disabled" :parsed-value="parsedValue" + :cell-class-name="cellClassName" @pick="handleYearPick" /> diff --git a/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue b/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue index ded0b6fd35..c7b061651b 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/panel-month-range.vue @@ -63,6 +63,7 @@ :range-state="rangeState" :disabled-date="disabledDate" :disabled="disabled" + :cell-class-name="cellClassName" @changerange="handleChangeRange" @pick="handleRangePick" @select="onSelect" @@ -103,6 +104,7 @@ :range-state="rangeState" :disabled-date="disabledDate" :disabled="disabled" + :cell-class-name="cellClassName" @changerange="handleChangeRange" @pick="handleRangePick" @select="onSelect" @@ -151,7 +153,7 @@ const isDefaultFormat = inject( ROOT_PICKER_IS_DEFAULT_FORMAT_INJECTION_KEY, undefined ) as any -const { shortcuts, disabledDate } = pickerBase.props +const { shortcuts, disabledDate, cellClassName } = pickerBase.props const format = toRef(pickerBase.props, 'format') const defaultValue = toRef(pickerBase.props, 'defaultValue') const leftDate = ref(dayjs().locale(lang.value)) diff --git a/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue b/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue index de57af059e..a668f3ffe6 100644 --- a/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue +++ b/packages/components/date-picker-panel/src/date-picker-com/panel-year-range.vue @@ -48,6 +48,7 @@ :range-state="rangeState" :disabled-date="disabledDate" :disabled="disabled" + :cell-class-name="cellClassName" @changerange="handleChangeRange" @pick="handleRangePick" @select="onSelect" @@ -86,6 +87,7 @@ :range-state="rangeState" :disabled-date="disabledDate" :disabled="disabled" + :cell-class-name="cellClassName" @changerange="handleChangeRange" @pick="handleRangePick" @select="onSelect" @@ -137,7 +139,7 @@ const isDefaultFormat = inject( undefined ) as any const pickerBase = inject(PICKER_BASE_INJECTION_KEY) as any -const { shortcuts, disabledDate } = pickerBase.props +const { shortcuts, disabledDate, cellClassName } = pickerBase.props const format = toRef(pickerBase.props, 'format') const defaultValue = toRef(pickerBase.props, 'defaultValue') diff --git a/packages/components/date-picker-panel/src/props/basic-date-table.ts b/packages/components/date-picker-panel/src/props/basic-date-table.ts index 9790a7a43a..24d5976a1a 100644 --- a/packages/components/date-picker-panel/src/props/basic-date-table.ts +++ b/packages/components/date-picker-panel/src/props/basic-date-table.ts @@ -1,4 +1,4 @@ -import { buildProps, definePropType } from '@element-plus/utils' +import { buildProps } from '@element-plus/utils' import { datePickerSharedProps, selectionModeWithDefault } from './shared' import type { ExtractPropTypes, __ExtractPublicPropTypes } from 'vue' @@ -6,9 +6,6 @@ import type { Dayjs } from 'dayjs' export const basicDateTableProps = buildProps({ ...datePickerSharedProps, - cellClassName: { - type: definePropType<(date: Date) => string>(Function), - }, showWeekNumber: Boolean, selectionMode: selectionModeWithDefault('date'), } as const) diff --git a/packages/components/date-picker-panel/src/props/shared.ts b/packages/components/date-picker-panel/src/props/shared.ts index ceeaaafcd3..ed61c308fd 100644 --- a/packages/components/date-picker-panel/src/props/shared.ts +++ b/packages/components/date-picker-panel/src/props/shared.ts @@ -23,8 +23,12 @@ export type RangeState = { } export type DisabledDateType = (date: Date) => boolean +export type CellClassNameType = (date: Date) => string export const datePickerSharedProps = buildProps({ + cellClassName: { + type: definePropType(Function), + }, disabledDate: { type: definePropType(Function), }, diff --git a/packages/components/date-picker/__tests__/date-picker.test.ts b/packages/components/date-picker/__tests__/date-picker.test.ts index 9c90be62c6..673ff3c842 100644 --- a/packages/components/date-picker/__tests__/date-picker.test.ts +++ b/packages/components/date-picker/__tests__/date-picker.test.ts @@ -588,6 +588,64 @@ describe('DatePicker', () => { vi.useRealTimers() }) + it('should have same common propreties for default slot', async () => { + const testCellData = (cell) => { + const cellProperties = [ + 'column', + 'type', + 'text', + 'start', + 'timestamp', + 'dayjs', + 'date', + 'isSelected', + 'inRange', + 'row', + 'customClass', + 'end', + ] //TODO: we should later increase the list in order to fit DateCell perfectly + expect(Object.keys(cell)).toEqual(expect.arrayContaining(cellProperties)) + const values = Object.entries(cell) + .filter(([key]) => cellProperties.includes(key)) + .map(([, val]) => val) + for (const value of values) { + expect(value).toBeDefined() + } + } + const wrapper = _mount( + ` + + + + `, + () => ({ testCellData }) + ) + const types = [ + 'year', + 'years', + 'month', + 'months', + 'date', + 'dates', + 'week', + 'datetime', + 'datetimerange', + 'daterange', + 'monthrange', + 'yearrange', + ] + for (const type of types) { + await wrapper.setProps({ type }) + { + ;(document.querySelector('.custom-cell') as HTMLElement).click() + } + } + }) + it('custom content', async () => { const wrapper = _mount( `