Skip to content

Commit

Permalink
feat(datepicker): support week multiple
Browse files Browse the repository at this point in the history
  • Loading branch information
HaixingOoO committed Dec 3, 2024
1 parent 51d7123 commit 647a3ac
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 12 deletions.
10 changes: 7 additions & 3 deletions src/date-picker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import useDefaultProps from '../hooks/useDefaultProps';
import useLatest from '../hooks/useLatest';
import useUpdateEffect from '../hooks/useUpdateEffect';
import type { TagInputRemoveContext } from '../tag-input';
import { useLocaleReceiver } from '../locale/LocalReceiver';

export interface DatePickerProps extends TdDatePickerProps, StyledProps {}

Expand Down Expand Up @@ -63,6 +64,7 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
setCacheValue,
} = useSingle(props);

const [local] = useLocaleReceiver('datePicker');
const { format, timeFormat, valueType } = getDefaultFormat({
mode,
format: props.format,
Expand Down Expand Up @@ -240,16 +242,18 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
}, []);

function processDate(date: Date) {
const isSameDate = (value as DateMultipleValue).some((val) => isSame(dayjs(val).toDate(), date));
const isSameDate = (value as DateMultipleValue).some((val) =>
isSame(parseToDayjs(val, format).toDate(), date, mode, local.dayjsLocale),
);
let currentDate: DateMultipleValue;

if (!isSameDate) {
currentDate = (value as DateMultipleValue).concat(formatDate(date, { format, targetFormat: valueType }));
} else {
currentDate = (value as DateMultipleValue).filter(
(val) =>
formatDate(val, { format, targetFormat: valueType }) !==
formatDate(date, { format, targetFormat: valueType }),
formatDate(val, { format, targetFormat: valueType, dayjsLocale: local.dayjsLocale }) !==
formatDate(date, { format, targetFormat: valueType, dayjsLocale: local.dayjsLocale }),
);
}

Expand Down
24 changes: 20 additions & 4 deletions src/date-picker/_example/multiple.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
import React, { useState } from 'react';
import { DatePicker } from 'tdesign-react';
import { DatePicker, Space } from 'tdesign-react';
import type { DatePickerProps, DateMultipleValue } from 'tdesign-react';

export default function YearDatePicker() {
const [defaultValue, setDefaultValue] = useState<DateMultipleValue>(['2000-01-04', '2000-01-03', '2000-01-05']);
const [defaultValue, setDefaultValue] = useState<DateMultipleValue>(['2000-01-04', '2000-01-03', '2000-01-10']);

const handleChange: DatePickerProps['onChange'] = (value: DateMultipleValue, context) => {
console.log('onChange:', value, context);
setDefaultValue(value);
};

return (
<div>
<Space direction="vertical">
{/* <DatePicker
value={defaultValue}
placeholder="可清除、可输入的日期选择器"
onChange={handleChange}
clearable
multiple
/> */}
<DatePicker
value={defaultValue}
placeholder="可清除、可输入的日期选择器"
onChange={handleChange}
clearable
multiple
mode="week"
/>
</div>
{/* <DatePicker
value={defaultValue}
placeholder="可清除、可输入的日期选择器"
onChange={handleChange}
clearable
multiple
mode="year"
/> */}
</Space>
);
}
37 changes: 33 additions & 4 deletions src/date-picker/base/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React, { useMemo } from 'react';
import classNames from 'classnames';
import type { Dayjs } from 'dayjs';
import { useLocaleReceiver } from '../../locale/LocalReceiver';
import useConfig from '../../hooks/useConfig';
import DatePickerCell from './Cell';
import { TdDatePickerProps } from '../type';
import type { DateMultipleValue, DateRangeValue, DateValue, TdDatePickerProps } from '../type';
import { SinglePanelProps } from '../panel/SinglePanel';
import { PanelContentProps } from '../panel/PanelContent';
import { parseToDayjs } from '../../_common/js/date-picker/format';

export interface DatePickerTableProps
extends Pick<TdDatePickerProps, 'mode' | 'firstDayOfWeek' | 'format'>,
extends Pick<TdDatePickerProps, 'mode' | 'firstDayOfWeek' | 'format' | 'multiple'>,
Pick<SinglePanelProps, 'onCellClick' | 'onCellMouseEnter' | 'onCellMouseLeave'>,
Pick<PanelContentProps, 'value'> {
data?: Array<any>;
Expand Down Expand Up @@ -55,8 +56,22 @@ const DatePickerTable = (props: DatePickerTableProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mode, value, format]);

const multipleValueYearWeek = useMemo(() => {
if (mode !== 'week' || (Array.isArray(value) && !value.length)) return [];

const DateMultipleValue = (value as DateMultipleValue).map((v) => v && parseToDayjs(v, format));

return DateMultipleValue.map((item) => {
const year = item?.year?.();
const week = item?.locale?.(local.dayjsLocale)?.week?.();

return { year, week };
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mode, value, format]);

// 高亮周区间
const weekRowClass = (value, targetDayjs) => {
const weekRowClass = (value: DateValue | DateRangeValue, targetDayjs: Dayjs) => {
if (mode !== 'week' || !value) return {};

if (Array.isArray(value)) {
Expand Down Expand Up @@ -85,6 +100,20 @@ const DatePickerTable = (props: DatePickerTableProps) => {
};
};

// multiple
const multipleWeekRowClass = (value: DateMultipleValue, targetDayjs: Dayjs) => {
if (mode !== 'week' || (Array.isArray(value) && !value.length)) return {};

const isSomeYearWeek = multipleValueYearWeek.some(
(item) => item.year === targetDayjs.year() && item.week === targetDayjs.week(),
);
return {
[`${classPrefix}-date-picker__table-${mode}-row--active`]: isSomeYearWeek,
};
};

const activeRowCss = props.multiple ? multipleWeekRowClass : weekRowClass;

return (
<div className={`${classPrefix}-date-picker__table`} onMouseLeave={(e) => onCellMouseLeave?.({ e })}>
<table>
Expand All @@ -102,7 +131,7 @@ const DatePickerTable = (props: DatePickerTableProps) => {
<tr
key={i}
className={classNames(`${classPrefix}-date-picker__table-${mode}-row`, {
...weekRowClass(value, row[0].dayjsObj),
...activeRowCss(value, row[0].dayjsObj),
})}
>
{row.map((col: any, j: number) => (
Expand Down
3 changes: 2 additions & 1 deletion src/date-picker/panel/PanelContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface PanelContentProps {
timePickerProps: SinglePanelProps['timePickerProps'];
firstDayOfWeek: SinglePanelProps['firstDayOfWeek'];
time: SinglePanelProps['time'];

multiple: SinglePanelProps['multiple'];
popupVisible?: boolean;
tableData: any[];
onMonthChange: SinglePanelProps['onMonthChange'] | RangePanelProps['onMonthChange'];
Expand Down Expand Up @@ -104,6 +104,7 @@ export default function PanelContent(props: PanelContentProps) {
time={time}
format={format}
firstDayOfWeek={firstDayOfWeek}
multiple={props.multiple}
onCellClick={(date: Date, { e }) => onCellClick?.(date, { e, partial })}
onCellMouseEnter={(date: Date) => onCellMouseEnter?.(date, { partial })}
onCellMouseLeave={onCellMouseLeave}
Expand Down

0 comments on commit 647a3ac

Please sign in to comment.