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

Commit 58242fe

Browse files
committed
feat: Range enhancements (resolves #93)
Props added: - minRange & maxRange - fixedStart & fixedEnd
1 parent 14baa05 commit 58242fe

File tree

5 files changed

+48
-2
lines changed

5 files changed

+48
-2
lines changed

index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ interface Vue3DatePicker {
184184
presetRanges?: { label: string; range: Date[] | string[] }[];
185185
flow?: ('month' | 'year' | 'calendar' | 'time' | 'minutes' | 'hours' | 'seconds')[];
186186
preventMinMaxNavigation?: boolean;
187+
minRange?: number | string;
188+
maxRange?: number | string;
189+
fixedStart?: boolean;
190+
fixedEnd?: boolean;
187191
}
188192

189193
interface PublicMethods extends MethodOptions {

src/Vue3DatePicker/Vue3DatePicker.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@
109109
presetRanges,
110110
flow,
111111
preventMinMaxNavigation,
112+
minRange,
113+
maxRange,
114+
fixedStart,
115+
fixedEnd,
112116
}"
113117
v-model:internalModelValue="internalModelValue"
114118
@close-picker="closeMenu"
@@ -276,6 +280,10 @@
276280
presetRanges: { type: Array as PropType<PresetRange[]>, default: () => [] },
277281
flow: { type: Array as PropType<Flow>, default: () => [] },
278282
preventMinMaxNavigation: { type: Boolean as PropType<boolean>, default: false },
283+
minRange: { type: [Number, String] as PropType<number | string>, default: null },
284+
maxRange: { type: [Number, String] as PropType<number | string>, default: null },
285+
fixedStart: { type: Boolean as PropType<boolean>, default: false },
286+
fixedEnd: { type: Boolean as PropType<boolean>, default: false },
279287
});
280288
const slots = useSlots();
281289
const isOpen = ref(false);

src/Vue3DatePicker/components/DatepickerMenu.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@
286286
presetRanges: { type: Array as PropType<PresetRange[]>, default: () => [] },
287287
flow: { type: Array as PropType<Flow>, default: () => [] },
288288
preventMinMaxNavigation: { type: Boolean as PropType<boolean>, default: false },
289+
minRange: { type: [Number, String] as PropType<number | string>, default: null },
290+
maxRange: { type: [Number, String] as PropType<number | string>, default: null },
291+
fixedStart: { type: Boolean as PropType<boolean>, default: false },
292+
fixedEnd: { type: Boolean as PropType<boolean>, default: false },
289293
});
290294
const slots = useSlots();
291295
const calendarWrapperRef = ref(null);

src/Vue3DatePicker/components/composition/calendar.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
add,
44
addDays,
55
addMonths,
6+
differenceInDays,
67
getDay,
78
getHours,
89
getISOWeek,
@@ -374,6 +375,29 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit, updateFlow: () =>
374375
}
375376
};
376377

378+
const checkMinMaxRange = (secondDate: Date): boolean => {
379+
if (Array.isArray(modelValue.value) && modelValue.value[0]) {
380+
const diff = Math.abs(differenceInDays(modelValue.value[0], secondDate));
381+
if (props.minRange && props.maxRange) return diff >= +props.minRange && diff <= +props.maxRange;
382+
if (props.minRange) return diff >= +props.minRange;
383+
if (props.maxRange) return diff <= +props.maxRange;
384+
}
385+
return true;
386+
};
387+
388+
const getRangeWithFixedDate = (date: Date): Date[] => {
389+
if (Array.isArray(modelValue.value) && modelValue.value.length === 2) {
390+
if (props.fixedStart && isDateAfter(date, modelValue.value[0])) {
391+
return [modelValue.value[0], date];
392+
}
393+
if (props.fixedEnd && isDateBefore(date, modelValue.value[1])) {
394+
return [date, modelValue.value[1]];
395+
}
396+
return modelValue.value;
397+
}
398+
return [];
399+
};
400+
377401
/**
378402
* Called when the date in the calendar is clicked
379403
* Do a necessary formatting and assign value to internal
@@ -398,18 +422,20 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit, updateFlow: () =>
398422
}
399423
} else if (isNumberArray(hours.value) && isNumberArray(minutes.value) && !props.multiDates) {
400424
let rangeDate = modelValue.value ? (modelValue.value as Date[]).slice() : [];
401-
if (rangeDate.length === 2) {
425+
if (rangeDate.length === 2 && !(props.fixedStart || props.fixedEnd)) {
402426
rangeDate = [];
403427
}
404428
if (props.autoRange) {
405429
if (isNext) {
406430
handleNextCalendarAutoRange(day.value);
407431
}
408432
rangeDate = [new Date(day.value), addDays(new Date(day.value), +props.autoRange)];
433+
} else if (props.fixedStart || props.fixedEnd) {
434+
rangeDate = getRangeWithFixedDate(new Date(day.value));
409435
} else {
410436
if (!rangeDate[0]) {
411437
rangeDate[0] = new Date(day.value);
412-
} else {
438+
} else if (checkMinMaxRange(new Date(day.value))) {
413439
if (isDateBefore(new Date(day.value), new Date(rangeDate[0]))) {
414440
rangeDate.unshift(new Date(day.value));
415441
} else {

src/Vue3DatePicker/interfaces.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ export type UseCalendar = {
8787
enableSeconds: boolean;
8888
monthChangeOnArrows: boolean;
8989
multiDates: boolean;
90+
minRange: number | string;
91+
maxRange: number | string;
92+
fixedStart: boolean;
93+
fixedEnd: boolean;
9094
} & { [key: string]: unknown };
9195

9296
export interface UseMonthYearPick {

0 commit comments

Comments
 (0)