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

Commit b4a3b80

Browse files
committed
feat: Add support for preset ranges (resolves #86)
1 parent 2a2408a commit b4a3b80

File tree

6 files changed

+125
-78
lines changed

6 files changed

+125
-78
lines changed

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ interface Vue3DatePicker {
180180
formatLocale?: Locale;
181181
autocomplete?: string;
182182
multiDates?: boolean;
183+
presetRanges?: { label: string; range: Date[] | string[] }[];
183184
}
184185

185186
interface PublicMethods extends MethodOptions {

src/Vue3DatePicker/Vue3DatePicker.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
disabled,
107107
readonly,
108108
multiDates,
109+
presetRanges,
109110
}"
110111
v-model:internalModelValue="internalModelValue"
111112
@close-picker="closeMenu"
@@ -154,6 +155,7 @@
154155
ITransition,
155156
IDisableDates,
156157
AltPosition,
158+
PresetRange,
157159
} from './interfaces';
158160
import { getDefaultPattern, isValidTime } from './utils/date-utils';
159161
import { getDefaultTextInputOptions, getDefaultFilters, mergeDefaultTransitions } from './utils/util';
@@ -266,6 +268,7 @@
266268
formatLocale: { type: Object as PropType<Locale>, default: null },
267269
autocomplete: { type: String as PropType<string>, default: null },
268270
multiDates: { type: Boolean as PropType<boolean>, default: false },
271+
presetRanges: { type: Array as PropType<PresetRange[]>, default: () => [] },
269272
});
270273
const slots = useSlots();
271274
const isOpen = ref(false);

src/Vue3DatePicker/components/DatepickerMenu.vue

Lines changed: 93 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -15,98 +15,110 @@
1515
>
1616
<div :class="disabledReadonlyOverlay" v-if="(disabled || readonly) && inline"></div>
1717
<div :class="arrowClass" v-if="!inline"></div>
18-
<div class="dp__instance_calendar" ref="calendarWrapperRef" role="document">
19-
<div :class="menuCalendarClassWrapper">
20-
<div v-for="instance in calendarAmm" :key="instance" :class="calendarInstanceClassWrapper">
18+
<div :class="presetRanges.length ? 'dp__menu_content_wrapper' : null">
19+
<div class="dp__preset_ranges" v-if="presetRanges.length">
20+
<div
21+
v-for="(preset, i) in presetRanges"
22+
:key="i"
23+
class="dp__preset_range"
24+
@click="presetDateRange(preset.range)"
25+
>
26+
{{ preset.label }}
27+
</div>
28+
</div>
29+
<div class="dp__instance_calendar" ref="calendarWrapperRef" role="document">
30+
<div :class="menuCalendarClassWrapper">
31+
<div v-for="instance in calendarAmm" :key="instance" :class="calendarInstanceClassWrapper">
32+
<component
33+
:is="monthYearComponent ? monthYearComponent : MonthYearInput"
34+
v-if="!disableMonthYearSelect && !timePicker"
35+
v-bind="{
36+
months,
37+
years,
38+
filters,
39+
monthPicker,
40+
month: month(instance),
41+
year: year(instance),
42+
customProps,
43+
multiCalendars,
44+
multiCalendarsSolo,
45+
instance,
46+
minDate,
47+
maxDate,
48+
}"
49+
@update:month="updateMonthYear(instance, $event, true)"
50+
@update:year="updateMonthYear(instance, $event, false)"
51+
@month-year-select="monthYearSelect"
52+
>
53+
<template v-for="(slot, i) in monthYearSlots" #[slot]="args" :key="i">
54+
<slot :name="slot" v-bind="args" />
55+
</template>
56+
</component>
57+
<Calendar
58+
v-bind="calendarProps"
59+
:instance="instance"
60+
:mapped-dates="mappedDates(instance)"
61+
:month="month(instance)"
62+
:year="year(instance)"
63+
:month-year-component="monthYearComponent"
64+
@select-date="selectDate($event, !isFirstInstance(instance))"
65+
@set-hover-date="setHoverDate($event)"
66+
@handle-scroll="handleScroll($event, instance)"
67+
>
68+
<template v-for="(slot, i) in calendarSlots" #[slot]="args" :key="i">
69+
<slot :name="slot" v-bind="{ ...args }" />
70+
</template>
71+
</Calendar>
72+
</div>
73+
</div>
74+
<div>
2175
<component
22-
:is="monthYearComponent ? monthYearComponent : MonthYearInput"
23-
v-if="!disableMonthYearSelect && !timePicker"
76+
v-if="enableTimePicker && !monthPicker"
77+
:is="timePickerComponent ? timePickerComponent : TimePickerCmp"
78+
ref="timePickerRef"
2479
v-bind="{
25-
months,
26-
years,
80+
is24,
81+
hoursIncrement,
82+
minutesIncrement,
83+
hoursGridIncrement,
84+
secondsIncrement,
85+
minutesGridIncrement,
86+
secondsGridIncrement,
87+
noHoursOverlay,
88+
noMinutesOverlay,
89+
noSecondsOverlay,
90+
range,
2791
filters,
28-
monthPicker,
29-
month: month(instance),
30-
year: year(instance),
92+
timePicker,
93+
hours,
94+
minutes,
95+
seconds,
3196
customProps,
32-
multiCalendars,
33-
multiCalendarsSolo,
34-
instance,
35-
minDate,
36-
maxDate,
97+
enableSeconds,
3798
}"
38-
@update:month="updateMonthYear(instance, $event, true)"
39-
@update:year="updateMonthYear(instance, $event, false)"
40-
@month-year-select="monthYearSelect"
99+
@update:hours="updateTime($event)"
100+
@update:minutes="updateTime($event, false)"
101+
@update:seconds="updateTime($event, false, true)"
41102
>
42-
<template v-for="(slot, i) in monthYearSlots" #[slot]="args" :key="i">
103+
<template v-for="(slot, i) in timePickerSlots" #[slot]="args" :key="i">
43104
<slot :name="slot" v-bind="args" />
44105
</template>
45106
</component>
46-
<Calendar
47-
v-bind="calendarProps"
48-
:instance="instance"
49-
:mapped-dates="mappedDates(instance)"
50-
:month="month(instance)"
51-
:year="year(instance)"
52-
:month-year-component="monthYearComponent"
53-
@select-date="selectDate($event, !isFirstInstance(instance))"
54-
@set-hover-date="setHoverDate($event)"
55-
@handle-scroll="handleScroll($event, instance)"
56-
>
57-
<template v-for="(slot, i) in calendarSlots" #[slot]="args" :key="i">
58-
<slot :name="slot" v-bind="{ ...args }" />
59-
</template>
60-
</Calendar>
61107
</div>
62108
</div>
63-
<div>
64-
<component
65-
v-if="enableTimePicker && !monthPicker"
66-
:is="timePickerComponent ? timePickerComponent : TimePickerCmp"
67-
ref="timePickerRef"
68-
v-bind="{
69-
is24,
70-
hoursIncrement,
71-
minutesIncrement,
72-
hoursGridIncrement,
73-
secondsIncrement,
74-
minutesGridIncrement,
75-
secondsGridIncrement,
76-
noHoursOverlay,
77-
noMinutesOverlay,
78-
noSecondsOverlay,
79-
range,
80-
filters,
81-
timePicker,
82-
hours,
83-
minutes,
84-
seconds,
85-
customProps,
86-
enableSeconds,
87-
}"
88-
@update:hours="updateTime($event)"
89-
@update:minutes="updateTime($event, false)"
90-
@update:seconds="updateTime($event, false, true)"
109+
<div class="dp__now_wrap" v-if="showNowButton">
110+
<slot name="now-button" v-if="$slots['now-button']" :selectCurrentDate="selectCurrentDate" />
111+
<button
112+
v-if="!$slots['now-button']"
113+
type="button"
114+
role="button"
115+
class="dp__now_button"
116+
@click="selectCurrentDate"
91117
>
92-
<template v-for="(slot, i) in timePickerSlots" #[slot]="args" :key="i">
93-
<slot :name="slot" v-bind="args" />
94-
</template>
95-
</component>
118+
{{ nowButtonLabel }}
119+
</button>
96120
</div>
97121
</div>
98-
<div class="dp__now_wrap" v-if="showNowButton">
99-
<slot name="now-button" v-if="$slots['now-button']" :selectCurrentDate="selectCurrentDate" />
100-
<button
101-
v-if="!$slots['now-button']"
102-
type="button"
103-
role="button"
104-
class="dp__now_button"
105-
@click="selectCurrentDate"
106-
>
107-
{{ nowButtonLabel }}
108-
</button>
109-
</div>
110122
<component
111123
v-if="!autoApply"
112124
:is="actionRowComponent ? actionRowComponent : ActionRow"
@@ -167,6 +179,7 @@
167179
IMarker,
168180
InternalModuleValue,
169181
ITimeValue,
182+
PresetRange,
170183
WeekStartNum,
171184
WeekStartStr,
172185
} from '../interfaces';
@@ -251,6 +264,7 @@
251264
disabled: { type: Boolean as PropType<boolean>, default: false },
252265
readonly: { type: Boolean as PropType<boolean>, default: false },
253266
multiDates: { type: Boolean as PropType<boolean>, default: false },
267+
presetRanges: { type: Array as PropType<PresetRange[]>, default: () => [] },
254268
});
255269
const slots = useSlots();
256270
const calendarWrapperRef = ref(null);
@@ -307,6 +321,7 @@
307321
selectCurrentDate,
308322
isHoverDateStartEnd,
309323
isHoverDate,
324+
presetDateRange,
310325
} = useCalendar(props, emit);
311326
312327
const calendarSlots = mapSlots(slots, 'calendar');

src/Vue3DatePicker/components/composition/calendar.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ interface IUseCalendar {
4646
handleScroll: (event: WheelEvent, instance: number) => void;
4747
handleArrow: (arrow: 'left' | 'right', instance: number) => void;
4848
getMarker: (day: UnwrapRef<ICalendarDay>) => IMarker | undefined;
49+
presetDateRange: (dates: Date[] | string[]) => void;
4950
selectCurrentDate: () => void;
5051
today: Ref<Date>;
5152
month: ComputedRef<(instance: number) => number>;
@@ -696,6 +697,13 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit): IUseCalendar =>
696697
}
697698
};
698699

700+
const presetDateRange = (dates: Date[] | string[]): void => {
701+
modelValue.value = dates.map((date) => new Date(date));
702+
if (props.autoApply) {
703+
emit('selectDate');
704+
}
705+
};
706+
699707
return {
700708
today,
701709
hours,
@@ -723,5 +731,6 @@ export const useCalendar = (props: UseCalendar, emit: VueEmit): IUseCalendar =>
723731
selectCurrentDate,
724732
isHoverDate,
725733
isHoverDateStartEnd,
734+
presetDateRange,
726735
};
727736
};

src/Vue3DatePicker/interfaces.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,5 @@ export type IDisableDates = (date: Date) => boolean;
131131
export type ITimeType = 'hours' | 'minutes' | 'seconds';
132132

133133
export type AltPosition = boolean | ((el: HTMLElement | undefined) => { top: string; left: string; transform: string });
134+
135+
export type PresetRange = { label: string; range: Date[] | string[] };

src/Vue3DatePicker/style/components/_DatepickerMenu.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,20 @@
8686
cursor: pointer;
8787
background: transparent;
8888
}
89+
90+
.dp__preset_ranges {
91+
padding: 5px;
92+
border-right: 1px solid var(--dp-border-color);
93+
}
94+
95+
.dp__preset_range {
96+
padding: 5px;
97+
&:hover {
98+
background-color: var(--dp-hover-color);
99+
cursor: pointer;
100+
}
101+
}
102+
103+
.dp__menu_content_wrapper {
104+
display: flex;
105+
}

0 commit comments

Comments
 (0)