Skip to content

Commit

Permalink
Merge pull request #2614 from XiaoMi/feature/date-picker(#2610)
Browse files Browse the repository at this point in the history
feat(date-picker): #2610
  • Loading branch information
solarjoker authored Oct 8, 2023
2 parents 15213b1 + db9fca5 commit 84ad061
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-goats-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/hiui": patch
---

DatePicker feat: add cellRender api
5 changes: 5 additions & 0 deletions .changeset/yellow-trees-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/date-picker": minor
---

feat: add cellRender api
2 changes: 2 additions & 0 deletions packages/ui/date-picker/src/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const DatePicker = forwardRef<HTMLDivElement | null, DatePickerProps>(
overlay,
invalid = false,
onClose,
cellRender,
...otherProps
},
ref
Expand Down Expand Up @@ -414,6 +415,7 @@ export const DatePicker = forwardRef<HTMLDivElement | null, DatePickerProps>(
showPanel,
isInDateRangeTimeMode,
size,
cellRender,
}}
>
<div className={cx(prefixCls, className)} {...otherProps}>
Expand Down
32 changes: 25 additions & 7 deletions packages/ui/date-picker/src/components/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Calendar = ({
altCalendarPresetData,
dateMarkPresetData,
prefixCls,
cellRender,
} = useContext(DPContext)

// const largeCell = !!(altCalendar || altCalendarPreset || dateMarkRender || dateMarkPreset)
Expand Down Expand Up @@ -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(' ')
}
Expand All @@ -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<HTMLTableElement, MouseEvent>) => {
Expand All @@ -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')
Expand Down Expand Up @@ -266,7 +279,8 @@ const Calendar = ({
<div
className={cx(
`${prefixCls}__calendar-wrap`,
`${prefixCls}__calendar-wrap--${isLarge ? 'lg' : 'md'}`
`${prefixCls}__calendar-wrap--${isLarge ? 'lg' : 'md'}`,
`${prefixCls}__calendar-wrap--type-${type}`
)}
>
<CSSTransition in={holidayFullNameShow} timeout={300} classNames={`${prefixCls}__indiaHoli`}>
Expand All @@ -278,7 +292,7 @@ const Calendar = ({
{(view.includes('date') || view.includes('week')) && (
<thead>
<tr>
{getWeeks().map((item: React.ReactNode, index: number) => {
{getWeeks(type).map((item: React.ReactNode, index: number) => {
return <th key={index}>{item}</th>
})}
</tr>
Expand All @@ -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 (
<td
key={_index}
Expand Down Expand Up @@ -336,9 +356,7 @@ const Calendar = ({
// @ts-ignore
belong-full-out-of-range={isBelongFullOutOfRange}
>
{parseInt(String(cell.text || cell.value)) < 10
? '0' + (cell.text || cell.value)
: cell.text || cell.value}
{cellRender ? cellRender(cell) : cellValue}
</span>
{renderAltCalendar(cell, isBelongFullOutOfRange)}
</div>
Expand Down
40 changes: 38 additions & 2 deletions packages/ui/date-picker/src/hooks/useCalenderData.tsx
Original file line number Diff line number Diff line change
@@ -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 = ({
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions packages/ui/date-picker/src/styles/date-picker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions packages/ui/date-picker/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -256,4 +257,8 @@ export interface DatePickerProps extends Omit<HiBaseHTMLProps<'div'>, 'placehold
* 面板关闭时回调
*/
onClose?: () => void
/**
* 自定义单元格内容
*/
cellRender?: (colInfo: CalendarColInfo) => React.ReactNode
}
102 changes: 102 additions & 0 deletions packages/ui/date-picker/stories/cell-render.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from 'react'
import DatePicker from '../src'

/**
* @title 自定义单元格内容
*/
export const CellRender = () => {
return (
<>
<h1>CellRender</h1>
<div className="date-picker-ymw__wrap">
<h2>年份</h2>
<DatePicker
style={{ width: 238 }}
type="year"
cellRender={(info) => {
const { type, text } = info

return type === 'today' ? <strong>{text}</strong> : text
}}
onChange={(date, dateStr) => {
console.log('onChange', date, dateStr)
}}
/>
<h2>月份</h2>
<DatePicker
style={{ width: 238 }}
type="month"
cellRender={(info) => {
const { type, text } = info
return type === 'today' ? <strong>{text}</strong> : text
}}
onChange={(date, dateStr) => {
console.log('onChange', date, dateStr)
}}
/>

<h2></h2>
<DatePicker
style={{ width: 238 }}
type="week"
defaultValue={new Date()}
cellRender={(info) => {
const { value, weekNum } = info

return weekNum ? weekNum + 'W' : value
}}
onChange={(date, dateStr) => {
console.log('onChange', date, dateStr)
}}
/>
<h2>周范围</h2>
<DatePicker
style={{ width: 560 }}
type="weekrange"
defaultValue={new Date()}
format={`YYYY年第w周`}
cellRender={(cellInfo) => {
// 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)
}}
/>
</div>
</>
)
}
1 change: 1 addition & 0 deletions packages/ui/date-picker/stories/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down

0 comments on commit 84ad061

Please sign in to comment.