From 033f897c2f600bb788bd3a74461f0ad642b139c6 Mon Sep 17 00:00:00 2001 From: Flavien DELANGLE Date: Mon, 2 Sep 2024 16:18:01 +0200 Subject: [PATCH] [pickers] Keep the calendar header and content in sync when switching locale (#14125) --- .../src/AdapterDayjs/AdapterDayjs.ts | 9 +++-- .../src/AdapterLuxon/AdapterLuxon.ts | 9 +++-- .../src/AdapterMoment/AdapterMoment.ts | 9 +++-- .../src/DateCalendar/DateCalendar.spec.tsx | 13 -------- .../src/DateCalendar/DayCalendar.tsx | 3 +- .../DateCalendar/tests/DateCalendar.spec.tsx | 11 +++++++ .../tests/localization.DateCalendar.test.tsx | 33 ++++++++++++++++--- 7 files changed, 53 insertions(+), 34 deletions(-) delete mode 100644 packages/x-date-pickers/src/DateCalendar/DateCalendar.spec.tsx diff --git a/packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts b/packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts index 1245f256ea80..cf564eb4e6ac 100644 --- a/packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts +++ b/packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts @@ -513,7 +513,7 @@ export class AdapterDayjs implements MuiPickersAdapter { }; public startOfWeek = (value: Dayjs) => { - return this.adjustOffset(value.startOf('week')); + return this.adjustOffset(this.setLocaleToValue(value).startOf('week')); }; public startOfDay = (value: Dayjs) => { @@ -529,7 +529,7 @@ export class AdapterDayjs implements MuiPickersAdapter { }; public endOfWeek = (value: Dayjs) => { - return this.adjustOffset(value.endOf('week')); + return this.adjustOffset(this.setLocaleToValue(value).endOf('week')); }; public endOfDay = (value: Dayjs) => { @@ -639,9 +639,8 @@ export class AdapterDayjs implements MuiPickersAdapter { }; 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; diff --git a/packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts b/packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts index 3fd21f704315..edaee013c9be 100644 --- a/packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts +++ b/packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts @@ -348,7 +348,7 @@ export class AdapterLuxon implements MuiPickersAdapter { }; public startOfWeek = (value: DateTime) => { - return value.startOf('week', { useLocaleWeeks: true }); + return this.setLocaleToValue(value).startOf('week', { useLocaleWeeks: true }); }; public startOfDay = (value: DateTime) => { @@ -364,7 +364,7 @@ export class AdapterLuxon implements MuiPickersAdapter { }; public endOfWeek = (value: DateTime) => { - return value.endOf('week', { useLocaleWeeks: true }); + return this.setLocaleToValue(value).endOf('week', { useLocaleWeeks: true }); }; public endOfDay = (value: DateTime) => { @@ -461,9 +461,8 @@ export class AdapterLuxon implements MuiPickersAdapter { }; 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(); diff --git a/packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts b/packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts index 57ba9986e51f..a6e5288f2ed9 100644 --- a/packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts +++ b/packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts @@ -390,7 +390,7 @@ export class AdapterMoment implements MuiPickersAdapter { }; public startOfWeek = (value: Moment) => { - return value.clone().startOf('week'); + return this.setLocaleToValue(value.clone()).startOf('week'); }; public startOfDay = (value: Moment) => { @@ -406,7 +406,7 @@ export class AdapterMoment implements MuiPickersAdapter { }; public endOfWeek = (value: Moment) => { - return value.clone().endOf('week'); + return this.setLocaleToValue(value.clone()).endOf('week'); }; public endOfDay = (value: Moment) => { @@ -516,9 +516,8 @@ export class AdapterMoment implements MuiPickersAdapter { }; 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; diff --git a/packages/x-date-pickers/src/DateCalendar/DateCalendar.spec.tsx b/packages/x-date-pickers/src/DateCalendar/DateCalendar.spec.tsx deleted file mode 100644 index 7fbd799e2208..000000000000 --- a/packages/x-date-pickers/src/DateCalendar/DateCalendar.spec.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import moment, { Moment } from 'moment'; -import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; - -// External components are generic as well - - view="day" - views={['day']} - value={moment()} - minDate={moment()} - maxDate={moment()} - onChange={(date) => date?.format()} -/>; diff --git a/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx b/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx index f1a173e45249..31d01710d5bf 100644 --- a/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx +++ b/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx @@ -502,7 +502,6 @@ export function DayCalendar(inProps: DayCalendarP const transitionKey = `${currentYearNumber}-${currentMonthNumber}`; // eslint-disable-next-line react-hooks/exhaustive-deps const slideNodeRef = React.useMemo(() => React.createRef(), [transitionKey]); - const startOfCurrentWeek = utils.startOfWeek(now); const focusableDay = React.useMemo(() => { const startOfMonth = utils.startOfMonth(currentMonth); @@ -574,7 +573,7 @@ export function DayCalendar(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)} diff --git a/packages/x-date-pickers/src/DateCalendar/tests/DateCalendar.spec.tsx b/packages/x-date-pickers/src/DateCalendar/tests/DateCalendar.spec.tsx index bd049cba6fd9..53ff42ee719a 100644 --- a/packages/x-date-pickers/src/DateCalendar/tests/DateCalendar.spec.tsx +++ b/packages/x-date-pickers/src/DateCalendar/tests/DateCalendar.spec.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import moment, { Moment } from 'moment'; import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; ; @@ -8,3 +9,13 @@ import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; ; ; + +// External components are generic as well + + view="day" + views={['day']} + value={moment()} + minDate={moment()} + maxDate={moment()} + onChange={(date) => date?.format()} +/>; diff --git a/packages/x-date-pickers/src/DateCalendar/tests/localization.DateCalendar.test.tsx b/packages/x-date-pickers/src/DateCalendar/tests/localization.DateCalendar.test.tsx index 6b4105506de2..90d8c9bc6040 100644 --- a/packages/x-date-pickers/src/DateCalendar/tests/localization.DateCalendar.test.tsx +++ b/packages/x-date-pickers/src/DateCalendar/tests/localization.DateCalendar.test.tsx @@ -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']; @@ -17,11 +20,33 @@ describe(' - localization', () => { adapterName, }); + const { render: renderWithoutWrapper } = createRenderer(); + it('should display correct week day labels in Hebrew locale ', () => { render(); expect(screen.getByText('א')).toBeVisible(); }); + + it('should correctly switch between locale with week starting in Monday and week starting in Sunday', () => { + const { setProps } = renderWithoutWrapper( + + + , + ); + + 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', + ); + }); }); }); });