Skip to content
This repository was archived by the owner on Apr 17, 2022. It is now read-only.

Commit c6e1ae6

Browse files
committed
feat: Two calendars with independent behaviour option
- Improvements in range marking - Spacing between calendars - Prevent marking offset dates when two calendars are enabled
1 parent dc558a8 commit c6e1ae6

File tree

9 files changed

+99
-19
lines changed

9 files changed

+99
-19
lines changed

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface Vue3DatePicker {
99
enableTimePicker?: boolean;
1010
range?: boolean;
1111
twoCalendars?: boolean;
12+
twoCalendarsSolo?: boolean;
1213
modelValue?:
1314
| Date
1415
| Date[]

src/Vue3DatePicker/Vue3DatePicker.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
noToday,
7878
noHoursOverlay,
7979
noMinutesOverlay,
80+
twoCalendarsSolo,
8081
}"
8182
v-model:internalModelValue="internalModelValue"
8283
@closePicker="closeMenu"
@@ -126,6 +127,7 @@
126127
locale: { type: String as PropType<string>, default: 'en-US' },
127128
range: { type: Boolean as PropType<boolean>, default: false },
128129
twoCalendars: { type: Boolean as PropType<boolean>, default: false },
130+
twoCalendarsSolo: { type: Boolean as PropType<boolean>, default: false },
129131
modelValue: { type: [String, Date, Array, Object] as PropType<ModelValue>, default: null },
130132
position: { type: String as PropType<OpenPosition>, default: OpenPosition.center },
131133
placeholder: { type: String as PropType<string>, default: null },

src/Vue3DatePicker/components/Calendar.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="dp__calendar">
2+
<div :class="calendarParentClass">
33
<div :class="contentWrapClass">
44
<component
55
:is="monthYearComponent ? monthYearComponent : MonthYearInput"
@@ -13,6 +13,7 @@
1313
year,
1414
customProps,
1515
twoCalendars,
16+
twoCalendarsSolo,
1617
instance,
1718
}"
1819
@update:month="$emit('update:month', $event)"
@@ -134,6 +135,7 @@
134135
year: { type: Number as PropType<number>, default: 0 },
135136
noHoursOverlay: { type: Boolean as PropType<boolean>, default: false },
136137
noMinutesOverlay: { type: Boolean as PropType<boolean>, default: false },
138+
twoCalendarsSolo: { type: Boolean as PropType<boolean>, default: false },
137139
});
138140
const slots = useSlots();
139141
@@ -154,6 +156,11 @@
154156
}),
155157
);
156158
159+
const calendarParentClass = computed(() => ({
160+
dp__calendar: true,
161+
dp__calendar_next: props.instance === 2,
162+
}));
163+
157164
// Wrapper class for the wrapper div
158165
const contentWrapClass = computed(
159166
(): DynamicClass => ({

src/Vue3DatePicker/components/DatepickerMenu.vue

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
yearRange: { type: Array as PropType<number[]>, default: () => [1970, 2100] },
110110
range: { type: Boolean as PropType<boolean>, default: false },
111111
twoCalendars: { type: Boolean as PropType<boolean>, default: false },
112+
twoCalendarsSolo: { type: Boolean as PropType<boolean>, default: false },
112113
calendarCellClassName: { type: String as PropType<string>, default: null },
113114
enableTimePicker: { type: Boolean as PropType<boolean>, default: false },
114115
is24: { type: Boolean as PropType<boolean>, default: true },
@@ -262,6 +263,7 @@
262263
years: years.value,
263264
noHoursOverlay: props.noHoursOverlay,
264265
noMinutesOverlay: props.noMinutesOverlay,
266+
twoCalendarsSolo: props.twoCalendarsSolo,
265267
}));
266268
267269
const dpMenuClass = computed(
@@ -281,11 +283,17 @@
281283
calendarDay.classData = {
282284
dp__cell_offset: !calendarDay.current,
283285
dp__pointer: !disabled && !(!calendarDay.current && props.hideOffsetDates),
284-
dp__active_date: isActiveDate(calendarDay),
286+
dp__active_date: props.range ? false : isActiveDate(calendarDay),
285287
dp__date_hover:
286-
!disabled && !isActiveDate(calendarDay) && !(!calendarDay.current && props.hideOffsetDates),
288+
!disabled &&
289+
!isActiveDate(calendarDay) &&
290+
!(!calendarDay.current && props.hideOffsetDates) &&
291+
(props.range
292+
? !rangeActiveStartEnd(calendarDay) && !rangeActiveStartEnd(calendarDay, false)
293+
: true),
287294
dp__range_between:
288295
props.range &&
296+
(props.twoCalendars ? calendarDay.current : true) &&
289297
!disabled &&
290298
!(!calendarDay.current && props.hideOffsetDates) &&
291299
!isActiveDate(calendarDay)
@@ -296,8 +304,12 @@
296304
dp__cell_auto_range: isAutoRangeInBetween(calendarDay),
297305
dp__cell_auto_range_start: isAutoRangeStart(calendarDay),
298306
dp__cell_auto_range_end: isHoverRangeEnd(calendarDay),
299-
dp__range_start: rangeActiveStartEnd(calendarDay),
300-
dp__range_end: rangeActiveStartEnd(calendarDay, false),
307+
dp__range_start: props.twoCalendars
308+
? calendarDay.current && rangeActiveStartEnd(calendarDay)
309+
: rangeActiveStartEnd(calendarDay),
310+
dp__range_end: props.twoCalendars
311+
? calendarDay.current && rangeActiveStartEnd(calendarDay, false)
312+
: rangeActiveStartEnd(calendarDay, false),
301313
[props.calendarCellClassName]: !!props.calendarCellClassName,
302314
};
303315
return calendarDay;

src/Vue3DatePicker/components/MonthYearInput.vue

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class="dp__month_year_row">
33
<template v-if="!monthPicker">
4-
<div class="dp__month_year_col_nav" @click="onPrev">
4+
<div class="dp__month_year_col_nav" @click="onPrev" v-if="showLeftIcon">
55
<div class="dp__inner_nav">
66
<slot name="arrow-left" v-if="$slots['arrow-left']" />
77
<ChevronLeftIcon v-if="!$slots['arrow-left']" />
@@ -47,7 +47,7 @@
4747
<slot name="year-overlay" :text="item.text" :value="item.value" />
4848
</template>
4949
</SelectionGrid>
50-
<div class="dp__month_year_col_nav" @click="onNext">
50+
<div class="dp__month_year_col_nav" @click="onNext" v-if="showRightIcon">
5151
<div class="dp__inner_nav">
5252
<slot name="arrow-right" v-if="$slots['arrow-right']" />
5353
<ChevronRightIcon v-if="!$slots['arrow-right']" />
@@ -126,6 +126,8 @@
126126
monthPicker: { type: Boolean as PropType<boolean>, default: false },
127127
instance: { type: Number as PropType<number>, default: 1 },
128128
customProps: { type: Object as PropType<Record<string, unknown>>, default: null },
129+
twoCalendars: { type: Boolean as PropType<boolean>, default: false },
130+
twoCalendarsSolo: { type: Boolean as PropType<boolean>, default: false },
129131
});
130132
131133
const showMonthPicker = ref(false);
@@ -165,6 +167,20 @@
165167
return getGroupedList(props.years);
166168
});
167169
170+
const showLeftIcon = computed(() => {
171+
if (props.twoCalendars) {
172+
return !props.twoCalendarsSolo ? props.instance === 1 : true;
173+
}
174+
return true;
175+
});
176+
177+
const showRightIcon = computed((): boolean => {
178+
if (props.twoCalendars) {
179+
return !props.twoCalendarsSolo ? props.instance === 2 : true;
180+
}
181+
return true;
182+
});
183+
168184
const toggleMonthPicker = (): void => {
169185
showMonthPicker.value = !showMonthPicker.value;
170186
};

src/Vue3DatePicker/components/composition/calendar.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
getDateMonth,
88
getDateYear,
99
getNextMonthYear,
10+
getNextYearMonth,
11+
getPreviousMonthYear,
1012
getWeekNumber,
1113
isDateAfter,
1214
isDateBefore,
@@ -124,16 +126,7 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit): IUseCalendar =>
124126
if (!props.range) {
125127
return isDateEqual(calendarDay.value, modelValue.value ? (modelValue.value as Date) : today.value);
126128
}
127-
return (
128-
isDateEqual(
129-
calendarDay.value,
130-
isModelValueRange(modelValue.value) && modelValue.value[0] ? modelValue.value[0] : null,
131-
) ||
132-
isDateEqual(
133-
calendarDay.value,
134-
isModelValueRange(modelValue.value) && modelValue.value[1] ? modelValue.value[1] : null,
135-
)
136-
);
129+
return false;
137130
};
138131

139132
/**
@@ -328,24 +321,48 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit): IUseCalendar =>
328321
const handleNextMonthYear = (): void => {
329322
if (Array.isArray(modelValue.value) && modelValue.value.length === 2) {
330323
const date = new Date(modelValue.value[1]);
331-
if (getDateMonth(modelValue.value[0]) !== getDateMonth(modelValue.value[1])) {
324+
if ((monthNext.value === month.value && yearNext.value === year.value) || !props.twoCalendarsSolo) {
325+
const date = getNextYearMonth(month.value, year.value);
326+
monthNext.value = date.month;
327+
yearNext.value = date.year;
328+
} else {
332329
monthNext.value = getDateMonth(date);
333330
yearNext.value = getDateYear(date);
334331
}
335332
}
336333
};
337334

335+
const handlePreviousCalendarChange = (monthVal: number, yearVal: number): void => {
336+
if (!props.twoCalendarsSolo) {
337+
const date = getPreviousMonthYear(monthVal, yearVal);
338+
month.value = date.month;
339+
year.value = date.year;
340+
}
341+
};
342+
343+
const handleNextCalendarChange = (monthVal: number, yearVal: number): void => {
344+
if (!props.twoCalendarsSolo) {
345+
const date = getNextYearMonth(monthVal, yearVal);
346+
monthNext.value = date.month;
347+
yearNext.value = date.year;
348+
}
349+
};
350+
338351
const updateMonthYear = (value: number, isMonth = true, isNext = false): void => {
339352
if (isMonth) {
340353
if (isNext) {
354+
handlePreviousCalendarChange(value, yearNext.value);
341355
monthNext.value = value;
342356
} else {
357+
handleNextCalendarChange(value, year.value);
343358
month.value = value;
344359
}
345360
} else {
346361
if (isNext) {
362+
handlePreviousCalendarChange(monthNext.value, value);
347363
yearNext.value = value;
348364
} else {
365+
handleNextCalendarChange(month.value, value);
349366
year.value = value;
350367
}
351368
}
@@ -401,6 +418,15 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit): IUseCalendar =>
401418
if (props.range && isRange(modelValue.value)) {
402419
if (props.hideOffsetDates && !day.current) return false;
403420
return isDateEqual(new Date(day.value), modelValue.value[isStart ? 0 : 1]);
421+
} else if (props.range) {
422+
return isDateEqual(
423+
new Date(day.value),
424+
modelValue.value && Array.isArray(modelValue.value)
425+
? isStart
426+
? modelValue.value[0] || null
427+
: modelValue.value[1]
428+
: null,
429+
);
404430
}
405431
return false;
406432
};

src/Vue3DatePicker/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export type UseCalendar = {
9292
timePicker: boolean;
9393
hideOffsetDates: boolean;
9494
twoCalendars: boolean;
95+
twoCalendarsSolo: boolean;
9596
autoRange: number | string;
9697
} & { [key: string]: any };
9798

src/Vue3DatePicker/style/components/_Calendar.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,8 @@
159159
width: 100%;
160160
height: 1px;
161161
background: var(--dp-border-color);
162-
}
162+
}
163+
164+
.dp__calendar_next {
165+
margin-left: 10px;
166+
}

src/Vue3DatePicker/utils/date-utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import addHours from 'date-fns/addHours';
2222
import subHours from 'date-fns/subHours';
2323
import addMinutes from 'date-fns/addMinutes';
2424
import subMinutes from 'date-fns/subMinutes';
25+
import subMonths from 'date-fns/subMonths';
2526

2627
import { IMonthValue, ITimeValue } from '../interfaces';
2728

@@ -260,3 +261,13 @@ export const addDateMinutes = (minutes: number, toAdd: number): number => {
260261
export const subDateMinutes = (minutes: number, toSub: number): number => {
261262
return getMinutes(subMinutes(setMinutes(new Date(), minutes), toSub));
262263
};
264+
265+
export const getPreviousMonthYear = (month: number, year: number): { month: number; year: number } => {
266+
const date = subMonths(setYear(setMonth(new Date(), month), year), 1);
267+
return { month: getMonth(date), year: getYear(date) };
268+
};
269+
270+
export const getNextYearMonth = (month: number, year: number): { month: number; year: number } => {
271+
const date = addMonths(setYear(setMonth(new Date(), month), year), 1);
272+
return { month: getMonth(date), year: getYear(date) };
273+
};

0 commit comments

Comments
 (0)