Skip to content

Commit 5340bed

Browse files
fix: reset monthSelectedIn when changeMonth is called in custom header
Fixes #3829 When using monthsShown >= 2 with a custom header, calling changeMonth() would produce inconsistent results depending on which calendar panel the user last selected a date in. This was because the monthSelectedIn state (which tracks the offset for multi-month display) was not being reset when changeMonth was explicitly called. This fix: - Adds onMonthSelectedInChange callback prop to Calendar component - Resets monthSelectedIn to 0 when changeMonth is called, ensuring the target month always appears in the leftmost position - Adds test to verify the fix
1 parent 5d228d3 commit 5340bed

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

src/calendar.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ type CalendarProps = React.PropsWithChildren<
180180
showPreviousMonths?: boolean;
181181
monthsShown?: number;
182182
monthSelectedIn?: number;
183+
onMonthSelectedInChange?: (monthSelectedIn: number) => void;
183184
onSelect: (
184185
day: Date,
185186
event?:
@@ -455,7 +456,12 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {
455456
({ date }) => ({
456457
date: setMonth(date, Number(month)),
457458
}),
458-
() => this.handleMonthChange(this.state.date),
459+
() => {
460+
this.handleMonthChange(this.state.date);
461+
// Reset monthSelectedIn to 0 so the target month appears in the leftmost position
462+
// This ensures consistent behavior when using changeMonth in custom headers
463+
this.props.onMonthSelectedInChange?.(0);
464+
},
459465
);
460466
};
461467

src/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,10 @@ export class DatePicker extends Component<DatePickerProps, DatePickerState> {
14611461
}
14621462
};
14631463

1464+
handleMonthSelectedInChange = (monthSelectedIn: number): void => {
1465+
this.setState({ monthSelectedIn });
1466+
};
1467+
14641468
renderCalendar = () => {
14651469
if (!this.props.inline && !this.isCalendarOpen()) {
14661470
return null;
@@ -1492,6 +1496,7 @@ export class DatePicker extends Component<DatePickerProps, DatePickerState> {
14921496
dropdownMode={
14931497
this.props.dropdownMode ?? DatePicker.defaultProps.dropdownMode
14941498
}
1499+
onMonthSelectedInChange={this.handleMonthSelectedInChange}
14951500
>
14961501
{this.props.children}
14971502
</Calendar>

src/test/calendar_test.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,47 @@ describe("Calendar", () => {
984984
expect(header).toHaveLength(1);
985985
expect(time).toHaveLength(1);
986986
});
987+
988+
it("should display the target month in the leftmost position when changeMonth is called with monthsShown >= 2", () => {
989+
// This test verifies the fix for issue #3829
990+
// When using changeMonth in a custom header with monthsShown >= 2,
991+
// the target month should always appear in the leftmost position
992+
// regardless of which calendar panel the user last selected a date in
993+
const onMonthSelectedInChangeSpy = jest.fn();
994+
995+
const renderCustomHeaderWithMonthSelect = ({
996+
changeMonth,
997+
}: {
998+
changeMonth: (month: number) => void;
999+
}) => (
1000+
<div className="custom-header">
1001+
<select
1002+
className="month-select"
1003+
onChange={({ target: { value } }) => changeMonth(Number(value))}
1004+
>
1005+
{months.map((option, index) => (
1006+
<option key={option} value={index}>
1007+
{option}
1008+
</option>
1009+
))}
1010+
</select>
1011+
</div>
1012+
);
1013+
1014+
const { calendar } = getCalendar({
1015+
renderCustomHeader: renderCustomHeaderWithMonthSelect,
1016+
monthsShown: 2,
1017+
onMonthSelectedInChange: onMonthSelectedInChangeSpy,
1018+
});
1019+
1020+
// Select June (month index 5) from the month dropdown
1021+
const monthSelect = safeQuerySelector(calendar, ".month-select");
1022+
fireEvent.change(monthSelect, { target: { value: 5 } });
1023+
1024+
// Verify that onMonthSelectedInChange was called with 0
1025+
// This ensures the target month appears in the leftmost position
1026+
expect(onMonthSelectedInChangeSpy).toHaveBeenCalledWith(0);
1027+
});
9871028
});
9881029

9891030
describe("when showDisabledMonthNavigation is enabled", () => {

0 commit comments

Comments
 (0)