Skip to content

Commit 134b14e

Browse files
Merge pull request #6067 from kykim00/feature/format-multiple-dates
feat: add formatMultipleDates prop to DatePicker
2 parents 928b2cf + aa0af9d commit 134b14e

File tree

5 files changed

+88
-1
lines changed

5 files changed

+88
-1
lines changed

docs-site/src/components/Examples/config.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import SpecificDateRange from "../../examples/ts/specificDateRange?raw";
9696
import ExcludeTimePeriod from "../../examples/ts/excludeTimePeriod?raw";
9797
import SelectsMultiple from "../../examples/ts/selectsMultiple?raw";
9898
import SelectsMultipleMonths from "../../examples/ts/selectsMultipleMonths?raw";
99+
import SelectsMultipleFormat from "../../examples/ts/selectsMultipleFormat?raw";
99100
import StrictParsing from "../../examples/ts/strictParsing?raw";
100101
import TabIndex from "../../examples/ts/tabIndex?raw";
101102
import Today from "../../examples/ts/today?raw";
@@ -501,6 +502,10 @@ export const EXAMPLE_CONFIG: IExampleConfig[] = [
501502
title: "Select multiple dates",
502503
component: SelectsMultiple,
503504
},
505+
{
506+
title: "Select multiple dates with custom format",
507+
component: SelectsMultipleFormat,
508+
},
504509
{
505510
title: "Select multiple months",
506511
component: SelectsMultipleMonths,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const SelectsMultipleFormat = () => {
2+
const [selectedDates, setSelectedDates] = useState<Date[]>([]);
3+
4+
const onChange = (dates: Date[] | null) => {
5+
setSelectedDates(dates ?? []);
6+
};
7+
8+
const formatMultipleDates = (
9+
dates: Date[],
10+
formatDate: (date: Date) => string,
11+
) => {
12+
return dates.map(formatDate).join(" | ");
13+
};
14+
15+
return (
16+
<DatePicker
17+
selectedDates={selectedDates}
18+
selectsMultiple
19+
onChange={onChange}
20+
shouldCloseOnSelect={false}
21+
disabledKeyboardNavigation
22+
formatMultipleDates={formatMultipleDates}
23+
/>
24+
);
25+
};
26+
27+
render(SelectsMultipleFormat);

src/index.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ export type DatePickerProps = OmitUnion<
218218
| {
219219
selectsRange?: never;
220220
selectsMultiple?: never;
221+
formatMultipleDates?: never;
221222
onChange?: (
222223
date: Date | null,
223224
event?:
@@ -228,6 +229,7 @@ export type DatePickerProps = OmitUnion<
228229
| {
229230
selectsRange: true;
230231
selectsMultiple?: never;
232+
formatMultipleDates?: never;
231233
onChange?: (
232234
date: [Date | null, Date | null],
233235
event?:
@@ -238,8 +240,12 @@ export type DatePickerProps = OmitUnion<
238240
| {
239241
selectsRange?: never;
240242
selectsMultiple: true;
243+
formatMultipleDates?: (
244+
dates: Date[],
245+
formatDate: (date: Date) => string,
246+
) => string;
241247
onChange?: (
242-
date: Date[] | null,
248+
dates: Date[] | null,
243249
event?:
244250
| React.MouseEvent<HTMLElement>
245251
| React.KeyboardEvent<HTMLElement>,
@@ -448,6 +454,7 @@ export class DatePicker extends Component<DatePickerProps, DatePickerState> {
448454
selectedDates,
449455
selectsMultiple,
450456
selectsRange,
457+
formatMultipleDates,
451458
value,
452459
} = this.props;
453460
const dateFormat =
@@ -466,6 +473,11 @@ export class DatePicker extends Component<DatePickerProps, DatePickerState> {
466473
rangeSeparator,
467474
});
468475
} else if (selectsMultiple) {
476+
if (formatMultipleDates) {
477+
const formatDateFn = (date: Date) =>
478+
safeDateFormat(date, { dateFormat, locale });
479+
return formatMultipleDates(selectedDates ?? [], formatDateFn);
480+
}
469481
return safeMultipleDatesFormat(selectedDates ?? [], {
470482
dateFormat,
471483
locale,

src/test/min_time_test.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const DatePickerWithState = (
2424
| "dateFormat"
2525
| "selectsRange"
2626
| "selectsMultiple"
27+
| "formatMultipleDates"
2728
| "onSelect"
2829
>,
2930
) => {

src/test/multiple_selected_dates.test.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,46 @@ describe("Multiple Dates Selected", function () {
9393
expect(input).not.toBeNull();
9494
expect(input?.value).toBe("01/01/2024 (+2)");
9595
});
96+
97+
it("should override default format when formatMultipleDates is provided", () => {
98+
const { container: datePicker } = getDatePicker({
99+
selectsMultiple: true,
100+
selectedDates: [
101+
new Date("2024/01/01"),
102+
new Date("2024/01/15"),
103+
new Date("2024/03/15"),
104+
],
105+
formatMultipleDates: (dates, formatDate) =>
106+
dates.map(formatDate).join(" | "),
107+
});
108+
109+
const input = datePicker.querySelector("input");
110+
111+
expect(input).not.toBeNull();
112+
expect(input?.value).toBe("01/01/2024 | 01/15/2024 | 03/15/2024");
113+
});
114+
115+
it("should pass correct arguments to formatMultipleDates", () => {
116+
const selectedDates = [new Date("2024/01/01"), new Date("2024/01/15")];
117+
const mockFormatter = jest.fn(
118+
(dates: Date[], formatDate: (d: Date) => string) =>
119+
dates.map(formatDate).join(", "),
120+
);
121+
122+
getDatePicker({
123+
selectsMultiple: true,
124+
selectedDates,
125+
formatMultipleDates: mockFormatter,
126+
});
127+
128+
expect(mockFormatter).toHaveBeenCalledTimes(1);
129+
130+
const [receivedDates, receivedFormatDate] = mockFormatter.mock.calls[0]!;
131+
expect(receivedDates).toHaveLength(2);
132+
expect(receivedDates[0]?.getTime()).toBe(selectedDates[0]?.getTime());
133+
expect(receivedDates[1]?.getTime()).toBe(selectedDates[1]?.getTime());
134+
135+
expect(typeof receivedFormatDate).toBe("function");
136+
expect(receivedFormatDate(new Date("2024/01/01"))).toBe("01/01/2024");
137+
});
96138
});

0 commit comments

Comments
 (0)