Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(date-picker): #2610 #2614

Merged
merged 1 commit into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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