Skip to content

Commit 10d0f0a

Browse files
committed
fix: multi-calendars not correctly displayed in specific range differences (fixes #540)
1 parent b4f6947 commit 10d0f0a

File tree

4 files changed

+57
-8
lines changed

4 files changed

+57
-8
lines changed

src/VueDatePicker/components/DatePicker/DpHeader.vue

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@
2727
<button
2828
type="button"
2929
class="dp__btn dp__month_year_select"
30+
tabindex="0"
31+
:aria-label="type.ariaLabel"
32+
:ref="(el) => setElRefs(el, i + 1)"
33+
:data-test="`${type.type}-toggle-overlay-${instance}`"
3034
@click="type.toggle"
3135
@keydown.enter.prevent="type.toggle"
3236
@keydown.space.prevent="type.toggle"
33-
:aria-label="type.ariaLabel"
34-
tabindex="0"
35-
:ref="(el) => setElRefs(el, i + 1)"
3637
>
3738
<slot v-if="$slots[type.type]" :name="type.type" v-bind="{ text: type.text }" />
3839
<template v-if="!$slots[type.type]">{{ type.text }}</template>

src/VueDatePicker/components/DatePicker/date-picker.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
add,
44
addDays,
55
addMonths,
6-
differenceInMonths,
76
getHours,
87
getMinutes,
98
getMonth,
@@ -154,9 +153,18 @@ export const useDatePicker = (
154153
}
155154
};
156155

156+
/**
157+
* In case of multi-calendars, check if the range can fit within the view
158+
* If it can, set focus index to the first date in the range, rest will be auto adjusted
159+
* In case of solo multi calendars, always take 0 index as reference
160+
*/
157161
const getRangeFocusIndex = (dates: Date[]) => {
158162
if (defaultedMultiCalendars.value.count) {
159-
return Math.abs(differenceInMonths(dates[0], dates[1])) >= defaultedMultiCalendars.value.count ? 1 : 0;
163+
if (defaultedMultiCalendars.value.solo) return 0;
164+
const startMonth = getMonth(dates[0]);
165+
const endMonth = getMonth(dates[1]);
166+
const showInTheSameView = Math.abs(endMonth - startMonth) < defaultedMultiCalendars.value.count;
167+
return showInTheSameView ? 0 : 1;
160168
}
161169
return 1;
162170
};

tests/unit/behaviour.spec.ts

+38-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import { utcToZonedTime } from 'date-fns-tz/esm';
44

55
import { resetDateTime } from '@/utils/date-utils';
66

7-
import { openMenu } from '../utils';
7+
import { getMonthName, openMenu } from '../utils';
88
import type { TimeModel } from '@/interfaces';
99
import type { VueWrapper } from '@vue/test-utils';
10+
import type { AllPropsType } from '@/props';
1011

1112
describe('It should validate various picker scenarios', () => {
1213
it('Should dynamically disable times', async () => {
@@ -53,8 +54,7 @@ describe('It should validate various picker scenarios', () => {
5354

5455
const year = getYear(date);
5556

56-
const month = new Intl.DateTimeFormat('en-Us', { month: 'short', timeZone: 'UTC' }).format(date);
57-
const monthName = month.charAt(0).toUpperCase() + month.substring(1);
57+
const monthName = getMonthName(date);
5858

5959
await dp.find(`[data-test="${monthName}"]`).trigger('click');
6060
await dp.find(`[data-test="${year}"]`).trigger('click');
@@ -213,4 +213,39 @@ describe('It should validate various picker scenarios', () => {
213213

214214
await validate(startTimes, dpRange);
215215
});
216+
217+
it('Should correctly display months in multi-calendars based on the given range', async () => {
218+
const today = new Date();
219+
const sameViewRange = [today, addMonths(today, 1)];
220+
const diffViewRange = [today, addMonths(today, 3)];
221+
222+
const dp = await openMenu({ modelValue: sameViewRange, multiCalendars: true, range: true });
223+
224+
const validateMonthAndYearValues = (index: number, date: Date) => {
225+
const month = dp.find(`[data-test="month-toggle-overlay-${index}"]`);
226+
const year = dp.find(`[data-test="year-toggle-overlay-${index}"]`);
227+
expect(month.text()).toEqual(getMonthName(date));
228+
expect(+year.text()).toEqual(getYear(date));
229+
};
230+
231+
const reOpenMenu = async (newProps: Partial<AllPropsType>) => {
232+
dp.vm.closeMenu();
233+
await dp.setProps(newProps);
234+
await dp.vm.$nextTick();
235+
dp.vm.openMenu();
236+
await dp.vm.$nextTick();
237+
};
238+
239+
validateMonthAndYearValues(0, sameViewRange[0]);
240+
validateMonthAndYearValues(1, sameViewRange[1]);
241+
242+
await reOpenMenu({ modelValue: diffViewRange });
243+
244+
validateMonthAndYearValues(0, diffViewRange[1]);
245+
246+
await reOpenMenu({ modelValue: diffViewRange, multiCalendars: { solo: true } });
247+
248+
validateMonthAndYearValues(0, diffViewRange[0]);
249+
validateMonthAndYearValues(1, diffViewRange[1]);
250+
});
216251
});

tests/utils.ts

+5
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ export const openMenu = async (props: Partial<AllPropsType>) => {
1313
await dp.vm.$nextTick();
1414
return dp;
1515
};
16+
17+
export const getMonthName = (date: Date) => {
18+
const month = new Intl.DateTimeFormat('en-Us', { month: 'short', timeZone: 'UTC' }).format(date);
19+
return month.charAt(0).toUpperCase() + month.substring(1);
20+
};

0 commit comments

Comments
 (0)