Skip to content

Commit

Permalink
[pickers] Keep the calendar header and content in sync when switching…
Browse files Browse the repository at this point in the history
… locale (#14125)
  • Loading branch information
flaviendelangle authored Sep 2, 2024
1 parent aff6ddb commit 033f897
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 34 deletions.
9 changes: 4 additions & 5 deletions packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ export class AdapterDayjs implements MuiPickersAdapter<Dayjs, string> {
};

public startOfWeek = (value: Dayjs) => {
return this.adjustOffset(value.startOf('week'));
return this.adjustOffset(this.setLocaleToValue(value).startOf('week'));
};

public startOfDay = (value: Dayjs) => {
Expand All @@ -529,7 +529,7 @@ export class AdapterDayjs implements MuiPickersAdapter<Dayjs, string> {
};

public endOfWeek = (value: Dayjs) => {
return this.adjustOffset(value.endOf('week'));
return this.adjustOffset(this.setLocaleToValue(value).endOf('week'));
};

public endOfDay = (value: Dayjs) => {
Expand Down Expand Up @@ -639,9 +639,8 @@ export class AdapterDayjs implements MuiPickersAdapter<Dayjs, string> {
};

public getWeekArray = (value: Dayjs) => {
const cleanValue = this.setLocaleToValue(value);
const start = this.startOfWeek(this.startOfMonth(cleanValue));
const end = this.endOfWeek(this.endOfMonth(cleanValue));
const start = this.startOfWeek(this.startOfMonth(value));
const end = this.endOfWeek(this.endOfMonth(value));

let count = 0;
let current = start;
Expand Down
9 changes: 4 additions & 5 deletions packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ export class AdapterLuxon implements MuiPickersAdapter<DateTime, string> {
};

public startOfWeek = (value: DateTime) => {
return value.startOf('week', { useLocaleWeeks: true });
return this.setLocaleToValue(value).startOf('week', { useLocaleWeeks: true });
};

public startOfDay = (value: DateTime) => {
Expand All @@ -364,7 +364,7 @@ export class AdapterLuxon implements MuiPickersAdapter<DateTime, string> {
};

public endOfWeek = (value: DateTime) => {
return value.endOf('week', { useLocaleWeeks: true });
return this.setLocaleToValue(value).endOf('week', { useLocaleWeeks: true });
};

public endOfDay = (value: DateTime) => {
Expand Down Expand Up @@ -461,9 +461,8 @@ export class AdapterLuxon implements MuiPickersAdapter<DateTime, string> {
};

public getWeekArray = (value: DateTime) => {
const cleanValue = this.setLocaleToValue(value);
const firstDay = this.startOfWeek(this.startOfMonth(cleanValue));
const lastDay = this.endOfWeek(this.endOfMonth(cleanValue));
const firstDay = this.startOfWeek(this.startOfMonth(value));
const lastDay = this.endOfWeek(this.endOfMonth(value));

const { days } = lastDay.diff(firstDay, 'days').toObject();

Expand Down
9 changes: 4 additions & 5 deletions packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ export class AdapterMoment implements MuiPickersAdapter<Moment, string> {
};

public startOfWeek = (value: Moment) => {
return value.clone().startOf('week');
return this.setLocaleToValue(value.clone()).startOf('week');
};

public startOfDay = (value: Moment) => {
Expand All @@ -406,7 +406,7 @@ export class AdapterMoment implements MuiPickersAdapter<Moment, string> {
};

public endOfWeek = (value: Moment) => {
return value.clone().endOf('week');
return this.setLocaleToValue(value.clone()).endOf('week');
};

public endOfDay = (value: Moment) => {
Expand Down Expand Up @@ -516,9 +516,8 @@ export class AdapterMoment implements MuiPickersAdapter<Moment, string> {
};

public getWeekArray = (value: Moment) => {
const cleanValue = this.setLocaleToValue(value);
const start = this.startOfWeek(this.startOfMonth(cleanValue));
const end = this.endOfWeek(this.endOfMonth(cleanValue));
const start = this.startOfWeek(this.startOfMonth(value));
const end = this.endOfWeek(this.endOfMonth(value));

let count = 0;
let current = start;
Expand Down
13 changes: 0 additions & 13 deletions packages/x-date-pickers/src/DateCalendar/DateCalendar.spec.tsx

This file was deleted.

3 changes: 1 addition & 2 deletions packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,6 @@ export function DayCalendar<TDate extends PickerValidDate>(inProps: DayCalendarP
const transitionKey = `${currentYearNumber}-${currentMonthNumber}`;
// eslint-disable-next-line react-hooks/exhaustive-deps
const slideNodeRef = React.useMemo(() => React.createRef<HTMLDivElement>(), [transitionKey]);
const startOfCurrentWeek = utils.startOfWeek(now);

const focusableDay = React.useMemo<TDate | null>(() => {
const startOfMonth = utils.startOfMonth(currentMonth);
Expand Down Expand Up @@ -574,7 +573,7 @@ export function DayCalendar<TDate extends PickerValidDate>(inProps: DayCalendarP
key={i.toString()}
variant="caption"
role="columnheader"
aria-label={utils.format(utils.addDays(startOfCurrentWeek, i), 'weekday')}
aria-label={utils.format(weekday, 'weekday')}
className={classes.weekDayLabel}
>
{dayOfWeekFormatter(weekday)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import moment, { Moment } from 'moment';
import { DateCalendar } from '@mui/x-date-pickers/DateCalendar';

<DateCalendar />;
Expand All @@ -8,3 +9,13 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar';
<DateCalendar value={new Date()} />;

<DateCalendar value={null} />;

// External components are generic as well
<DateCalendar<Moment>
view="day"
views={['day']}
value={moment()}
minDate={moment()}
maxDate={moment()}
onChange={(date) => date?.format()}
/>;
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as React from 'react';
import { expect } from 'chai';
import { screen } from '@mui/internal-test-utils';
import { DateCalendar } from '@mui/x-date-pickers/DateCalendar';
import { createPickerRenderer, AdapterName } from 'test/utils/pickers';
import { he } from 'date-fns/locale';
import { screen, createRenderer } from '@mui/internal-test-utils';
import { DateCalendar, dayCalendarClasses } from '@mui/x-date-pickers/DateCalendar';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { createPickerRenderer, AdapterName, availableAdapters } from 'test/utils/pickers';
import { he, fr } from 'date-fns/locale';
import 'dayjs/locale/he';
import 'dayjs/locale/fr';
import 'moment/locale/he';
import 'moment/locale/fr';

const ADAPTERS_TO_USE: AdapterName[] = ['date-fns', 'dayjs', 'luxon', 'moment'];

Expand All @@ -17,11 +20,33 @@ describe('<DateCalendar /> - localization', () => {
adapterName,
});

const { render: renderWithoutWrapper } = createRenderer();

it('should display correct week day labels in Hebrew locale ', () => {
render(<DateCalendar />);

expect(screen.getByText('א')).toBeVisible();
});

it('should correctly switch between locale with week starting in Monday and week starting in Sunday', () => {
const { setProps } = renderWithoutWrapper(
<LocalizationProvider dateAdapter={availableAdapters[adapterName]}>
<DateCalendar reduceAnimations />
</LocalizationProvider>,
);

expect(document.querySelector(`.${dayCalendarClasses.weekDayLabel}`)!.ariaLabel).to.equal(
'Sunday',
);

setProps({
adapterLocale: adapterName === 'date-fns' ? fr : 'fr',
});

expect(document.querySelector(`.${dayCalendarClasses.weekDayLabel}`)!.ariaLabel).to.equal(
'lundi',
);
});
});
});
});

0 comments on commit 033f897

Please sign in to comment.