diff --git a/.changeset/brave-goats-hide.md b/.changeset/brave-goats-hide.md new file mode 100644 index 000000000..22370c6cd --- /dev/null +++ b/.changeset/brave-goats-hide.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +DatePicker feat: add cellRender api diff --git a/.changeset/yellow-trees-sneeze.md b/.changeset/yellow-trees-sneeze.md new file mode 100644 index 000000000..952658ce0 --- /dev/null +++ b/.changeset/yellow-trees-sneeze.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/date-picker": minor +--- + +feat: add cellRender api diff --git a/packages/ui/date-picker/src/DatePicker.tsx b/packages/ui/date-picker/src/DatePicker.tsx index 11c441a5a..4a9a61045 100644 --- a/packages/ui/date-picker/src/DatePicker.tsx +++ b/packages/ui/date-picker/src/DatePicker.tsx @@ -73,6 +73,7 @@ export const DatePicker = forwardRef( overlay, invalid = false, onClose, + cellRender, ...otherProps }, ref @@ -414,6 +415,7 @@ export const DatePicker = forwardRef( showPanel, isInDateRangeTimeMode, size, + cellRender, }} >
diff --git a/packages/ui/date-picker/src/components/calendar.tsx b/packages/ui/date-picker/src/components/calendar.tsx index 2b8066cfc..5fea02ae0 100644 --- a/packages/ui/date-picker/src/components/calendar.tsx +++ b/packages/ui/date-picker/src/components/calendar.tsx @@ -39,6 +39,7 @@ const Calendar = ({ altCalendarPresetData, dateMarkPresetData, prefixCls, + cellRender, } = useContext(DPContext) // const largeCell = !!(altCalendar || altCalendarPreset || dateMarkRender || dateMarkPreset) @@ -91,6 +92,7 @@ const Calendar = ({ td.rangeStart && _class.push(`${prefixCls}__cell--range-start`) td.rangeEnd && _class.push(`${prefixCls}__cell--range-end`) isInWeekMode && _class.push(`${prefixCls}__cell--week-mode-select`) + td.weekNum && _class.push(`${prefixCls}__cell--weekNum`) return _class.join(' ') } @@ -99,10 +101,15 @@ const Calendar = ({ setCalenderCls(cx(`${prefixCls}__calendar`, `${prefixCls}__calendar--${view}`)) }, [prefixCls, view]) - const getWeeks = () => { + const getWeeks = (type: string) => { const week: string[] = i18n.get('datePicker.week') as any // 根据偏移做数组移位,展示顶部星期文案 - return week.slice(weekOffset).concat(week.slice(0, weekOffset)) + const _week = week.slice(weekOffset).concat(week.slice(0, weekOffset)) + + // 如果是周选择类型,第一个th增加一个空白标题 + if (type === 'week' || type === 'weekrange') _week.unshift('') + + return _week } const onTableClick = (e: React.MouseEvent) => { @@ -118,6 +125,12 @@ const Calendar = ({ const cellType = td.getAttribute('type') const cellWeekType = td.getAttribute('weektype') + // 如果点击的是周数,则直接拿到该周的周一日期返回 + if (cellType === 'week') { + onPick(moment().isoWeek(clickVal)) + return false + } + if (type !== 'weekrange' || isBelongFullOurOfRange) { if (cellType === 'prev' || cellWeekType === 'prev') { _date.subtract(1, 'months') @@ -266,7 +279,8 @@ const Calendar = ({
@@ -278,7 +292,7 @@ const Calendar = ({ {(view.includes('date') || view.includes('week')) && ( - {getWeeks().map((item: React.ReactNode, index: number) => { + {getWeeks(type).map((item: React.ReactNode, index: number) => { return {item} })} @@ -302,6 +316,12 @@ const Calendar = ({ })} > {row.map((cell, _index) => { + const cellValue = cell.weekNum + ? cell.weekNum + : parseInt(String(cell.text || cell.value)) < 10 + ? '0' + (cell.text || cell.value) + : cell.text || cell.value + return ( - {parseInt(String(cell.text || cell.value)) < 10 - ? '0' + (cell.text || cell.value) - : cell.text || cell.value} + {cellRender ? cellRender(cell) : cellValue} {renderAltCalendar(cell, isBelongFullOutOfRange)}
diff --git a/packages/ui/date-picker/src/hooks/useCalenderData.tsx b/packages/ui/date-picker/src/hooks/useCalenderData.tsx index f3f820be4..75a3e4b90 100644 --- a/packages/ui/date-picker/src/hooks/useCalenderData.tsx +++ b/packages/ui/date-picker/src/hooks/useCalenderData.tsx @@ -1,8 +1,8 @@ import { useState, useEffect } from 'react' -import moment from 'moment' +import moment, { Moment } from 'moment' import { DAY_MILLISECONDS } from '../utils/constants' import { DatePickerTypeEnum, DisabledDate } from '../types' -import { getBelongWeekBoundary } from '../utils/week' +import { getBelongWeek, getBelongWeekBoundary } from '../utils/week' import { UseLocaleContext } from '@hi-ui/core' const getYearOrMonthRows = ({ @@ -338,6 +338,39 @@ const getDateRows = ({ } } } + + // 如果是周类型,则计算出每一行的周数并放入每行数组第一个 + if (type === 'week' || type === 'weekrange') { + const year = _date.year() + const month = _date.month() + 1 + + for (let i = 0, len = rows.length; i < len; i++) { + const item = rows[i][0] + const { type, value } = item + let _year = year + let _month = type === 'prev' ? month - 1 : type === 'next' ? month + 1 : month + + if (_month > 12) { + _year = _year + 1 + _month = 1 + } + + if (_month < 1) { + _year = _year - 1 + _month = 12 + } + + const weekStartDate = getBelongWeekBoundary(moment(`${_year}-${_month}-${value}`), weekOffset) + + rows[i].unshift({ + ...item, + weekNum: getBelongWeek(weekStartDate, weekOffset), + weekStartDate, + renderDate: _date, + }) + } + } + return rows } @@ -356,6 +389,9 @@ export interface CalendarColInfo { value: number weekType: CalendarRowType text: string | number + weekNum?: number + weekStartDate?: Moment + renderDate?: Moment } export type CalendarRowInfo = CalendarColInfo[] & { weekNum: number diff --git a/packages/ui/date-picker/src/styles/date-picker.scss b/packages/ui/date-picker/src/styles/date-picker.scss index 9f1745401..720a605ff 100644 --- a/packages/ui/date-picker/src/styles/date-picker.scss +++ b/packages/ui/date-picker/src/styles/date-picker.scss @@ -340,6 +340,10 @@ $calendar-large-background-border-radius: $calendar-large-indicator-border-radiu &--md { width: 240px; // https://github.com/XiaoMi/hiui/issues/2400 + + &.#{$prefix}__calendar-wrap--type-week, &.#{$prefix}__calendar-wrap--type-weekrange { + width: 280px; + } } &--lg { @@ -386,6 +390,11 @@ $calendar-large-background-border-radius: $calendar-large-indicator-border-radiu z-index: 0; padding: 0; + &--weekNum { + width: 40px; + color: use-color('gray', 400); + } + &-text, &-week-indicator { width: 28px; diff --git a/packages/ui/date-picker/src/types.ts b/packages/ui/date-picker/src/types.ts index 7700cad85..c71e040e7 100644 --- a/packages/ui/date-picker/src/types.ts +++ b/packages/ui/date-picker/src/types.ts @@ -2,6 +2,7 @@ import React from 'react' import { HiBaseHTMLProps } from '@hi-ui/core' import { PopperOverlayProps } from '@hi-ui/popper' import { TimePickerPanelType } from '@hi-ui/time-picker' +import { CalendarColInfo } from './hooks/useCalenderData' export type CalendarViewEnum = 'date' | 'year' | 'month' @@ -256,4 +257,8 @@ export interface DatePickerProps extends Omit, 'placehold * 面板关闭时回调 */ onClose?: () => void + /** + * 自定义单元格内容 + */ + cellRender?: (colInfo: CalendarColInfo) => React.ReactNode } diff --git a/packages/ui/date-picker/stories/cell-render.stories.tsx b/packages/ui/date-picker/stories/cell-render.stories.tsx new file mode 100644 index 000000000..4a846374d --- /dev/null +++ b/packages/ui/date-picker/stories/cell-render.stories.tsx @@ -0,0 +1,102 @@ +import React from 'react' +import DatePicker from '../src' + +/** + * @title 自定义单元格内容 + */ +export const CellRender = () => { + return ( + <> +

CellRender

+
+

年份

+ { + const { type, text } = info + + return type === 'today' ? {text} : text + }} + onChange={(date, dateStr) => { + console.log('onChange', date, dateStr) + }} + /> +

月份

+ { + const { type, text } = info + return type === 'today' ? {text} : text + }} + onChange={(date, dateStr) => { + console.log('onChange', date, dateStr) + }} + /> + +

+ { + const { value, weekNum } = info + + return weekNum ? weekNum + 'W' : value + }} + onChange={(date, dateStr) => { + console.log('onChange', date, dateStr) + }} + /> +

周范围

+ { + // console.log('cellInfo', cellInfo) + + const { value, weekNum } = cellInfo + + if (weekNum) { + // weekStartDate 周一日期 + // renderDate 当前月日期 + const { weekStartDate, renderDate } = cellInfo + // 当前周最后一天 + const weekEndDate = weekStartDate?.clone().add(6, 'day') + + if ( + weekEndDate && + renderDate && + (weekEndDate?.month() > renderDate?.month() || + weekEndDate?.year() > renderDate?.year()) && + weekStartDate?.month() === renderDate?.month() + ) { + return weekNum + 'A' + } + + if ( + weekStartDate && + renderDate && + (weekStartDate?.month() < renderDate?.month() || + weekStartDate?.year() < renderDate?.year()) && + weekEndDate?.month() === renderDate?.month() + ) { + return weekNum + 'B' + } + + return weekNum + } else { + return value + } + }} + onChange={(date, dateStr) => { + console.log('onChange', date, dateStr) + }} + /> +
+ + ) +} diff --git a/packages/ui/date-picker/stories/index.stories.tsx b/packages/ui/date-picker/stories/index.stories.tsx index 8450cf500..839c882c3 100644 --- a/packages/ui/date-picker/stories/index.stories.tsx +++ b/packages/ui/date-picker/stories/index.stories.tsx @@ -4,6 +4,7 @@ import DatePicker from '../src' export * from './basic.stories' export * from './appearance.stories' export * from './year-month-week.stories' +export * from './cell-render.stories' export * from './date-time.stories' export * from './range.stories' export * from './shortcut.stories'